Portable AES256 expansion.
This commit is contained in:
@@ -1,8 +1,3 @@
|
||||
const AES128_KEY_LENGTH: usize = 4; // Nk
|
||||
const AES128_BLOCK_SIZE: usize = 4; // Nb
|
||||
const AES128_NUM_ROUNDS: usize = 10; // Nr
|
||||
const AES128_STATE_WORDS: usize = AES128_BLOCK_SIZE * (AES128_NUM_ROUNDS + 1);
|
||||
|
||||
const RIJNDAEL_KEY_SCHEDULE: [u32; 11] = [
|
||||
0x00000000, 0x01000000, 0x02000000, 0x04000000,
|
||||
0x08000000, 0x10000000, 0x20000000, 0x40000000,
|
||||
@@ -28,10 +23,6 @@ const SUB_BYTES_SBOX: [u8; 256] = [
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
];
|
||||
|
||||
struct AES128 {
|
||||
expanded: [u32; AES128_STATE_WORDS]
|
||||
}
|
||||
|
||||
fn word(a: u8, b: u8, c: u8, d: u8) -> u32 {
|
||||
((a as u32) << 24) | ((b as u32) << 16) |
|
||||
((c as u32) << 08) | ((d as u32) << 00)
|
||||
@@ -48,6 +39,21 @@ fn sub_word(x: u32) -> u32 {
|
||||
(((SUB_BYTES_SBOX[((x >> 00) & 0xff) as usize]) as u32) << 00)
|
||||
}
|
||||
|
||||
/**************************************************************************************************/
|
||||
/* */
|
||||
/* AES256 Implementation */
|
||||
/* */
|
||||
/**************************************************************************************************/
|
||||
|
||||
const AES128_KEY_LENGTH: usize = 4; // Nk
|
||||
const AES128_BLOCK_SIZE: usize = 4; // Nb
|
||||
const AES128_NUM_ROUNDS: usize = 10; // Nr
|
||||
const AES128_STATE_WORDS: usize = AES128_BLOCK_SIZE * (AES128_NUM_ROUNDS + 1);
|
||||
|
||||
struct AES128 {
|
||||
expanded: [u32; AES128_STATE_WORDS]
|
||||
}
|
||||
|
||||
impl AES128 {
|
||||
pub fn new(base_key: &[u8; 16]) -> AES128 {
|
||||
let mut expanded = [0; AES128_STATE_WORDS];
|
||||
@@ -151,3 +157,145 @@ mod aes128 {
|
||||
assert_eq!(expanded.expanded[43], 0xb6630ca6);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************************************/
|
||||
/* */
|
||||
/* AES256 Implementation */
|
||||
/* */
|
||||
/**************************************************************************************************/
|
||||
|
||||
const AES256_KEY_LENGTH: usize = 8; // Nk
|
||||
const AES256_BLOCK_SIZE: usize = 4; // Nb
|
||||
const AES256_NUM_ROUNDS: usize = 14; // Nr
|
||||
const AES256_STATE_WORDS: usize = AES256_BLOCK_SIZE * (AES256_NUM_ROUNDS + 1);
|
||||
|
||||
struct AES256 {
|
||||
expanded: [u32; AES256_STATE_WORDS]
|
||||
}
|
||||
|
||||
impl AES256 {
|
||||
pub fn new(base_key: &[u8; 32]) -> AES256 {
|
||||
let mut expanded = [0; AES256_STATE_WORDS];
|
||||
let mut i = 0;
|
||||
|
||||
// while (i < Nk)
|
||||
// w[i] = word(key[4*i],key[4*i+1],key[4*i+2],key[4*i+3])
|
||||
// i = i+1
|
||||
// end while
|
||||
while i < AES256_KEY_LENGTH {
|
||||
expanded[i] = word(base_key[(4*i)+0], base_key[(4*i)+1],
|
||||
base_key[(4*i)+2], base_key[(4*i)+3]);
|
||||
println!("{:02}: expanded[{}] = {:08x}", i, i, expanded[i]);
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
// i = Nk
|
||||
assert_eq!(i, AES256_KEY_LENGTH);
|
||||
|
||||
// while (i < Nb * (Nr + 1))
|
||||
while i < AES256_BLOCK_SIZE * (AES256_NUM_ROUNDS+1) {
|
||||
// temp = w[i-1]
|
||||
let mut temp = expanded[i-1];
|
||||
println!("{:02}: temp = {:08x}", i, temp);
|
||||
// if (i mod Nk = 0)
|
||||
// temp = sub_word(rot_word(temp)) xor Rcon[i/Nk]
|
||||
// else
|
||||
// temp = sub_word(temp)
|
||||
// end if
|
||||
if i % AES256_KEY_LENGTH == 0 {
|
||||
temp = rot_word(temp);
|
||||
println!("{:02}: after rotword = {:08x}", i, temp);
|
||||
temp = sub_word(temp);
|
||||
println!("{:02}: after subword = {:08x}", i, temp);
|
||||
temp ^= RIJNDAEL_KEY_SCHEDULE[i/AES256_KEY_LENGTH];
|
||||
println!("{:02}: after rcon xor = {:08x}", i, temp);
|
||||
} else if i % 4 == 0 {
|
||||
temp = sub_word(temp);
|
||||
println!("{:02}: after subword' = {:08x}", i, temp);
|
||||
}
|
||||
// w[i] = w[i-Nk] ^ temp;
|
||||
println!("{:02}: w[{}-{}] = {:08x}", i, i, AES256_KEY_LENGTH, expanded[i-AES256_KEY_LENGTH]);
|
||||
expanded[i] = expanded[i-AES256_KEY_LENGTH] ^ temp;
|
||||
println!("{:02}: expanded[{:02}] = {:08x}", i, i, expanded[i]);
|
||||
// i = i + 1
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
AES256{ expanded }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod aes256 {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn fips197_key_expansion_example() {
|
||||
let cipher_key = [0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,
|
||||
0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,
|
||||
0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,
|
||||
0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4];
|
||||
let expanded = AES256::new(&cipher_key);
|
||||
assert_eq!(expanded.expanded[00], 0x603deb10);
|
||||
assert_eq!(expanded.expanded[01], 0x15ca71be);
|
||||
assert_eq!(expanded.expanded[02], 0x2b73aef0);
|
||||
assert_eq!(expanded.expanded[03], 0x857d7781);
|
||||
assert_eq!(expanded.expanded[04], 0x1f352c07);
|
||||
assert_eq!(expanded.expanded[05], 0x3b6108d7);
|
||||
assert_eq!(expanded.expanded[06], 0x2d9810a3);
|
||||
assert_eq!(expanded.expanded[07], 0x0914dff4);
|
||||
assert_eq!(expanded.expanded[08], 0x9ba35411);
|
||||
assert_eq!(expanded.expanded[09], 0x8e6925af);
|
||||
assert_eq!(expanded.expanded[10], 0xa51a8b5f);
|
||||
assert_eq!(expanded.expanded[11], 0x2067fcde);
|
||||
assert_eq!(expanded.expanded[12], 0xa8b09c1a);
|
||||
assert_eq!(expanded.expanded[13], 0x93d194cd);
|
||||
assert_eq!(expanded.expanded[14], 0xbe49846e);
|
||||
assert_eq!(expanded.expanded[15], 0xb75d5b9a);
|
||||
assert_eq!(expanded.expanded[16], 0xd59aecb8);
|
||||
assert_eq!(expanded.expanded[17], 0x5bf3c917);
|
||||
assert_eq!(expanded.expanded[18], 0xfee94248);
|
||||
assert_eq!(expanded.expanded[19], 0xde8ebe96);
|
||||
assert_eq!(expanded.expanded[20], 0xb5a9328a);
|
||||
assert_eq!(expanded.expanded[21], 0x2678a647);
|
||||
assert_eq!(expanded.expanded[22], 0x98312229);
|
||||
assert_eq!(expanded.expanded[23], 0x2f6c79b3);
|
||||
assert_eq!(expanded.expanded[24], 0x812c81ad);
|
||||
assert_eq!(expanded.expanded[25], 0xdadf48ba);
|
||||
assert_eq!(expanded.expanded[26], 0x24360af2);
|
||||
assert_eq!(expanded.expanded[27], 0xfab8b464);
|
||||
assert_eq!(expanded.expanded[28], 0x98c5bfc9);
|
||||
assert_eq!(expanded.expanded[29], 0xbebd198e);
|
||||
assert_eq!(expanded.expanded[30], 0x268c3ba7);
|
||||
assert_eq!(expanded.expanded[31], 0x09e04214);
|
||||
assert_eq!(expanded.expanded[32], 0x68007bac);
|
||||
assert_eq!(expanded.expanded[33], 0xb2df3316);
|
||||
assert_eq!(expanded.expanded[34], 0x96e939e4);
|
||||
assert_eq!(expanded.expanded[35], 0x6c518d80);
|
||||
assert_eq!(expanded.expanded[36], 0xc814e204);
|
||||
assert_eq!(expanded.expanded[37], 0x76a9fb8a);
|
||||
assert_eq!(expanded.expanded[38], 0x5025c02d);
|
||||
assert_eq!(expanded.expanded[39], 0x59c58239);
|
||||
assert_eq!(expanded.expanded[40], 0xde136967);
|
||||
assert_eq!(expanded.expanded[41], 0x6ccc5a71);
|
||||
assert_eq!(expanded.expanded[42], 0xfa256395);
|
||||
assert_eq!(expanded.expanded[43], 0x9674ee15);
|
||||
assert_eq!(expanded.expanded[44], 0x5886ca5d);
|
||||
assert_eq!(expanded.expanded[45], 0x2e2f31d7);
|
||||
assert_eq!(expanded.expanded[46], 0x7e0af1fa);
|
||||
assert_eq!(expanded.expanded[47], 0x27cf73c3);
|
||||
assert_eq!(expanded.expanded[48], 0x749c47ab);
|
||||
assert_eq!(expanded.expanded[49], 0x18501dda);
|
||||
assert_eq!(expanded.expanded[50], 0xe2757e4f);
|
||||
assert_eq!(expanded.expanded[51], 0x7401905a);
|
||||
assert_eq!(expanded.expanded[52], 0xcafaaae3);
|
||||
assert_eq!(expanded.expanded[53], 0xe4d59b34);
|
||||
assert_eq!(expanded.expanded[54], 0x9adf6ace);
|
||||
assert_eq!(expanded.expanded[55], 0xbd10190d);
|
||||
assert_eq!(expanded.expanded[56], 0xfe4890d1);
|
||||
assert_eq!(expanded.expanded[57], 0xe6188d0b);
|
||||
assert_eq!(expanded.expanded[58], 0x046df344);
|
||||
assert_eq!(expanded.expanded[59], 0x706c631e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user