find round key, square attack AES128 4 rounds
This commit is contained in:
parent
7a2a5c567e
commit
363ca06bad
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,
|
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
|
where
|
||||||
A: Default + AsMut<[T]>,
|
A: Default + AsMut<[T]>,
|
||||||
T: Clone,
|
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 i: usize = ((byte >> 4) & 0xF).into();
|
||||||
let j: usize = (byte & 0xF).into();
|
let j: usize = (byte & 0xF).into();
|
||||||
if encryption {
|
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() {
|
for i in (1..4).rev() {
|
||||||
let mut tmp = vec![0u8; i];
|
let mut tmp = vec![0u8; i];
|
||||||
tmp[..i].copy_from_slice(&state[4 - i][..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 i in 0..4 {
|
||||||
// for j in 0..4 {
|
// for j in 0..4 {
|
||||||
// state[i][j] ^= key[j][i];
|
// 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 {
|
pub struct Aes {
|
||||||
n_turn: usize,
|
n_turn: usize,
|
||||||
key: [u8; 16],
|
key: [u8; 16],
|
||||||
expanded_key: [[u8; 4]; 44],
|
pub expanded_key: [[u8; 4]; 44],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Aes {
|
impl Aes {
|
||||||
fn new(&key: &[u8; 16], &n_turn: &usize) -> Self {
|
pub fn new(&key: &[u8; 16], &n_turn: &usize) -> Self {
|
||||||
Aes {
|
Aes {
|
||||||
n_turn,
|
n_turn,
|
||||||
key,
|
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 result = [0u8; 16];
|
||||||
|
|
||||||
let mut state = [[0u8; 4]; 4];
|
let mut state = [[0u8; 4]; 4];
|
||||||
@ -348,7 +348,7 @@ 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[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 i in 0..4 {
|
||||||
for j in 0..4 {
|
for j in 0..4 {
|
||||||
@ -358,7 +358,7 @@ impl Aes {
|
|||||||
result
|
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 result = [0u8; 16];
|
||||||
|
|
||||||
let mut state = [[0u8; 4]; 4];
|
let mut state = [[0u8; 4]; 4];
|
||||||
@ -366,7 +366,7 @@ 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[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_shift_rows(&mut state);
|
||||||
inverse_substitute_state(&mut state);
|
inverse_substitute_state(&mut state);
|
||||||
|
|
||||||
@ -421,6 +421,111 @@ impl Aes {
|
|||||||
|
|
||||||
expanded_key
|
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)]
|
#[cfg(test)]
|
||||||
|
160
src/main.rs
160
src/main.rs
@ -2,24 +2,148 @@ 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, 0x4f,
|
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf,
|
||||||
0x3c,
|
0x4f, 0x3c,
|
||||||
];
|
];
|
||||||
let expanded_key = Aes::key_schedule(&key);
|
let found_key: [u8; 16] = Aes::findroundkey(&key);
|
||||||
for i in 0..11 {
|
for &byte in &found_key {
|
||||||
println!("Block {}", i + 1);
|
print!("{:02x}", byte);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user