feat(aes): add substitute bytes

This commit is contained in:
Kristofers Solo 2025-11-13 10:35:50 +02:00
parent 7e5162fb44
commit b2c5209214
Signed by: kristoferssolo
GPG Key ID: 74FF8144483D82C8
7 changed files with 99 additions and 20 deletions

View File

@ -23,4 +23,4 @@ zeroize = { version = "1.8", features = ["derive"] }
[workspace.lints.clippy] [workspace.lints.clippy]
pedantic = "warn" pedantic = "warn"
nursery = "warn" nursery = "warn"
unwrap_used = "warn" # unwrap_used = "warn"

View File

@ -2,6 +2,7 @@ use crate::{
Block128, Block128,
block::Block32, block::Block32,
key::{Key, Subkey, Subkeys}, key::{Key, Subkey, Subkeys},
sbox::SboxLookup,
}; };
use cipher_core::{BlockCipher, CipherError}; use cipher_core::{BlockCipher, CipherError};
@ -34,18 +35,28 @@ impl BlockCipher for Aes {
let block128 = Block128::from_be_bytes(block_arr); let block128 = Block128::from_be_bytes(block_arr);
let round_key = add_round_key( let mut subkey_iter = self.subkeys.chunks();
*self.subkeys.first().unwrap(), dbg!(&subkey_iter.count());
*block128.as_block32_array().first().unwrap(),
); // let foo = *subkey_iter.next().unwrap();
// let round_key = add_round_key(
// *block128.as_block32_array().first().unwrap(),
// *subkey_iter.next().unwrap(),
// );
// for i in subkey_iter {}
todo!() todo!()
} }
} }
fn add_round_key(subkey: Subkey, block: Block32) -> Block32 { fn add_round_key(block: Block32, subkey: Subkey) -> Block32 {
block ^ subkey block ^ subkey
} }
fn substitute_bytes(block: Block128) -> Block128 {
block.sbox_lookup()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rstest::rstest; use rstest::rstest;
@ -63,8 +74,20 @@ mod tests {
let block = Block32::new(block); let block = Block32::new(block);
let subkey = Subkey::from_u32(subkey); let subkey = Subkey::from_u32(subkey);
let result = add_round_key(subkey, block); let result = add_round_key(block, subkey);
assert_eq!(result.as_u32(), expected); assert_eq!(result.as_u32(), expected);
} }
#[rstest]
#[case(
0x0E36_34AE_CE72_25B6_E26B_174E_D92B_5588,
0xAB05_18E4_8B40_3F4E_987F_F02F_35F1_FCC4
)]
fn byte_substitution(#[case] block: u128, #[case] expected: u128) {
let block = Block128::new(block);
let result = substitute_bytes(block);
assert_eq!(result.as_u128(), expected);
}
} }

View File

@ -1,7 +1,10 @@
use crate::block::{Block32, secret_block}; use crate::{
block::{Block32, secret_block},
sbox::SboxLookup,
};
use cipher_core::{BlockError, InputBlock}; use cipher_core::{BlockError, InputBlock};
use std::{ use std::{
slice::{from_raw_parts, from_raw_parts_mut}, slice::{ChunksExact, from_raw_parts, from_raw_parts_mut},
str::FromStr, str::FromStr,
}; };
@ -19,6 +22,12 @@ impl InputBlock for Block128 {
} }
} }
impl SboxLookup for Block128 {
fn sbox_lookup(self) -> Self {
Self(self.0.sbox_lookup())
}
}
impl Block128 { impl Block128 {
#[inline] #[inline]
#[must_use] #[must_use]
@ -40,6 +49,7 @@ impl Block128 {
#[inline] #[inline]
#[must_use] #[must_use]
#[allow(clippy::cast_possible_truncation)]
pub const fn as_block32_array(self) -> [Block32; 4] { pub const fn as_block32_array(self) -> [Block32; 4] {
let val = self.0; let val = self.0;
[ [

View File

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

View File

@ -1,12 +1,13 @@
use crate::{ use crate::{
constants::{RCON, S_BOXES}, constants::RCON,
key::{Key, expanded::ExpandedKey, subkey::Subkey}, key::{Key, expanded::ExpandedKey, subkey::Subkey},
sbox::SboxLookup,
}; };
use std::{ use std::{
fmt::Debug, fmt::Debug,
iter::Rev, iter::Rev,
ops::Index, ops::Index,
slice::{Iter, IterMut}, slice::{ChunksExact, Iter, IterMut},
}; };
const SUBKEY_COUNT: usize = 44; const SUBKEY_COUNT: usize = 44;
@ -53,9 +54,15 @@ impl Subkeys {
} }
/// Returns the first element of the slice, or `None` if it is empty. /// Returns the first element of the slice, or `None` if it is empty.
pub fn first(&self) -> Option<&Subkey> { pub const fn first(&self) -> Option<&Subkey> {
self.0.first() self.0.first()
} }
#[inline]
#[must_use]
pub fn chunks(&self) -> SubkeyChunks<'_> {
SubkeyChunks(self.0.chunks_exact(4))
}
} }
impl<'a> IntoIterator for &'a Subkeys { impl<'a> IntoIterator for &'a Subkeys {
@ -87,7 +94,18 @@ impl Debug for Subkeys {
} }
} }
const fn expand(subkey: Subkey, rcon: u32) -> ExpandedKey { pub struct SubkeyChunks<'a>(ChunksExact<'a, Subkey>);
impl<'a> Iterator for SubkeyChunks<'a> {
type Item = &'a [Subkey; 4];
fn next(&mut self) -> Option<Self::Item> {
self.0
.next()
.map(|chunk| <&[Subkey; 4]>::try_from(chunk).unwrap())
}
}
fn expand(subkey: Subkey, rcon: u32) -> ExpandedKey {
let word = subkey.rotate_left(8).as_u32(); let word = subkey.rotate_left(8).as_u32();
let b0 = sbox_lookup(word >> 24); let b0 = sbox_lookup(word >> 24);
@ -98,12 +116,8 @@ const fn expand(subkey: Subkey, rcon: u32) -> ExpandedKey {
ExpandedKey::from_u32(substituted ^ rcon) ExpandedKey::from_u32(substituted ^ rcon)
} }
const fn sbox_lookup(byte: u32) -> u32 { fn sbox_lookup<T: SboxLookup>(val: T) -> T {
const MASK: u32 = 0xFF; val.sbox_lookup()
let row = ((byte & MASK) as usize) >> 4;
let col = ((byte & MASK) as usize) & 0xF;
S_BOXES[row][col] as u32
} }
#[cfg(test)] #[cfg(test)]

View File

@ -2,6 +2,7 @@ mod aes;
mod block; mod block;
mod constants; mod constants;
mod key; mod key;
mod sbox;
mod utils; mod utils;
pub use {aes::Aes, block::Block128}; pub use {aes::Aes, block::Block128};

27
aes/src/sbox.rs Normal file
View File

@ -0,0 +1,27 @@
use crate::constants::S_BOXES;
pub trait SboxLookup: Sized {
fn sbox_lookup(self) -> Self;
}
macro_rules! impl_sbox_lookup {
($ty:ty, $bytes:expr) => {
impl SboxLookup for $ty {
fn sbox_lookup(self) -> Self {
(0..$bytes).fold(0, |acc, idx| {
let shift = ($bytes - 1 - idx) * 8;
let byte = ((self >> shift) & 0xFF) as u8;
let row = (byte >> 4) as usize;
let col = (byte & 0xF) as usize;
acc | Self::from(S_BOXES[row][col]) << shift
})
}
}
};
}
impl_sbox_lookup!(u8, 1);
impl_sbox_lookup!(u16, 2);
impl_sbox_lookup!(u32, 4);
impl_sbox_lookup!(u64, 8);
impl_sbox_lookup!(u128, 16);