diff --git a/src/aes.rs b/src/aes.rs index 89d744c..eadefab 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -3,7 +3,6 @@ use std::io::{Error, ErrorKind}; // AES specs // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf - // S box, 16*16 Matrix with fixed values static SBOX: [[u8; 16]; 16] = [ [ @@ -144,13 +143,16 @@ static RC: [u8; 11] = [ 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, ]; -// Mix Columns -static MIXCOLUMNS: [[u8; 4]; 4] = [ - [0x02, 0x03, 0x01, 0x01], - [0x01, 0x02, 0x03, 0x01], - [0x01, 0x01, 0x02, 0x03], - [0x03, 0x01, 0x01, 0x02], -]; + +fn clone_into_array(slice: &[T]) -> A +where + A: Default + AsMut<[T]>, + T: Clone, +{ + let mut a = A::default(); + >::as_mut(&mut a).clone_from_slice(slice); + a +} fn xor(bits1: &[u8; 4], bits2: &[u8; 4]) -> [u8; 4] { let mut result = [0u8; 4]; @@ -165,29 +167,28 @@ fn substitute_word(bytes: &[u8; 4]) -> [u8; 4] { for i in 0..4 { result[i] = substitute(bytes[i], true); } - return result; + result } fn substitute_state(state: &mut [[u8; 4]; 4]) { - for i in 0..4 { - for j in 0..4 { - state[i][j] = substitute(state[i][j], true); + for row in state.iter_mut().take(4) { + for item in row.iter_mut().take(4) { + *item = substitute(*item, true); } } } + fn inverse_substitute_state(state: &mut [[u8; 4]; 4]) { - for i in 0..4 { - for j in 0..4 { - state[i][j] = substitute(state[i][j], false); + for row in state.iter_mut().take(4) { + for item in row.iter_mut().take(4) { + *item = substitute(*item, false); } } } fn substitute(byte: u8, encryption: bool) -> u8 { - let i: usize; - let j: usize; - i = ((byte >> 4) & 0xF).into(); - j = (byte & 0xF).into(); - if encryption == true { + let i: usize = ((byte >> 4) & 0xF).into(); + let j: usize = (byte & 0xF).into(); + if encryption { SBOX[i][j] } else { INVERSE_SBOX[i][j] @@ -202,10 +203,85 @@ fn shift_word(bytes: &[u8; 4]) -> [u8; 4] { result } -fn add_round_key(state: &mut [[u8; 4]; 4], key: &[[u8; 4]; 4]) { +fn shift_rows(state: &mut [[u8; 4]; 4]) { + for i in 1..4 { + let mut tmp = vec![0u8; i]; + tmp[..i].copy_from_slice(&state[i][..i]); + for j in 0..4 - i { + state[i][j] = state[i][j + i]; + } + for j in 0..i { + state[i][3 - j] = tmp[i - j - 1]; + } + } +} + +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]); + for j in 0..4 - i { + state[4 - i][j] = state[4 - i][j + i]; + } + for j in 0..i { + state[4 - i][3 - j] = tmp[i - j - 1]; + } + } +} + +fn galois_multiplication(ap: u8, bp: u8) -> u8 { + let mut p = 0u8; + let mut high_bit; + let mut a = ap; + let mut b = bp; + for _i in 0..8 { + if b & 1 == 1 { + p ^= a + } + high_bit = a & 0x80; + a <<= 1; + if high_bit == 0x80 { + a ^= 0x1b; + } + b >>= 1; + } + p +} + +fn mix_columns(state: &mut [[u8; 4]; 4]) { for i in 0..4 { + let mut temp = [0u8; 4]; for j in 0..4 { - state[i][j] = state[i][j] ^ key[j][i]; + temp[j] = state[j][i]; + } + state[0][i] = galois_multiplication(temp[0], 2) + ^ galois_multiplication(temp[3], 1) + ^ galois_multiplication(temp[2], 1) + ^ galois_multiplication(temp[1], 3); + state[1][i] = galois_multiplication(temp[1], 2) + ^ galois_multiplication(temp[0], 1) + ^ galois_multiplication(temp[3], 1) + ^ galois_multiplication(temp[2], 3); + state[2][i] = galois_multiplication(temp[2], 2) + ^ galois_multiplication(temp[1], 1) + ^ galois_multiplication(temp[0], 1) + ^ galois_multiplication(temp[3], 3); + state[3][i] = galois_multiplication(temp[3], 2) + ^ galois_multiplication(temp[2], 1) + ^ galois_multiplication(temp[1], 1) + ^ galois_multiplication(temp[0], 3); + } +} + +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]; + // } + // } + for (i, row) in state.iter_mut().enumerate().take(4) { + for (j, item) in row.iter_mut().enumerate().take(4) { + *item ^= key[j][i]; } } } @@ -214,41 +290,49 @@ pub struct Aes { n_turn: usize, key: [u8; 16], expanded_key: [[u8; 4]; 44], - state: [[u8; 4]; 4], } impl Aes { - fn new(block: [[u8; 4]; 4], key: [u8; 16], n_turn: usize) -> Self { + fn new(&key: &[u8; 16], &n_turn: &usize) -> Self { Aes { n_turn, key, expanded_key: Self::key_schedule(&key), - state: block, } } - fn sub_bytes(&mut self) { - unimplemented!(); + + fn encrypt_block(&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[0..4])); + + for i in 1..self.n_turn { + substitute_state(&mut state); + shift_rows(&mut state); + mix_columns(&mut state); + add_round_key( + &mut state, + &clone_into_array(&self.expanded_key[i * 4..(i + 1) * 4]), + ); + } + + substitute_state(&mut state); + shift_rows(&mut state); + add_round_key(&mut state, &clone_into_array(&self.expanded_key[40..44])); + + for i in 0..4 { + for j in 0..4 { + result[4 * j + i] = state[i][j] + } + } + result } - fn shift_rows(&mut self) { - unimplemented!(); - } - - fn mix_columns(&mut self) { - unimplemented!(); - } - - fn add_round_key(&mut self) { - unimplemented!(); - } - - fn turn(&mut self) { - unimplemented!(); - } - - fn encrypt_block(block: [[u8; 4]; 4], key: Vec, n_turn: usize) { - unimplemented!(); - } pub fn key_schedule(key_bytes: &[u8; 16]) -> [[u8; 4]; 44] { let mut original_key = [[0u8; 4]; 4]; let mut expanded_key = [[0u8; 4]; 44]; @@ -310,24 +394,48 @@ mod tests { #[test] fn key_schedule_test() { 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); let expected: [u32; 44] = [ - 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, 0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605, 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, 0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00, 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, 0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f, 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f, 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, 0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6, + 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, 0xa0fafe17, 0x88542cb1, 0x23a33939, + 0x2a6c7605, 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f, 0x3d80477d, 0x4716fe3e, + 0x1e237e44, 0x6d7a883b, 0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00, 0xd4d1c6f8, + 0x7c839d87, 0xcaf2b8bc, 0x11f915bc, 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, + 0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f, 0xead27321, 0xb58dbad2, 0x312bf560, + 0x7f8d292f, 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, 0xd014f9a8, 0xc9ee2589, + 0xe13f0cc8, 0xb6630ca6, ]; let mut expected_bytes: [u8; 4]; for i in 0..11 { for j in 0..4 { let index = i * 4 + j; expected_bytes = expected[index].to_be_bytes(); - for (&byte, &expected_byte) in expanded_key[index].iter().zip(expected_bytes.iter()) { + for (&byte, &expected_byte) in expanded_key[index].iter().zip(expected_bytes.iter()) + { assert_eq!(byte, expected_byte); } } } } + #[test] + fn encrypt_test() { + let cleartext: [u8; 16] = [ + 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, + 0x07, 0x34, + ]; + let key: [u8; 16] = [ + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, + 0x4f, 0x3c, + ]; + let nturn = 10; + let aescipher = Aes::new(&key, &nturn); + let ciphertext: [u8; 16] = aescipher.encrypt_block(&cleartext); + let expected_ciphertext: [u8; 16] = [ + 0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, + 0x0b, 0x32, + ]; + assert_eq!(ciphertext, expected_ciphertext); + } } diff --git a/src/main.rs b/src/main.rs index e7a11a9..33a0761 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,25 @@ +mod aes; +use aes::Aes; fn main() { - println!("Hello, world!"); + let key: [u8; 16] = [ + 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); + } }