use super::*;
use crate::types::key::SymmetricKey;
use crate::types::Nonce;
use crate::types::RandomGeneration;
use crate::ChaCha20Algorithm;
use hex;
use rand::rngs::OsRng;
#[test]
fn test_chacha20_rfc8439() {
let key =
hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap();
let nonce = hex::decode("000000000000004a00000000").unwrap();
let plaintext = hex::decode("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e")
.unwrap();
let expected_ciphertext = hex::decode("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d")
.unwrap();
let key_bytes: [u8; CHACHA20_KEY_SIZE] = key.try_into().expect("Invalid key length");
let nonce_array: [u8; CHACHA20_NONCE_SIZE] = nonce.try_into().expect("Invalid nonce length");
let nonce = Nonce::<CHACHA20_NONCE_SIZE>::new(nonce_array);
let mut chacha = ChaCha20::with_counter(&key_bytes, &nonce, 1);
let mut output = plaintext.clone();
chacha.encrypt(&mut output);
assert_eq!(output, expected_ciphertext);
let mut chacha = ChaCha20::with_counter(&key_bytes, &nonce, 1);
let mut decrypted = expected_ciphertext.clone();
chacha.decrypt(&mut decrypted);
assert_eq!(decrypted, plaintext);
}
#[test]
fn test_chacha20_keystream() {
let key = [0x42; CHACHA20_KEY_SIZE];
let nonce_array = [0x24; CHACHA20_NONCE_SIZE];
let nonce = Nonce::<CHACHA20_NONCE_SIZE>::new(nonce_array);
let mut chacha = ChaCha20::new(&key, &nonce);
let mut keystream = [0u8; 64];
chacha.keystream(&mut keystream);
let plaintext = [0x12; 64];
let mut ciphertext = plaintext;
chacha.reset();
chacha.encrypt(&mut ciphertext);
let mut expected = [0u8; 64];
for i in 0..64 {
expected[i] = plaintext[i] ^ keystream[i];
}
assert_eq!(ciphertext, expected);
}
#[test]
fn test_chacha20_seek() {
let key = [0x42; CHACHA20_KEY_SIZE];
let nonce_array = [0x24; CHACHA20_NONCE_SIZE];
let nonce = Nonce::<CHACHA20_NONCE_SIZE>::new(nonce_array);
let mut chacha1 = ChaCha20::new(&key, &nonce);
let mut chacha2 = ChaCha20::new(&key, &nonce);
let mut data = [0u8; 200];
chacha1.process(&mut data);
chacha2.seek(3);
let mut ks1 = [0u8; 64];
let mut ks2 = [0u8; 64];
chacha1.keystream(&mut ks1);
chacha2.keystream(&mut ks2);
assert_eq!(ks1, ks2);
}
#[test]
fn test_chacha20_with_secure_key() {
let key = SymmetricKey::<ChaCha20Algorithm, 32>::random(&mut OsRng).unwrap();
let nonce = Nonce::<12>::random(&mut OsRng);
let mut cipher = ChaCha20::new(key.as_ref().try_into().unwrap(), &nonce);
let plaintext = b"test message";
let mut buffer = plaintext.to_vec();
cipher.encrypt(&mut buffer);
assert_ne!(&buffer[..], plaintext);
cipher.reset();
cipher.decrypt(&mut buffer);
assert_eq!(&buffer[..], plaintext);
}
#[test]
fn test_chacha20_zeroization() {
let key = [0x42u8; 32];
let nonce = Nonce::<12>::zeroed();
let mut cipher = ChaCha20::new(&key, &nonce);
let mut keystream = [0u8; 64];
cipher.keystream(&mut keystream);
assert_ne!(keystream, [0u8; 64]);
cipher.reset();
}