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);
+ }
}