From 14ccb2288d723b66b79aa94a2a1064711099044e Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 17 Oct 2025 20:46:04 +0300 Subject: [PATCH] feat(block): add secret_block! macro --- des/src/block/block32.rs | 31 +-------- des/src/block/block48.rs | 27 ++------ des/src/block/block6.rs | 21 ++---- des/src/block/block64.rs | 25 ++----- des/src/block/mod.rs | 2 + des/src/block/secret_block.rs | 126 ++++++++++++++++++++++++++++++++++ des/src/key/secret_key.rs | 2 +- 7 files changed, 145 insertions(+), 89 deletions(-) create mode 100644 des/src/block/secret_block.rs diff --git a/des/src/block/block32.rs b/des/src/block/block32.rs index d68f01d..8e3501f 100644 --- a/des/src/block/block32.rs +++ b/des/src/block/block32.rs @@ -1,34 +1,9 @@ use std::ops::BitXor; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Block32(u32); +use crate::secret_block; -impl Block32 { - const MASK: u32 = 0xFFFF_FFFF; - - #[inline] - #[must_use] - pub const fn new(value: u32) -> Self { - Self(value) - } - - #[inline] - #[must_use] - pub const fn as_u32(self) -> u32 { - self.0 - } - - #[inline] - #[must_use] - pub const fn as_u64(self) -> u64 { - self.0 as u64 - } -} - -impl From for Block32 { - fn from(value: u32) -> Self { - Self(value) - } +secret_block! { + pub struct Block32(u32, 32, 0xFFFF_FFFF); } impl From for Block32 { diff --git a/des/src/block/block48.rs b/des/src/block/block48.rs index 47b909b..576232b 100644 --- a/des/src/block/block48.rs +++ b/des/src/block/block48.rs @@ -1,24 +1,11 @@ +use crate::{block::Block6, key::Subkey, secret_block}; use std::{array, ops::BitXor}; -use crate::{block::Block6, key::Subkey}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Block48(u64); +secret_block! { + pub struct Block48(u64, 48, 0xFFFF_FFFF_FFFF); +} impl Block48 { - const MASK: u64 = 0xFFFF_FFFF_FFFF; - #[inline] - #[must_use] - pub const fn new(value: u64) -> Self { - Self(value & Self::MASK) - } - - #[inline] - #[must_use] - pub const fn as_u64(self) -> u64 { - self.0 - } - #[must_use] pub fn as_block6_array(self) -> [Block6; 8] { array::from_fn(|idx| { @@ -29,12 +16,6 @@ impl Block48 { } } -impl From for Block48 { - fn from(value: u64) -> Self { - Self::new(value) - } -} - impl BitXor for Block48 { type Output = Self; fn bitxor(self, rhs: Self) -> Self::Output { diff --git a/des/src/block/block6.rs b/des/src/block/block6.rs index cf0797a..2c5fb0c 100644 --- a/des/src/block/block6.rs +++ b/des/src/block/block6.rs @@ -1,27 +1,16 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Block6(u8); +use crate::secret_block; + +secret_block! { + pub struct Block6(u8, 6, 0x3F); +} impl Block6 { - const MASK: u8 = 0x3F; - - #[inline] - #[must_use] - pub const fn new(value: u8) -> Self { - Self(value & Self::MASK) - } - #[inline] #[must_use] pub const fn zero() -> Self { Self(0) } - #[inline] - #[must_use] - pub const fn as_u8(self) -> u8 { - self.0 - } - #[inline] #[must_use] pub const fn to_row(self) -> usize { diff --git a/des/src/block/block64.rs b/des/src/block/block64.rs index 29edb7c..9da15d4 100644 --- a/des/src/block/block64.rs +++ b/des/src/block/block64.rs @@ -1,21 +1,10 @@ -use crate::block::lr::LR; +use crate::block::{lr::LR, secret_block}; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Block64(u64); +secret_block! { + pub struct Block64(u64, 64, 0xFFFF_FFFF_FFFF_FFFF); +} impl Block64 { - #[inline] - #[must_use] - pub const fn new(value: u64) -> Self { - Self(value) - } - - #[inline] - #[must_use] - pub const fn as_u64(self) -> u64 { - self.0 - } - #[inline] #[must_use] pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { @@ -47,12 +36,6 @@ impl From<[u8; 8]> for Block64 { } } -impl From for Block64 { - fn from(value: u64) -> Self { - Self::new(value) - } -} - impl From for LR { fn from(block: Block64) -> Self { let left = (block.0 >> 32) as u32; diff --git a/des/src/block/mod.rs b/des/src/block/mod.rs index 0a64b52..d4672b0 100644 --- a/des/src/block/mod.rs +++ b/des/src/block/mod.rs @@ -3,5 +3,7 @@ mod block48; mod block6; mod block64; mod lr; +mod secret_block; +use crate::secret_block; pub use {block6::Block6, block32::Block32, block48::Block48, block64::Block64, lr::LR}; diff --git a/des/src/block/secret_block.rs b/des/src/block/secret_block.rs new file mode 100644 index 0000000..13ea19b --- /dev/null +++ b/des/src/block/secret_block.rs @@ -0,0 +1,126 @@ +/// Macro to generate a masked, zeroizable integer wrapper type. +/// +/// Usage: +/// ``` +/// secret_block! { +/// /// docs... +/// pub struct Block48(u64, 48, 0x0000_FFFF_FFFF_FFFFu64); +/// } +/// ``` +#[macro_export] +macro_rules! secret_block { + ( + $(#[$meta:meta])* + $vis:vis struct $name:ident ( $int:tt, $bits:expr, $mask:expr ); +) => { + $(#[$meta])* + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + $vis struct $name($int); + + impl $name { + /// Mask to restrict the underlying integer to valid bits. + pub const MASK: $int = $mask; + + #[inline] + #[must_use] + pub const fn new(value: $int) -> Self { + Self(value & Self::MASK) + } + + secret_block!(@conversions_as $int); + secret_block!(@conversions_from $int $int); + } + + impl From<$int> for $name { + fn from(v: $int) -> Self { + Self(v & Self::MASK) + } + } + }; + // Helper: generate conversions_as based on type + (@conversions_as u8) => { + /// Return value as u8 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u8(&self) -> u8 { + self.0 as u8 + } + + secret_block!(@conversions_as u16); + }; + (@conversions_as u16) => { + /// Return value as u16 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u16(&self) -> u16 { + self.0 as u16 + } + + secret_block!(@conversions_as u32); + }; + (@conversions_as u32) => { + /// Return value as u32 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u32(&self) -> u32 { + self.0 as u32 + } + + secret_block!(@conversions_as u64); + }; + (@conversions_as u64) => { + /// Return value as u64 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn as_u64(&self) -> u64 { + self.0 as u64 + } + }; + // Helper: generate conversions_from based on type + (@conversions_from u8 $int:tt) => { + /// Create value from u8 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u8(key: u8) -> Self { + Self(key as $int & Self::MASK) + } + }; + (@conversions_from u16 $int:tt) => { + /// Create value from u16 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u16(key: u16) -> Self { + Self(key as $int & Self::MASK) + } + + secret_block!(@conversions_from u8 $int); + }; + (@conversions_from u32 $int:tt) => { + /// Create value from u32 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u32(key: u32) -> Self { + Self(key as $int & Self::MASK) + } + + secret_block!(@conversions_from u16 $int); + }; + (@conversions_from u64 $int:tt) => { + /// Create value from u64 + #[allow(dead_code)] + #[inline] + #[must_use] + pub const fn from_u64(key: u64) -> Self { + Self(key & Self::MASK) + } + + secret_block!(@conversions_from u32 $int); + } +} diff --git a/des/src/key/secret_key.rs b/des/src/key/secret_key.rs index 319a545..1d5f4cb 100644 --- a/des/src/key/secret_key.rs +++ b/des/src/key/secret_key.rs @@ -15,7 +15,6 @@ macro_rules! secret_key { ) => { $(#[$meta])* #[derive(::zeroize::ZeroizeOnDrop, Default)] - #[zeroize(drop)] $vis struct $name($int); impl $name { @@ -81,6 +80,7 @@ macro_rules! secret_key { self.0 as u64 } }; + // Helper: generate conversions_from based on type (@conversions_from u8 $int:tt) => { /// Create value from u8 #[allow(dead_code)]