refactor(des): use InputBlock trait

This commit is contained in:
2025-11-04 10:03:20 +02:00
parent 211a7cefe6
commit db53ae2ee7
16 changed files with 180 additions and 199 deletions

View File

@@ -1,9 +1,24 @@
use crate::block::{lr::LR, secret_block};
use cipher_core::{BlockError, InputBlock};
use std::{
slice::{from_raw_parts, from_raw_parts_mut},
str::FromStr,
};
secret_block! {
pub struct Block64(u64, 64, 0xFFFF_FFFF_FFFF_FFFF);
}
impl InputBlock for Block64 {
const BLOCK_SIZE: usize = 64;
fn as_bytes(&self) -> &[u8] {
unsafe { from_raw_parts((&raw const self.0).cast::<u64>().cast::<u8>(), 8) }
}
fn as_bytes_mut(&mut self) -> &mut [u8] {
unsafe { from_raw_parts_mut((&raw mut self.0).cast::<u64>().cast::<u8>(), 8) }
}
}
impl Block64 {
#[inline]
#[must_use]
@@ -30,6 +45,68 @@ impl Block64 {
}
}
impl FromStr for Block64 {
type Err = BlockError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(parse_string_to_u64(s)?))
}
}
fn parse_string_to_u64(s: &str) -> Result<u64, BlockError> {
let trimmed = s.trim();
if trimmed.is_empty() {
return Err(BlockError::EmptyBlock);
}
// Hexadecimal with 0x/0X prefix
if let Some(hex_str) = trimmed
.strip_prefix("0x")
.or_else(|| trimmed.strip_prefix("0X"))
{
return parse_radix(hex_str, 16);
}
// Binary with 0b/0B prefix
if let Some(bin_str) = trimmed
.strip_prefix("0b")
.or_else(|| trimmed.strip_prefix("0B"))
{
return parse_radix(bin_str, 2);
}
// 8-character ASCII string conversion to u64
if trimmed.len() > 8 {
return Err(BlockError::InvalidByteStringLength(trimmed.len()));
}
ascii_string_to_u64(trimmed)
}
fn parse_radix(s: &str, radix: u32) -> Result<u64, BlockError> {
let trimmed = s.trim_start_matches('0');
if trimmed.is_empty() {
return Ok(0);
}
u64::from_str_radix(trimmed, radix).map_err(BlockError::from)
}
fn ascii_string_to_u64(s: &str) -> Result<u64, BlockError> {
if !s.is_ascii() {
return Err(BlockError::conversion_error(
"u64",
"String contains non-ASCII characters",
));
}
let mut bytes = [0; 8];
for (idx, byte) in s.bytes().enumerate() {
bytes[idx] = byte;
}
Ok(u64::from_be_bytes(bytes))
}
impl From<[u8; 8]> for Block64 {
fn from(bytes: [u8; 8]) -> Self {
Self::from_be_bytes(bytes)

View File

@@ -45,7 +45,7 @@ impl BlockCipher for Des {
&self,
block: &[u8],
action: cipher_core::CipherAction,
) -> cipher_core::CipherResult<cipher_core::CipherOutput> {
) -> cipher_core::CipherResult<cipher_core::Output> {
let block_arr: [u8; Self::BLOCK_SIZE] = block
.try_into()
.map_err(|_| CipherError::invalid_block_size(Self::BLOCK_SIZE, block.len()))?;

View File

@@ -4,4 +4,4 @@ mod des;
mod key;
pub(crate) mod utils;
pub use des::Des;
pub use {block::Block64, des::Des};

View File

@@ -1,4 +1,4 @@
use cipher_core::{BlockCipher, CipherOutput};
use cipher_core::{BlockCipher, Output};
use claims::assert_ok;
use des::Des;
use rstest::rstest;
@@ -192,7 +192,7 @@ fn different_inputs() {
);
}
fn cipher_block_to_u64(block: CipherOutput) -> u64 {
fn cipher_block_to_u64(block: Output) -> u64 {
let bytes = block.as_slice().try_into().expect("8 bytes");
u64::from_be_bytes(bytes)
}