use sz_orm_crypto::{hmac_sha256, AesGcmCrypter, PasswordHasher, Pbkdf2Hasher};
fn hex(s: &str) -> Vec<u8> {
(0..s.len())
.step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
.collect()
}
#[test]
fn kat_sha256_nist_vectors() {
assert_eq!(
sz_orm_crypto::sha256_hex(b"abc"),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);
assert_eq!(
sz_orm_crypto::sha256_hex(b""),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
let long = vec![b'a'; 1_000_000];
assert_eq!(
sz_orm_crypto::sha256_hex(&long),
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
);
}
#[test]
fn kat_hmac_sha256_rfc4231() {
let key1 = vec![0x0b; 20];
assert_eq!(
hmac_sha256(&key1, b"Hi There").to_vec(),
hex("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7")
);
assert_eq!(
hmac_sha256(b"Jefe", b"what do ya want for nothing?").to_vec(),
hex("5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843")
);
}
#[test]
fn kat_pbkdf2_sha256_python_vectors() {
let hasher = Pbkdf2Hasher::new();
let c1 = "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b";
let hash_c1 = format!("$1$73616c74${c1}");
let verify_c1 = hasher.verify("password", &hash_c1);
assert!(
matches!(verify_c1, Err(sz_orm_crypto::CryptoError::InvalidHash(_))),
"c=1 低迭代哈希必须被拒绝(M-8 修复)"
);
let c2 = "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43";
let hash_c2 = format!("$2$73616c74${c2}");
let verify_c2 = hasher.verify("password", &hash_c2);
assert!(
matches!(verify_c2, Err(sz_orm_crypto::CryptoError::InvalidHash(_))),
"c=2 低迭代哈希必须被拒绝(M-8 修复)"
);
let hashed = hasher.hash("password").unwrap();
assert!(hasher.verify("password", &hashed).unwrap());
assert!(!hasher.verify("wrong", &hashed).unwrap());
}
#[test]
fn kat_aes256gcm_roundtrip_and_tamper() {
let key: [u8; 32] = *b"0123456789abcdef0123456789abcdef";
let cipher = AesGcmCrypter::new(&key);
let plaintext = b"attack-at-dawn-2026";
let aad = b"header-v1";
let ct = cipher.encrypt_with_aad(plaintext, aad).unwrap();
let pt = cipher.decrypt_with_aad(&ct, aad).unwrap();
assert_eq!(pt, plaintext);
let mut tampered = ct.clone();
let last = tampered.len() - 1;
tampered[last] ^= 0x01;
assert!(
cipher.decrypt_with_aad(&tampered, aad).is_err(),
"篡改密文必须认证失败"
);
assert!(
cipher.decrypt_with_aad(&ct, b"wrong-aad").is_err(),
"AAD 不匹配必须认证失败"
);
assert!(cipher.decrypt_with_aad(&[0u8; 4], aad).is_err());
}