feat(aes): add round key

This commit is contained in:
Kristofers Solo 2025-11-11 09:54:04 +02:00
parent 4007a9a04d
commit 7e5162fb44
Signed by: kristoferssolo
GPG Key ID: 74FF8144483D82C8
7 changed files with 120 additions and 13 deletions

View File

@ -1,12 +1,19 @@
use cipher_core::BlockCipher; use crate::{
Block128,
block::Block32,
key::{Key, Subkey, Subkeys},
};
use cipher_core::{BlockCipher, CipherError};
use crate::key::Key; pub struct Aes {
subkeys: Subkeys,
pub struct Aes {} }
impl Aes { impl Aes {
pub fn new(_key: impl Into<Key>) -> Self { pub fn new(key: impl Into<Key>) -> Self {
todo!() Self {
subkeys: Subkeys::from_key(&key.into()),
}
} }
} }
@ -18,9 +25,46 @@ impl BlockCipher for Aes {
fn transform_impl( fn transform_impl(
&self, &self,
_block: &[u8], block: &[u8],
_action: cipher_core::CipherAction, action: cipher_core::CipherAction,
) -> cipher_core::CipherResult<cipher_core::Output> { ) -> 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()))?;
let block128 = Block128::from_be_bytes(block_arr);
let round_key = add_round_key(
*self.subkeys.first().unwrap(),
*block128.as_block32_array().first().unwrap(),
);
todo!() todo!()
} }
} }
fn add_round_key(subkey: Subkey, block: Block32) -> Block32 {
block ^ subkey
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
const TEST_MESSAGE: u128 = 0x0123_4567_89AB_CDEF_FEDC_BA98_7654_3210;
#[rstest]
#[case(0x0123_4567, 0x0F15_71C9, 0x0E36_34AE)]
#[case(0x89AB_CDEF, 0x47D9_E859, 0xCE72_25B6)]
#[case(0xFEDC_BA98, 0x1CB7_ADD6, 0xE26B_174E)]
#[case(0x7654_3210, 0xAF7F_6798, 0xD92B_5588)]
fn round_key(#[case] block: u32, #[case] subkey: u32, #[case] expected: u32) {
let block = Block32::new(block);
let subkey = Subkey::from_u32(subkey);
let result = add_round_key(subkey, block);
assert_eq!(result.as_u32(), expected);
}
}

View File

@ -1,4 +1,4 @@
use crate::block::secret_block; use crate::block::{Block32, secret_block};
use cipher_core::{BlockError, InputBlock}; use cipher_core::{BlockError, InputBlock};
use std::{ use std::{
slice::{from_raw_parts, from_raw_parts_mut}, slice::{from_raw_parts, from_raw_parts_mut},
@ -37,6 +37,18 @@ impl Block128 {
pub const fn to_le_bytes(self) -> [u8; 16] { pub const fn to_le_bytes(self) -> [u8; 16] {
self.0.to_le_bytes() self.0.to_le_bytes()
} }
#[inline]
#[must_use]
pub const fn as_block32_array(self) -> [Block32; 4] {
let val = self.0;
[
Block32::from_u32((val >> 96) as u32),
Block32::from_u32((val >> 64) as u32),
Block32::from_u32((val >> 32) as u32),
Block32::from_u32(val as u32),
]
}
} }
impl FromStr for Block128 { impl FromStr for Block128 {
@ -105,14 +117,20 @@ impl From<[u8; 16]> for Block128 {
} }
} }
impl From<Block128> for [Block32; 4] {
fn from(block: Block128) -> Self {
block.as_block32_array()
}
}
impl From<Block128> for Vec<u8> { impl From<Block128> for Vec<u8> {
fn from(value: Block128) -> Self { fn from(value: Block128) -> Self {
value.0.to_be_bytes().to_vec() value.to_be_bytes().to_vec()
} }
} }
impl From<&Block128> for Vec<u8> { impl From<&Block128> for Vec<u8> {
fn from(value: &Block128) -> Self { fn from(value: &Block128) -> Self {
value.0.to_be_bytes().to_vec() value.to_be_bytes().to_vec()
} }
} }

27
aes/src/block/block32.rs Normal file
View File

@ -0,0 +1,27 @@
use std::ops::BitXor;
use crate::{block::secret_block, key::Subkey};
secret_block! {
pub struct Block32(u32, 32, 0xFFFF_FFFF);
}
impl Block32 {
#[inline]
#[must_use]
pub const fn to_be_bytes(self) -> [u8; 4] {
self.0.to_be_bytes()
}
#[inline]
#[must_use]
pub const fn to_le_bytes(self) -> [u8; 4] {
self.0.to_le_bytes()
}
}
impl BitXor<Subkey> for Block32 {
type Output = Self;
fn bitxor(self, rhs: Subkey) -> Self::Output {
Self(self.0 ^ rhs.as_u32())
}
}

View File

@ -1,5 +1,6 @@
mod block128; mod block128;
mod block32;
mod secret_block; mod secret_block;
use crate::secret_block; use crate::secret_block;
pub use block128::Block128; pub use {block32::Block32, block128::Block128};

View File

@ -5,4 +5,4 @@ mod subkey;
mod subkeys; mod subkeys;
use crate::secret_key; use crate::secret_key;
pub use aes_key::Key; pub use {aes_key::Key, subkey::Subkey, subkeys::Subkeys};

View File

@ -27,6 +27,18 @@ impl Subkey {
pub const fn rotate_right(self, n: u32) -> Self { pub const fn rotate_right(self, n: u32) -> Self {
Self(self.0.rotate_right(n)) Self(self.0.rotate_right(n))
} }
#[inline]
#[must_use]
pub const fn to_be_bytes(self) -> [u8; 4] {
self.0.to_be_bytes()
}
#[inline]
#[must_use]
pub const fn to_le_bytes(self) -> [u8; 4] {
self.0.to_le_bytes()
}
} }
impl BitXor<ExpandedKey> for Subkey { impl BitXor<ExpandedKey> for Subkey {

View File

@ -51,6 +51,11 @@ impl Subkeys {
pub fn iter_mut(&mut self) -> IterMut<'_, Subkey> { pub fn iter_mut(&mut self) -> IterMut<'_, Subkey> {
self.0.iter_mut() self.0.iter_mut()
} }
/// Returns the first element of the slice, or `None` if it is empty.
pub fn first(&self) -> Option<&Subkey> {
self.0.first()
}
} }
impl<'a> IntoIterator for &'a Subkeys { impl<'a> IntoIterator for &'a Subkeys {