diff --git a/src/aes.rs b/src/aes.rs index 4229a0f..41569bb 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -168,6 +168,14 @@ fn substitute_word(bytes: &[u8; 4]) -> [u8; 4] { } 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]) { for row in state.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 } +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]) { for i in 1..4 { let mut tmp = vec![0u8; i]; @@ -348,7 +364,10 @@ impl Aes { substitute_state(&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 j in 0..4 { @@ -366,7 +385,10 @@ impl Aes { 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_substitute_state(&mut state); @@ -422,6 +444,64 @@ impl Aes { 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] { let nturn = 4; let aescipher = Self::new(&key, &nturn); @@ -447,12 +527,9 @@ impl Aes { for i in 0..16 { state[i % 4][i / 4] = block[i]; } - add_round_key( - &mut state, - &clone_into_array(&self.expanded_key[16..20]), - ); - inverse_shift_rows(&mut state); - inverse_substitute_state(&mut state); + add_round_key(&mut state, &clone_into_array(&self.expanded_key[16..20])); + inverse_shift_rows(&mut state); + inverse_substitute_state(&mut state); for i in 0..4 { for j in 0..4 { @@ -462,7 +539,7 @@ impl Aes { result } - pub fn guessroundkey(&texts: &[[u8; 16]; 256]) -> [Vec; 16]{ + pub fn guessroundkey(&texts: &[[u8; 16]; 256]) -> [Vec; 16] { let mut key: [Vec; 16] = Default::default(); let mut s: u8; let mut matrix: [[u8; 4]; 4] = [[0; 4]; 4]; @@ -482,7 +559,7 @@ impl Aes { array[j * 4 + i] = matrix[j][i]; } } - s ^= substitute(array[j]^ i as u8, false); + s ^= substitute(array[j] ^ i, false); } if s == 0x00 { println!("found: {:02x} for byte {}", i, j); @@ -493,6 +570,7 @@ impl Aes { } key } + pub fn findroundkey(&key: &[u8; 16]) -> [u8; 16] { let mut found_key: [u8; 16] = [0x00; 16]; let mut const_byte: u8 = 0x00; @@ -501,11 +579,16 @@ impl Aes { let mut more_key_guesses: [Vec; 16]; let mut result: [Vec; 16] = Default::default(); 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); - more_key_guesses = Self::guessroundkey(&ciphertexts); - for ((vec1, vec2), result_vec) in more_key_guesses.iter().zip(key_guesses.iter()).zip(result.iter_mut()) { - let common_elements: Vec = vec1.iter() + more_key_guesses = Self::guessroundkey(&ciphertexts); + for ((vec1, vec2), result_vec) in more_key_guesses + .iter() + .zip(key_guesses.iter()) + .zip(result.iter_mut()) + { + let common_elements: Vec = vec1 + .iter() .filter(|&byte| vec2.contains(byte)) .copied() .collect(); @@ -515,7 +598,6 @@ impl Aes { for (source, target) in result.iter().zip(key_guesses.iter_mut()) { *target = source.clone(); } - } for (index, vec) in key_guesses.iter().enumerate() { if let Some(&first_byte) = vec.first() { @@ -524,7 +606,9 @@ impl Aes { } found_key } - + // pub fn findkey(&key: &[u8; 16]) -> [u8; 16] { + // + // } } #[cfg(test)] @@ -627,7 +711,7 @@ mod tests { ]; let nturn = 4; // doesn't matter for this test let aescipher = Aes::new(&key, &nturn); - let expected: [u8; 16] = aescipher.expanded_key[16..20] // 5th key (1st is the pre_whitenning, 2nd, 3rd and 4th the 3 previous round key) + let expected: [u8; 16] = aescipher.expanded_key[16..20] // 5th key (1st is the pre_whitenning, 2nd, 3rd and 4th the 3 previous round key) .iter() .flat_map(|subarray| subarray.iter()) .copied() @@ -637,4 +721,16 @@ mod tests { let found_key: [u8; 16] = Aes::findroundkey(&key); 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)); + } } diff --git a/src/main.rs b/src/main.rs index bdcc1df..fc2b18d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,17 +2,33 @@ mod aes; use aes::Aes; fn main() { let key: [u8; 16] = [ - 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, - 0x4f, 0x3c, + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, + 0x3c, ]; - let found_key: [u8; 16] = Aes::findroundkey(&key); + let mut found_key: [u8; 16] = Aes::findroundkey(&key); for &byte in &found_key { print!("{:02x}", byte); } - println!() + println!(); // should be // ef44a541 // a8525b7f // b671253b // 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 }