find round key, square attack AES128 4 rounds
This commit is contained in:
		
							
								
								
									
										125
									
								
								src/aes.rs
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								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<A, T>(slice: &[T]) -> A | ||||
| pub fn clone_into_array<A, T>(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<u8>; 16]{ | ||||
|         let mut key: [Vec<u8>; 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<u8>; 16] = Self::guessroundkey(&ciphertexts); | ||||
|         let mut more_key_guesses: [Vec<u8>; 16]; | ||||
|         let mut result: [Vec<u8>; 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<u8> = 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)] | ||||
|   | ||||
							
								
								
									
										160
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								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 | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user