From 363ca06bad178bc0e2cb1e1740d238e64a4deda0 Mon Sep 17 00:00:00 2001 From: Sam Hadow Date: Sat, 27 Apr 2024 18:40:15 +0200 Subject: [PATCH] find round key, square attack AES128 4 rounds --- src/aes.rs | 125 ++++++++++++++++++++++++++++++++++++---- src/main.rs | 160 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 257 insertions(+), 28 deletions(-) diff --git a/src/aes.rs b/src/aes.rs index 0966947..3f34cbf 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -143,7 +143,7 @@ static RC: [u8; 11] = [ 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, ]; -fn clone_into_array(slice: &[T]) -> A +pub fn clone_into_array(slice: &[T]) -> A where A: Default + AsMut<[T]>, T: Clone, @@ -184,7 +184,7 @@ fn inverse_substitute_state(state: &mut [[u8; 4]; 4]) { } } -fn substitute(byte: u8, encryption: bool) -> u8 { +pub fn substitute(byte: u8, encryption: bool) -> u8 { let i: usize = ((byte >> 4) & 0xF).into(); let j: usize = (byte & 0xF).into(); if encryption { @@ -215,7 +215,7 @@ fn shift_rows(state: &mut [[u8; 4]; 4]) { } } -fn inverse_shift_rows(state: &mut [[u8; 4]; 4]) { +pub fn inverse_shift_rows(state: &mut [[u8; 4]; 4]) { for i in (1..4).rev() { let mut tmp = vec![0u8; i]; tmp[..i].copy_from_slice(&state[4 - i][..i]); @@ -298,7 +298,7 @@ fn inverse_mix_columns(state: &mut [[u8; 4]; 4]) { } } -fn add_round_key(state: &mut [[u8; 4]; 4], key: &[[u8; 4]; 4]) { +pub fn add_round_key(state: &mut [[u8; 4]; 4], key: &[[u8; 4]; 4]) { // for i in 0..4 { // for j in 0..4 { // state[i][j] ^= key[j][i]; @@ -314,11 +314,11 @@ fn add_round_key(state: &mut [[u8; 4]; 4], key: &[[u8; 4]; 4]) { pub struct Aes { n_turn: usize, key: [u8; 16], - expanded_key: [[u8; 4]; 44], + pub expanded_key: [[u8; 4]; 44], } impl Aes { - fn new(&key: &[u8; 16], &n_turn: &usize) -> Self { + pub fn new(&key: &[u8; 16], &n_turn: &usize) -> Self { Aes { n_turn, key, @@ -326,7 +326,7 @@ impl Aes { } } - fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] { + pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] { let mut result = [0u8; 16]; let mut state = [[0u8; 4]; 4]; @@ -348,7 +348,7 @@ impl Aes { substitute_state(&mut state); shift_rows(&mut state); - add_round_key(&mut state, &clone_into_array(&self.expanded_key[40..44])); + 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 { @@ -358,7 +358,7 @@ impl Aes { result } - fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] { + pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] { let mut result = [0u8; 16]; let mut state = [[0u8; 4]; 4]; @@ -366,7 +366,7 @@ impl Aes { state[i % 4][i / 4] = block[i]; } - add_round_key(&mut state, &clone_into_array(&self.expanded_key[40..44])); + 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); @@ -421,6 +421,111 @@ impl Aes { expanded_key } + + pub fn aes_reduced(&key: &[u8; 16], &block: &[u8; 16]) -> [u8; 16] { + let nturn = 4; + let aescipher = Self::new(&key, &nturn); + aescipher.encrypt_block(&block) + } + pub fn aes_reduced_gen_texts(&key: &[u8; 16], &const_byte: &u8) -> [[u8; 16]; 256] { + let mut cleartext: [u8; 16]; + let mut ciphertexts: [[u8; 16]; 256] = [[0; 16]; 256]; + for i in 0..=255 { + cleartext = [ + i, const_byte, const_byte, const_byte, const_byte, const_byte, const_byte, + const_byte, const_byte, const_byte, const_byte, const_byte, const_byte, const_byte, + const_byte, const_byte, + ]; + ciphertexts[i as usize] = Aes::aes_reduced(&key, &cleartext); + } + ciphertexts + } + pub fn decrypt_block_reduced_1_step(&self, block: &[u8; 16]) -> [u8; 16] { + let mut result = [0u8; 16]; + + let mut state = [[0u8; 4]; 4]; + 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); + + for i in 0..4 { + for j in 0..4 { + result[4 * j + i] = state[i][j] + } + } + + result + } + 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]; + let mut array: [u8; 16] = [0; 16]; + for j in 0..16 { + for i in 0..=255 { + s = 0x00; + for ciphertext in texts { + for i in 0..4 { + for j in 0..4 { + matrix[j][i] = ciphertext[j * 4 + i]; + } + } + // aes::inverse_shift_rows(&mut matrix); + for i in 0..4 { + for j in 0..4 { + array[j * 4 + i] = matrix[j][i]; + } + } + s ^= substitute(array[j]^ i as u8, false); + } + if s == 0x00 { + println!("found: {:02x} for byte {}", i, j); + key[j].push(i); + } + } + println!(); + } + key + } + pub fn findroundkey(&key: &[u8; 16]) -> [u8; 16] { + let mut found_key: [u8; 16] = [0x00; 16]; + let mut const_byte: u8 = 0x00; + let mut ciphertexts: [[u8; 16]; 256] = Self::aes_reduced_gen_texts(&key, &const_byte); + let mut key_guesses: [Vec; 16] = Self::guessroundkey(&ciphertexts); + 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; + 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() + .filter(|&byte| vec2.contains(byte)) + .copied() + .collect(); + + *result_vec = common_elements; + } + 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() { + found_key[index] = first_byte; + } + } + found_key + + } + } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index 33a0761..dc557ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,24 +2,148 @@ 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 expanded_key = Aes::key_schedule(&key); - for i in 0..11 { - println!("Block {}", i + 1); - for j in 0..4 { - let index = i * 4 + j; - print!(" "); - for &byte in &expanded_key[index] { - print!("{:02x}", byte); - } - println!(); - } - } - let my_number: u32 = 0x2b7e1516; - let bytes: [u8; 4] = my_number.to_be_bytes(); - for &byte in &bytes { - println!("{:02x}", byte); + let found_key: [u8; 16] = Aes::findroundkey(&key); + for &byte in &found_key { + print!("{:02x}", byte); } + println!() + // should be + // ef44a541 + // a8525b7f + // b671253b + // db0bad00 + + // let aescipher = Aes::new(&key, &4); + // let expanded_key = Aes::key_schedule(&key); + // for i in 0..10 { + // println!("Block {}", i + 1); + // for j in 0..4 { + // let index = i * 4 + j; + // print!(" "); + // for &byte in &expanded_key[index] { + // print!("{:02x}", byte); + // } + // println!(); + // } + // } + // let cleartext: [u8; 16] = [ + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 0x00, + // ]; + // let ciphertext: [u8; 16] = Aes::aes_reduced(&key, &cleartext); + // + // let mut ciphertexts = Aes::aes_reduced_gen_texts(&key, &0x00); + // let mut S = 0x00; + // + // + // + // let mut matrix: [[u8; 4]; 4] = [[0; 4]; 4]; + // let mut array: [u8; 16] = [0; 16]; + // + // for j in 0..16 { + // for i in 0..=255 { + // S = 0x00; + // for ciphertext in ciphertexts { + // for i in 0..4 { + // for j in 0..4 { + // matrix[j][i] = ciphertext[j * 4 + i]; + // } + // } + // // aes::inverse_shift_rows(&mut matrix); + // for i in 0..4 { + // for j in 0..4 { + // array[j * 4 + i] = matrix[j][i]; + // } + // } + // S ^= aes::substitute(array[j]^ i as u8, false); + // } + // if S == 0x00 { + // println!("found: {:02x}", i); + // } + // } + // println!(); + // } + // println!("part 2"); + // ciphertexts = Aes::aes_reduced_gen_texts(&key, &0xff); + // + // let mut matrix: [[u8; 4]; 4] = [[0; 4]; 4]; + // let mut array: [u8; 16] = [0; 16]; + // + // for j in 0..16 { + // for i in 0..=255 { + // S = 0x00; + // for ciphertext in ciphertexts { + // for k in 0..4 { + // for m in 0..4 { + // matrix[k][m] = ciphertext[k * 4 + m]; + // } + // } + // // aes::inverse_shift_rows(&mut matrix); + // for i in 0..4 { + // for j in 0..4 { + // array[j * 4 + i] = matrix[j][i]; + // } + // } + // S ^= aes::substitute(array[j]^ i as u8, false); + // } + // if S == 0x00 { + // println!("found: {:02x}", i); + // } + // } + // println!(); + // } + // println!("part 3"); + // ciphertexts = Aes::aes_reduced_gen_texts(&key, &0xff); + // + // let mut matrix: [[u8; 4]; 4] = [[0; 4]; 4]; + // let mut array: [u8; 16] = [0; 16]; + // + // let mut ciphertext2: [[u8;16]; 256] = [[0; 16]; 256]; + // S = 0x00; + // for i in 0..256 { + // ciphertext2[i] = aescipher.decrypt_block_reduced_1_step(&ciphertexts[i]); + // // for &byte in &aescipher.decrypt_block(&ciphertexts[i]) { + // // print!("{:02x}", byte); + // // } + // // println!(); + // + // } + // for ciphertext in ciphertext2 { + // S ^= ciphertext[0]; + // } + // if S == 0x00 { + // println!("should be: {:02x}", S); + // } + // println!(); + + // 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, WHITENING 0;4 + // 0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605, ROUND 1 4;8 + // 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, ROUND 2 8;12 + // 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, ROUND 3 12;16 + // 0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00, ROUND 4 16;20 + // 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, + // 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, + // 0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f, + // 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f, + // 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, + // 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, + + // for ciphertext in ciphertexts { + // S = S ^ aes::substitute(ciphertext[0] ^ 0x4b, false); + // for elem in ciphertext { + // print!("{:02x}", elem); + // } + // println!(); + // } + // println!("should be: {:02x}", S); + + // ef44a541 + // a8525b7f + // b671253b + // db0bad00 + + }