use aes::{Aes128, Aes256};
use cipher::KeyIvInit;
use eme2::{Eme2, Error};
use hex_literal::hex;
type Aes128Eme2 = Eme2<Aes128>;
type Aes256Eme2 = Eme2<Aes256>;
fn test_roundtrip(len: usize) {
let key = [0x42; 32];
let tweak = [0x11; 16];
let mut plaintext = vec![0u8; len];
for i in 0..len {
plaintext[i] = (i % 256) as u8;
}
let mut buf = plaintext.clone();
let cipher = Aes256Eme2::new(&key.into(), &tweak.into());
cipher.encrypt(&mut buf).unwrap();
assert_ne!(buf, plaintext);
assert_eq!(buf.len(), plaintext.len());
cipher.decrypt(&mut buf).unwrap();
assert_eq!(buf, plaintext);
}
#[test]
fn test_exact_block() {
test_roundtrip(16);
}
#[test]
fn test_multiple_blocks() {
test_roundtrip(32);
test_roundtrip(48);
test_roundtrip(64);
test_roundtrip(1024);
}
#[test]
fn test_partial_blocks() {
test_roundtrip(17);
test_roundtrip(31);
test_roundtrip(33);
test_roundtrip(127);
test_roundtrip(1025);
}
#[test]
fn test_data_too_short() {
let key = [0x42; 32];
let tweak = [0x11; 16];
let cipher = Aes256Eme2::new(&key.into(), &tweak.into());
let mut buf = vec![0u8; 15];
let err = cipher.encrypt(&mut buf).unwrap_err();
assert_eq!(err, Error::DataTooShort);
}
#[test]
fn test_sprp_avalanche_effect() {
let key = [0x42; 32];
let tweak = [0x11; 16];
let cipher = Aes256Eme2::new(&key.into(), &tweak.into());
let plaintext = b"This is a message that spans multiple blocks for SPRP test!!";
let mut buf1 = plaintext.to_vec();
cipher.encrypt(&mut buf1).unwrap();
let mut buf2 = buf1.clone();
buf2[25] ^= 0x01;
cipher.decrypt(&mut buf1).unwrap();
cipher.decrypt(&mut buf2).unwrap();
assert_eq!(&buf1[..], &plaintext[..]);
let diff_count = buf1.iter().zip(buf2.iter()).filter(|(a, b)| a != b).count();
assert!(diff_count > plaintext.len() / 2, "SPRP property failed, diff_count: {}", diff_count);
}
#[test]
fn test_tweak_separation() {
let key = [0x42; 32];
let tweak1 = [0x11; 16];
let tweak2 = [0x22; 16];
let plaintext = vec![0xAB; 64];
let mut buf1 = plaintext.clone();
let mut buf2 = plaintext.clone();
let cipher1 = Aes256Eme2::new(&key.into(), &tweak1.into());
let cipher2 = Aes256Eme2::new(&key.into(), &tweak2.into());
cipher1.encrypt(&mut buf1).unwrap();
cipher2.encrypt(&mut buf2).unwrap();
assert_ne!(buf1, buf2);
}
#[test]
fn test_aes128_compatibility() {
let key = [0x42; 16];
let tweak = [0x11; 16];
let cipher = Aes128Eme2::new(&key.into(), &tweak.into());
let mut buf = vec![0x00; 32];
cipher.encrypt(&mut buf).unwrap();
assert_ne!(buf, vec![0x00; 32]);
cipher.decrypt(&mut buf).unwrap();
assert_eq!(buf, vec![0x00; 32]);
}
#[test]
fn test_reference_vectors() {
let key1 = [0x00; 32];
let tweak1 = [0x01; 16];
let pt1 = [0x02; 16];
let expected_ct1 = hex!("ceaadba3ecd8dd680e172f1b3f4ed77b");
let cipher1 = Aes256Eme2::new(&key1.into(), &tweak1.into());
let mut buf1 = pt1.to_vec();
cipher1.encrypt(&mut buf1).unwrap();
assert_eq!(buf1, expected_ct1);
cipher1.decrypt(&mut buf1).unwrap();
assert_eq!(buf1, pt1);
let pt2 = [0x02; 32];
let expected_ct2 = hex!("64cc76e47aa39f0bd168c1b50d80e46d23865a2fea731ff538dc9fff4039869d");
let mut buf2 = pt2.to_vec();
cipher1.encrypt(&mut buf2).unwrap();
assert_eq!(buf2, expected_ct2);
cipher1.decrypt(&mut buf2).unwrap();
assert_eq!(buf2, pt2);
let mut key3 = [0u8; 32];
for i in 0..32 { key3[i] = (i * 3) as u8; }
let mut tweak3 = [0u8; 16];
for i in 0..16 { tweak3[i] = (i * 7) as u8; }
let mut pt3 = [0u8; 64];
for i in 0..64 { pt3[i] = i as u8; }
let expected_ct3 = hex!("f65ed34d2f7d1eff17d32b352ddcdc669b708f1c11fb2b9308aa2af412a85a7790d15b575ddde9b80ecbbcbae9767e4601c0443f563ec3a82d9f0514b4bf0b78");
let cipher3 = Aes256Eme2::new(&key3.into(), &tweak3.into());
let mut buf3 = pt3.to_vec();
cipher3.encrypt(&mut buf3).unwrap();
assert_eq!(buf3, expected_ct3);
cipher3.decrypt(&mut buf3).unwrap();
assert_eq!(buf3, pt3);
}