refactor(key): improve secret_int! macro

This commit is contained in:
2025-10-17 20:35:40 +03:00
parent 2d59f4fb70
commit db52714d52
13 changed files with 221 additions and 232 deletions

View File

@@ -3,97 +3,26 @@ use thiserror::Error;
#[derive(Debug, Error, Clone, Copy, PartialEq, Eq)]
pub enum CipherError {
/// Invalid key size for the cipher
#[error("invalid key size: expected {expected} bytes, got {actual}")]
#[error("Invalid key size: expected {expected} bytes, got {actual}")]
InvalidKeySize { expected: usize, actual: usize },
/// Input data doesn't match the cipher's block size
#[error("invalid block size: expected {expected} bytes, got {actual}")]
#[error("Invalid block size: expected {expected} bytes, got {actual}")]
InvalidBlockSize { expected: usize, actual: usize },
/// Decryption detected invalid padding
#[error("invalid padding detected during decryption")]
InvalidPadding,
/// Input length not valid for unpadded operation
#[error("invalid plaintext length: {actual} bytes (must be multiple of block size)")]
InvalidPlaintextLength { actual: usize },
/// General size validation failure
#[error("size mismatch: expected {expected} bytes, got {actual}")]
InvalidSize { expected: usize, actual: usize },
}
impl CipherError {
/// Creates a key size error
#[inline]
#[must_use]
pub const fn invalid_key_size(expected: usize, actual: usize) -> Self {
Self::InvalidKeySize { expected, actual }
}
/// Creates a block size error
#[inline]
#[must_use]
pub const fn invalid_block_size(expected: usize, actual: usize) -> Self {
Self::InvalidBlockSize { expected, actual }
}
/// Creates an invalid padding error
#[inline]
#[must_use]
pub const fn invalid_padding() -> Self {
Self::InvalidPadding
}
/// Creates a plaintext length error
#[inline]
#[must_use]
pub const fn invalid_plaintext_length(actual: usize) -> Self {
Self::InvalidPlaintextLength { actual }
}
/// Returns true if this is a key size error
#[inline]
#[must_use]
pub const fn is_key_error(&self) -> bool {
matches!(self, Self::InvalidKeySize { .. })
}
/// Returns true if this is a block size error
#[inline]
#[must_use]
pub const fn is_block_error(&self) -> bool {
matches!(self, Self::InvalidBlockSize { .. })
}
/// Returns true if this is a size-related error
#[must_use]
pub const fn is_size_error(&self) -> bool {
self.is_key_error() || self.is_block_error() || matches!(self, Self::InvalidSize { .. })
}
/// Returns the expected size for size-related errors
#[must_use]
pub const fn expected_size(&self) -> Option<usize> {
match self {
Self::InvalidKeySize { expected, .. }
| Self::InvalidBlockSize { expected, .. }
| Self::InvalidSize { expected, .. } => Some(*expected),
_ => None,
}
}
/// Returns the actual size for size-related errors
#[must_use]
pub const fn actual_size(&self) -> Option<usize> {
match self {
Self::InvalidKeySize { actual, .. }
| Self::InvalidBlockSize { actual, .. }
| Self::InvalidSize { actual, .. }
| Self::InvalidPlaintextLength { actual } => Some(*actual),
Self::InvalidPadding => None,
}
}
}
/// Type alias for clean Result types

View File

@@ -1,10 +1,28 @@
use crate::{CipherAction, CipherError, CipherResult};
/// Generic block cipher trait.
///
/// Implements the standard encrypt/decrypt interface for block ciphers.
/// Implementers define `transform_impl` to handle the core algorithm,
/// while `transform` provides validation and convenience wrappers.
pub trait BlockCipher: Sized {
const BLOCK_SIZE: usize;
/// Core cipher transformation (must be implemented by concrete types).
///
/// # Errors
///
/// Returns `CipherError` if the transformation fails.
fn transform_impl(&self, block: &[u8], action: CipherAction) -> CipherResult<Vec<u8>>;
/// Transforms a block with validation.
///
/// Validates that the block size matches `BLOCK_SIZE` before delegating
/// to `transform_impl`.
///
/// # Errors
///
/// Returns `CipherError::InvalidBlockSize` if `block.len() != BLOCK_SIZE`.
fn transform(&self, block: &[u8], action: CipherAction) -> CipherResult<Vec<u8>> {
if block.len() != Self::BLOCK_SIZE {
return Err(CipherError::invalid_block_size(
@@ -15,9 +33,20 @@ pub trait BlockCipher: Sized {
self.transform_impl(block, action)
}
/// Encrypts a single block.
///
/// # Errors
///
/// Returns `CipherError::InvalidBlockSize` if the plaintext is not exactly `BLOCK_SIZE` bytes.
fn encrypt(&self, plaintext: &[u8]) -> CipherResult<Vec<u8>> {
self.transform(plaintext, CipherAction::Encrypt)
}
/// Decrypts a single block.
///
/// # Errors
///
/// Returns `CipherError::InvalidBlockSize` if the plaintext is not exactly `BLOCK_SIZE` bytes.
fn decrypt(&self, ciphertext: &[u8]) -> CipherResult<Vec<u8>> {
self.transform(ciphertext, CipherAction::Decrypt)
}