use crate::cryptography::aes::{
bite_sub::SBOX, key::expand_key, mix_column::mix_columns_state, shift_rows::shift_rows_state,
};
use std::sync::OnceLock;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct U256 {
pub data: [u64; 4],
}
impl U256 {
pub const fn new(data: [u64; 4]) -> Self {
Self { data }
}
pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
let mut data = [0u64; 4];
for (index, chunk) in bytes.chunks_exact(8).enumerate() {
let mut word = [0u8; 8];
word.copy_from_slice(chunk);
data[index] = u64::from_be_bytes(word);
}
Self { data }
}
pub fn to_be_bytes(self) -> [u8; 32] {
let mut bytes = [0u8; 32];
for (index, word) in self.data.iter().enumerate() {
bytes[index * 8..(index + 1) * 8].copy_from_slice(&word.to_be_bytes());
}
bytes
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct U192 {
pub data: [u64; 3],
}
impl U192 {
pub const fn new(data: [u64; 3]) -> Self {
Self { data }
}
pub fn from_be_bytes(bytes: [u8; 24]) -> Self {
let mut data = [0u64; 3];
for (index, chunk) in bytes.chunks_exact(8).enumerate() {
let mut word = [0u8; 8];
word.copy_from_slice(chunk);
data[index] = u64::from_be_bytes(word);
}
Self { data }
}
pub fn to_be_bytes(self) -> [u8; 24] {
let mut bytes = [0u8; 24];
for (index, word) in self.data.iter().enumerate() {
bytes[index * 8..(index + 1) * 8].copy_from_slice(&word.to_be_bytes());
}
bytes
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AesEncryptionType {
Low(u128),
Medium(U192),
High(U256),
}
impl AesEncryptionType {
pub(crate) fn key_bytes(self) -> Vec<u8> {
match self {
Self::Low(key) => key.to_be_bytes().to_vec(),
Self::Medium(key) => key.to_be_bytes().to_vec(),
Self::High(key) => key.to_be_bytes().to_vec(),
}
}
pub(crate) const fn rounds(self) -> usize {
match self {
Self::Low(_) => 10,
Self::Medium(_) => 12,
Self::High(_) => 14,
}
}
pub const fn bit_len(self) -> usize {
match self {
Self::Low(_) => 128,
Self::Medium(_) => 192,
Self::High(_) => 256,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Aes {
security: AesEncryptionType,
x: u128,
}
impl Aes {
pub const fn new(security: AesEncryptionType, x: u128) -> Self {
Self { security, x }
}
pub fn encrypt(&self) -> u128 {
encrypt_block(self.x, self.security)
}
}
pub(crate) fn encrypt_block(block: u128, security: AesEncryptionType) -> u128 {
let round_keys = expand_key(security);
let mut state = block.to_be_bytes();
add_round_key(&mut state, round_keys[0]);
for round_key in round_keys.iter().take(security.rounds()).skip(1) {
sub_bytes_state(&mut state);
shift_rows_state(&mut state);
mix_columns_state(&mut state);
add_round_key(&mut state, *round_key);
}
sub_bytes_state(&mut state);
shift_rows_state(&mut state);
add_round_key(&mut state, round_keys[security.rounds()]);
u128::from_be_bytes(state)
}
pub(crate) fn add_round_key(state: &mut [u8; 16], round_key: u128) {
for (byte, key_byte) in state.iter_mut().zip(round_key.to_be_bytes()) {
*byte ^= key_byte;
}
}
pub(crate) fn sub_bytes_state(state: &mut [u8; 16]) {
for byte in state.iter_mut() {
*byte = substitute_byte(*byte);
}
}
pub(crate) fn inverse_sub_bytes_state(state: &mut [u8; 16]) {
for byte in state.iter_mut() {
*byte = inverse_substitute_byte(*byte);
}
}
pub(crate) fn substitute_byte(byte: u8) -> u8 {
SBOX[(byte >> 4) as usize][(byte & 0x0F) as usize]
}
pub(crate) fn inverse_substitute_byte(byte: u8) -> u8 {
static INVERSE_SBOX: OnceLock<[u8; 256]> = OnceLock::new();
let table = INVERSE_SBOX.get_or_init(|| {
let mut inverse = [0u8; 256];
for candidate in 0..=u8::MAX {
inverse[substitute_byte(candidate) as usize] = candidate;
}
inverse
});
table[byte as usize]
}