use encryption::contract::SymmetricCipher;
use encryption::encryptor::{Aes256CbcEncryptor, Aes256GcmEncryptor, SodiumXChaCha20Encryptor};
use encryption::guomi::{Sm2Service, Sm4CbcEncryptor};
const PLAINTEXT: &[u8] = "KAT vector 已知答案向量".as_bytes();
fn key32() -> [u8; 32] {
std::array::from_fn(|i| i as u8)
}
fn key16() -> [u8; 16] {
std::array::from_fn(|i| i as u8)
}
fn hex(s: &str) -> Vec<u8> {
assert_eq!(s.len() % 2, 0, "hex 字面量长度必须为偶数");
(0..s.len() / 2)
.map(|i| u8::from_str_radix(&s[2 * i..2 * i + 2], 16).expect("非 hex 字符"))
.collect()
}
const GCM_BLOB: &str = concat!(
"7631a0a1a2a3a4a5a6a7a8a9aaabf3cc402e603216440b88169c67215267ad59",
"280d33ae61cb0d17a736b0c82741d54bf4847416ca890c9fcf01f0",
);
#[test]
fn aes256gcm_decrypts_php_openssl_vector() {
let plaintext = Aes256GcmEncryptor::new(key32())
.decrypt(&hex(GCM_BLOB))
.expect("参考实现密文应能解开");
assert_eq!(plaintext, PLAINTEXT);
}
#[test]
fn aes256gcm_rejects_tampered_reference_vector() {
let mut blob = hex(GCM_BLOB);
*blob.last_mut().unwrap() ^= 0x01;
assert!(Aes256GcmEncryptor::new(key32()).decrypt(&blob).is_err());
}
const XCHACHA_BLOB: &str = concat!(
"7631c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7bbdfdef3ea73",
"f6e78ab1fa12e3daca2f07eae6c76a193286c881702be11e65dc1e574eb2e087",
"a5ae5b0adb57b2",
);
#[test]
fn xchacha20_decrypts_php_sodium_vector() {
let plaintext = SodiumXChaCha20Encryptor::new(key32())
.decrypt(&hex(XCHACHA_BLOB))
.expect("参考实现密文应能解开");
assert_eq!(plaintext, PLAINTEXT);
}
const CBC_BLOB: &str = concat!(
"7631b0b1b2b3b4b5b6b7b8b9babbbcbdbebf1c25467a7b8847b6fa1614b62962",
"5f5f00d63a92a853b3a4716d9f3eda2669ecd3cb1667b54049dbb6248771dfaf",
"0acfdb6696cb161e360d7a69fd8a63c4f469",
);
#[test]
fn aes256cbc_hmac_decrypts_php_openssl_vector() {
let plaintext = Aes256CbcEncryptor::new(key32())
.decrypt(&hex(CBC_BLOB))
.expect("参考实现密文应能解开");
assert_eq!(plaintext, PLAINTEXT);
}
const SM4_BLOB: &str = concat!(
"7631b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc4ad1603f3268200e5ed6c2a6d1d",
"5289c92714cb7692d682ca598b799ac6d395d8cdf2fd7df48ec92704a8e3ae9f",
"682f823842b0e5937b8506a917b329e34dfa",
);
#[test]
fn sm4cbc_decrypts_php_openssl_vector() {
let plaintext = Sm4CbcEncryptor::new(key16())
.decrypt(&hex(SM4_BLOB))
.expect("参考实现密文应能解开");
assert_eq!(plaintext, PLAINTEXT);
}
const SM2_ANNEX_C_CIPHERTEXT: &str = concat!(
"04", "04EBFC718E8D1798620432268E77FEB6415E2EDE0E073C0F4F640ECD2E149A73", "E858F9D81E5430A57B36DAAB8F950A3C64E6EE6A63094D99283AFF767E124DF0", "59983C18F809E262923C53AEC295D30383B54E39D609D160AFCB1908D0BD8766", "21886CA989CA9C7D58087307CA93092D651EFA", );
#[test]
fn sm2_decrypts_gmt0003_annex_c_openssl_vector() {
const PRIVATE_KEY: &str = "3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8";
assert_eq!(SM2_ANNEX_C_CIPHERTEXT.len(), 2 * 116);
let plaintext = Sm2Service::decrypt(SM2_ANNEX_C_CIPHERTEXT, PRIVATE_KEY)
.expect("GM/T 0003.5 附录 C 密文应能解开");
assert_eq!(plaintext, b"encryption standard");
}