reverse key schedule

This commit is contained in:
Sam Hadow 2024-04-27 22:42:53 +02:00
parent 6520a36e14
commit 9cbbc0ff79
2 changed files with 133 additions and 21 deletions

View File

@ -168,6 +168,14 @@ fn substitute_word(bytes: &[u8; 4]) -> [u8; 4] {
} }
result result
} }
fn inverse_substitute_word(bytes: &[u8; 4]) -> [u8; 4] {
let mut result = [0u8; 4];
for i in 0..4 {
result[i] = substitute(bytes[i], false);
}
result
}
fn substitute_state(state: &mut [[u8; 4]; 4]) { fn substitute_state(state: &mut [[u8; 4]; 4]) {
for row in state.iter_mut().take(4) { for row in state.iter_mut().take(4) {
for item in row.iter_mut().take(4) { for item in row.iter_mut().take(4) {
@ -202,6 +210,14 @@ fn shift_word(bytes: &[u8; 4]) -> [u8; 4] {
result result
} }
fn inverse_shift_word(bytes: &[u8; 4]) -> [u8; 4] {
let mut result = [0u8; 4];
for i in 0..4 {
result[i] = bytes[(i + 3) % 4];
}
result
}
fn shift_rows(state: &mut [[u8; 4]; 4]) { fn shift_rows(state: &mut [[u8; 4]; 4]) {
for i in 1..4 { for i in 1..4 {
let mut tmp = vec![0u8; i]; let mut tmp = vec![0u8; i];
@ -348,7 +364,10 @@ impl Aes {
substitute_state(&mut state); substitute_state(&mut state);
shift_rows(&mut state); shift_rows(&mut state);
add_round_key(&mut state, &clone_into_array(&self.expanded_key[(self.n_turn)*4..(self.n_turn+1)*4])); add_round_key(
&mut state,
&clone_into_array(&self.expanded_key[(self.n_turn) * 4..(self.n_turn + 1) * 4]),
);
for i in 0..4 { for i in 0..4 {
for j in 0..4 { for j in 0..4 {
@ -366,7 +385,10 @@ impl Aes {
state[i % 4][i / 4] = block[i]; state[i % 4][i / 4] = block[i];
} }
add_round_key(&mut state, &clone_into_array(&self.expanded_key[(self.n_turn)*4..(self.n_turn+1)*4])); add_round_key(
&mut state,
&clone_into_array(&self.expanded_key[(self.n_turn) * 4..(self.n_turn + 1) * 4]),
);
inverse_shift_rows(&mut state); inverse_shift_rows(&mut state);
inverse_substitute_state(&mut state); inverse_substitute_state(&mut state);
@ -422,6 +444,64 @@ impl Aes {
expanded_key expanded_key
} }
// pub fn reverse_key_schedule(round_key: &mut [u8; 16], aes_round: usize) -> [[u8; 4]; 4] {
// let mut round_keys = [[0u8; 4]; 4]; // Array to store the round keys
// let n = 4;
//
// // Extract the original key from the provided round key
// let mut original_key = [[0u8; 4]; 4];
// for i in 0..16 {
// original_key[i / 4][i % 4] = round_key[i];
// }
//
// // Reverse the key expansion process for the first 4 rounds
// for i in (0..16).rev() {
// if i % n == 0 {
// // Reverse the addition of the round constant
// let mut rcon = [0u8; 4];
// rcon[0] = RC[i / n];
// round_keys[i / n] = xor(
// &original_key[i / n],
// &inverse_shift_word(&inverse_substitute_word(&xor(&original_key[i / n], &rcon))),
// );
// } else if i >= n {
// // Reverse the XOR operation
// round_keys[i / n] = xor(&original_key[i / n], &original_key[i / n - 1]);
// }
// }
//
// // Update the provided round key array with the round keys for the specified AES rounds
// for i in 0..16 {
// round_key[i] = round_keys[aes_round / n][i % n];
// }
//
// round_keys
// }
pub fn reverse_key_schedule(round_key: &mut [u8; 16], aes_round: usize) -> [u8; 16] {
let mut rcon = [0u8; 4];
// let n = 4;
// let indexes = [1,2,3,4];
for i in (0..aes_round).rev() {
rcon[0] = RC[i + 1];
let a2: [u8; 4] = round_key[0..4].try_into().unwrap();
let b2: [u8; 4] = round_key[4..8].try_into().unwrap();
let c2: [u8; 4] = round_key[8..12].try_into().unwrap();
let d2: [u8; 4] = round_key[12..16].try_into().unwrap();
let d1 = xor(&d2, &c2);
let c1 = xor(&c2, &b2);
let b1 = xor(&b2, &a2);
let a1 = xor(&xor(&a2, &shift_word(&substitute_word(&d1))), &rcon);
round_key[0..4].copy_from_slice(&a1);
round_key[4..8].copy_from_slice(&b1);
round_key[8..12].copy_from_slice(&c1);
round_key[12..16].copy_from_slice(&d1);
}
*round_key
}
pub fn aes_reduced(&key: &[u8; 16], &block: &[u8; 16]) -> [u8; 16] { pub fn aes_reduced(&key: &[u8; 16], &block: &[u8; 16]) -> [u8; 16] {
let nturn = 4; let nturn = 4;
let aescipher = Self::new(&key, &nturn); let aescipher = Self::new(&key, &nturn);
@ -447,10 +527,7 @@ impl Aes {
for i in 0..16 { for i in 0..16 {
state[i % 4][i / 4] = block[i]; state[i % 4][i / 4] = block[i];
} }
add_round_key( add_round_key(&mut state, &clone_into_array(&self.expanded_key[16..20]));
&mut state,
&clone_into_array(&self.expanded_key[16..20]),
);
inverse_shift_rows(&mut state); inverse_shift_rows(&mut state);
inverse_substitute_state(&mut state); inverse_substitute_state(&mut state);
@ -482,7 +559,7 @@ impl Aes {
array[j * 4 + i] = matrix[j][i]; array[j * 4 + i] = matrix[j][i];
} }
} }
s ^= substitute(array[j]^ i as u8, false); s ^= substitute(array[j] ^ i, false);
} }
if s == 0x00 { if s == 0x00 {
println!("found: {:02x} for byte {}", i, j); println!("found: {:02x} for byte {}", i, j);
@ -493,6 +570,7 @@ impl Aes {
} }
key key
} }
pub fn findroundkey(&key: &[u8; 16]) -> [u8; 16] { pub fn findroundkey(&key: &[u8; 16]) -> [u8; 16] {
let mut found_key: [u8; 16] = [0x00; 16]; let mut found_key: [u8; 16] = [0x00; 16];
let mut const_byte: u8 = 0x00; let mut const_byte: u8 = 0x00;
@ -501,11 +579,16 @@ impl Aes {
let mut more_key_guesses: [Vec<u8>; 16]; let mut more_key_guesses: [Vec<u8>; 16];
let mut result: [Vec<u8>; 16] = Default::default(); let mut result: [Vec<u8>; 16] = Default::default();
while key_guesses.iter().any(|vec| vec.len() > 1) { while key_guesses.iter().any(|vec| vec.len() > 1) {
const_byte += 1 as u8; const_byte += 1_u8;
ciphertexts = Self::aes_reduced_gen_texts(&key, &const_byte); ciphertexts = Self::aes_reduced_gen_texts(&key, &const_byte);
more_key_guesses = Self::guessroundkey(&ciphertexts); more_key_guesses = Self::guessroundkey(&ciphertexts);
for ((vec1, vec2), result_vec) in more_key_guesses.iter().zip(key_guesses.iter()).zip(result.iter_mut()) { for ((vec1, vec2), result_vec) in more_key_guesses
let common_elements: Vec<u8> = vec1.iter() .iter()
.zip(key_guesses.iter())
.zip(result.iter_mut())
{
let common_elements: Vec<u8> = vec1
.iter()
.filter(|&byte| vec2.contains(byte)) .filter(|&byte| vec2.contains(byte))
.copied() .copied()
.collect(); .collect();
@ -515,7 +598,6 @@ impl Aes {
for (source, target) in result.iter().zip(key_guesses.iter_mut()) { for (source, target) in result.iter().zip(key_guesses.iter_mut()) {
*target = source.clone(); *target = source.clone();
} }
} }
for (index, vec) in key_guesses.iter().enumerate() { for (index, vec) in key_guesses.iter().enumerate() {
if let Some(&first_byte) = vec.first() { if let Some(&first_byte) = vec.first() {
@ -524,7 +606,9 @@ impl Aes {
} }
found_key found_key
} }
// pub fn findkey(&key: &[u8; 16]) -> [u8; 16] {
//
// }
} }
#[cfg(test)] #[cfg(test)]
@ -637,4 +721,16 @@ mod tests {
let found_key: [u8; 16] = Aes::findroundkey(&key); let found_key: [u8; 16] = Aes::findroundkey(&key);
assert_eq!(found_key, expected); assert_eq!(found_key, expected);
} }
#[test]
fn inverse_shift_word_test() {
let word: [u8; 4] = [0x01, 0x34, 0x76, 0x49];
let inverse_word: [u8; 4] = shift_word(&word);
assert_eq!(word, inverse_shift_word(&inverse_word));
}
#[test]
fn inverse_substitute_word_test() {
let word: [u8; 4] = [0x01, 0x34, 0x76, 0x49];
let inverse_word: [u8; 4] = substitute_word(&word);
assert_eq!(word, inverse_substitute_word(&inverse_word));
}
} }

View File

@ -2,17 +2,33 @@ mod aes;
use aes::Aes; use aes::Aes;
fn main() { fn main() {
let key: [u8; 16] = [ let key: [u8; 16] = [
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f,
0x4f, 0x3c, 0x3c,
]; ];
let found_key: [u8; 16] = Aes::findroundkey(&key); let mut found_key: [u8; 16] = Aes::findroundkey(&key);
for &byte in &found_key { for &byte in &found_key {
print!("{:02x}", byte); print!("{:02x}", byte);
} }
println!() println!();
// should be // should be
// ef44a541 // ef44a541
// a8525b7f // a8525b7f
// b671253b // b671253b
// db0bad00 // db0bad00
let found_key_origininal = Aes::reverse_key_schedule(&mut found_key, 4);
for &byte in &found_key_origininal {
print!("{:02x}", byte);
}
println!();
// 247e156b 22aed2a6 a7f71588 01cf4f3c
// 2b7e1516, 28aed2a6, abf71588, 09cf4f3c, EXPECTED
// 2b7e1574 27aed2a6 a4f71588 00cf4f3c
// 2b7e1516 28aed2a6 abf71588 09cf4f3c
// 2b7e1516, 28aed2a6, abf71588, 09cf4f3c,
// a0fafe17, 88542cb1, 23a33939, 2a6c7605,
// f2c295f2, 7a96b943, 5935807a, 7359f67f,
// 3d80477d, 4716fe3e, 1e237e44, 6d7a883b,
// ef44a541, a8525b7f, b671253b, db0bad00
} }