#![cfg(feature = "std")]
use pqc_combo::*;
mod nist_kem_vectors {
use super::*;
#[test]
fn test_kem_keygen_vector_1() {
let seed_hex = "061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA100000000000000000000000000000000";
let seed_bytes = hex::decode(seed_hex).expect("Invalid hex");
let seed: [u8; 64] = seed_bytes.try_into().expect("Wrong length");
let keys = KyberKeys::generate_key_pair_with_seed(seed);
assert_eq!(keys.pk.as_slice().len(), ML_KEM_1024_PK_BYTES);
assert_eq!(keys.sk.as_slice().len(), ML_KEM_1024_SK_BYTES);
println!("✓ KEM KeyGen Vector 1 passed");
}
#[test]
fn test_kem_encaps_vector_1() {
let keygen_seed_hex = "7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4700000000000000000000000000000000";
let keygen_seed_bytes = hex::decode(keygen_seed_hex).unwrap();
let keygen_seed: [u8; 64] = keygen_seed_bytes.try_into().unwrap();
let encap_seed_hex = "1679015C2D90D6B5EFE3F4F8F6F8F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4";
let encap_seed_bytes = hex::decode(encap_seed_hex).unwrap();
let encap_seed: [u8; 32] = encap_seed_bytes.try_into().unwrap();
let keys = KyberKeys::generate_key_pair_with_seed(keygen_seed);
let (ct, ss) = encapsulate_shared_secret_with_randomness(&keys.pk, encap_seed);
assert_eq!(ct.as_slice().len(), ML_KEM_1024_CT_BYTES);
assert_eq!(ss.len(), ML_KEM_1024_SS_BYTES);
assert!(ss.iter().any(|&b| b != 0), "Shared secret is all zeros");
let ss_decap = decapsulate_shared_secret(&keys.sk, &ct);
assert_eq!(ss, ss_decap);
println!("✓ KEM Encaps Vector 1 passed");
}
#[test]
fn test_kem_determinism() {
let seed = [0x42; 64];
let encap_seed = [0x43; 32];
let keys1 = KyberKeys::generate_key_pair_with_seed(seed);
let keys2 = KyberKeys::generate_key_pair_with_seed(seed);
assert_eq!(keys1.pk.as_slice(), keys2.pk.as_slice());
assert_eq!(keys1.sk.as_slice(), keys2.sk.as_slice());
let (ct1, ss1) = encapsulate_shared_secret_with_randomness(&keys1.pk, encap_seed);
let (ct2, ss2) = encapsulate_shared_secret_with_randomness(&keys2.pk, encap_seed);
assert_eq!(ct1.as_slice(), ct2.as_slice());
assert_eq!(ss1, ss2);
println!("✓ KEM Determinism test passed");
}
#[test]
fn test_kem_wrong_key() {
let seed1 = [0x01; 64];
let seed2 = [0x02; 64];
let keys1 = KyberKeys::generate_key_pair_with_seed(seed1);
let keys2 = KyberKeys::generate_key_pair_with_seed(seed2);
let (ct, ss_correct) = encapsulate_shared_secret(&keys1.pk);
let ss_wrong = decapsulate_shared_secret(&keys2.sk, &ct);
assert_ne!(ss_correct, ss_wrong);
println!("✓ KEM Wrong Key test passed");
}
}
mod nist_dsa_vectors {
use super::*;
#[test]
fn test_dsa_keygen_vector_1() {
let seed_hex = "7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2D";
let seed_bytes = hex::decode(seed_hex).expect("Invalid hex");
let seed: [u8; 32] = seed_bytes.try_into().expect("Wrong length");
let (pk, sk) = generate_dilithium_keypair_with_seed(seed);
assert_eq!(pk.as_slice().len(), ML_DSA_65_PK_BYTES);
assert_eq!(sk.as_slice().len(), ML_DSA_65_SK_BYTES);
assert!(pk.as_slice().iter().any(|&b| b != 0));
assert!(sk.as_slice().iter().any(|&b| b != 0));
println!("✓ DSA KeyGen Vector 1 passed");
}
#[test]
fn test_dsa_sign_vector_1() {
let keygen_seed_hex = "061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7";
let keygen_seed_bytes = hex::decode(keygen_seed_hex).unwrap();
let keygen_seed: [u8; 32] = keygen_seed_bytes.try_into().unwrap();
let sign_seed_hex = "1679015C2D90D6B5EFE3F4F8F6F8F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4";
let sign_seed_bytes = hex::decode(sign_seed_hex).unwrap();
let sign_seed: [u8; 32] = sign_seed_bytes.try_into().unwrap();
let message = b"NIST ML-DSA Test Vector";
let (pk, sk) = generate_dilithium_keypair_with_seed(keygen_seed);
let sig = sign_message_with_randomness(&sk, message, sign_seed);
assert_eq!(sig.as_slice().len(), ML_DSA_65_SIG_BYTES);
assert!(verify_signature(&pk, message, &sig));
assert!(!verify_signature(&pk, b"wrong message", &sig));
println!("✓ DSA Sign Vector 1 passed");
}
#[test]
fn test_dsa_determinism() {
let keygen_seed = [0x42; 32];
let sign_seed = [0x43; 32];
let message = b"Deterministic test message";
let (pk1, sk1) = generate_dilithium_keypair_with_seed(keygen_seed);
let (pk2, sk2) = generate_dilithium_keypair_with_seed(keygen_seed);
assert_eq!(pk1.as_slice(), pk2.as_slice());
assert_eq!(sk1.as_slice(), sk2.as_slice());
let sig1 = sign_message_with_randomness(&sk1, message, sign_seed);
let sig2 = sign_message_with_randomness(&sk2, message, sign_seed);
assert_eq!(sig1.as_slice(), sig2.as_slice());
println!("✓ DSA Determinism test passed");
}
#[test]
fn test_dsa_wrong_key() {
let seed1 = [0x01; 32];
let seed2 = [0x02; 32];
let message = b"Test message";
let (_, sk1) = generate_dilithium_keypair_with_seed(seed1);
let (pk2, _) = generate_dilithium_keypair_with_seed(seed2);
let sig = sign_message(&sk1, message);
assert!(!verify_signature(&pk2, message, &sig));
println!("✓ DSA Wrong Key test passed");
}
}
mod interop_tests {
use super::*;
#[test]
fn test_key_serialization_roundtrip() {
let keys = KyberKeys::generate_key_pair();
let pk_slice = keys.pk.as_slice();
let sk_slice = keys.sk.as_slice();
let mut pk_array = [0u8; ML_KEM_1024_PK_BYTES];
pk_array.copy_from_slice(pk_slice);
let mut sk_array = [0u8; ML_KEM_1024_SK_BYTES];
sk_array.copy_from_slice(sk_slice);
let pk_restored = KyberPublicKey::from(pk_array);
let sk_restored = KyberSecretKey::from(sk_array);
let (ct, ss1) = encapsulate_shared_secret(&pk_restored);
let ss2 = decapsulate_shared_secret(&sk_restored, &ct);
assert_eq!(ss1, ss2);
println!("✓ Key serialization roundtrip passed");
}
#[test]
fn test_signature_serialization_roundtrip() {
let (pk, sk) = generate_dilithium_keypair();
let message = b"Test message";
let sig = sign_message(&sk, message);
let sig_bytes = sig.as_slice();
assert_eq!(sig_bytes.len(), ML_DSA_65_SIG_BYTES);
assert!(sig_bytes.iter().any(|&b| b != 0), "Signature is all zeros");
assert!(verify_signature(&pk, message, &sig));
println!("✓ Signature properties verified");
}
#[test]
fn test_cross_platform_determinism() {
let kem_seed = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
];
let dsa_seed = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
];
let kem_keys = KyberKeys::generate_key_pair_with_seed(kem_seed);
let (dsa_pk, dsa_sk) = generate_dilithium_keypair_with_seed(dsa_seed);
use sha3::{Digest, Sha3_256};
let kem_pk_hash = Sha3_256::digest(kem_keys.pk.as_slice());
let kem_sk_hash = Sha3_256::digest(kem_keys.sk.as_slice());
let dsa_pk_hash = Sha3_256::digest(dsa_pk.as_slice());
let dsa_sk_hash = Sha3_256::digest(dsa_sk.as_slice());
println!("KEM PK hash: {}", hex::encode(&kem_pk_hash));
println!("KEM SK hash: {}", hex::encode(&kem_sk_hash));
println!("DSA PK hash: {}", hex::encode(&dsa_pk_hash));
println!("DSA SK hash: {}", hex::encode(&dsa_sk_hash));
println!("✓ Cross-platform determinism test passed");
}
}
mod fips_compliance {
use super::*;
#[test]
fn test_fips_203_key_sizes() {
let keys = KyberKeys::generate_key_pair();
assert_eq!(keys.pk.as_slice().len(), 1568);
assert_eq!(keys.sk.as_slice().len(), 3168);
let (ct, ss) = encapsulate_shared_secret(&keys.pk);
assert_eq!(ct.as_slice().len(), 1568);
assert_eq!(ss.len(), 32);
println!("✓ FIPS 203 key sizes verified");
}
#[test]
fn test_fips_204_key_sizes() {
let (pk, sk) = generate_dilithium_keypair();
assert_eq!(pk.as_slice().len(), 1952);
assert_eq!(sk.as_slice().len(), 4032);
let sig = sign_message(&sk, b"test");
assert_eq!(sig.as_slice().len(), 3309);
println!("✓ FIPS 204 key sizes verified");
}
}
mod edge_cases {
use super::*;
#[test]
fn test_empty_message_signature() {
let (pk, sk) = generate_dilithium_keypair();
let empty_msg = b"";
let sig = sign_message(&sk, empty_msg);
assert!(verify_signature(&pk, empty_msg, &sig));
println!("✓ Empty message signature test passed");
}
#[test]
fn test_large_message_signature() {
let (pk, sk) = generate_dilithium_keypair();
let large_msg = vec![0x42u8; 10_000];
let sig = sign_message(&sk, &large_msg);
assert!(verify_signature(&pk, &large_msg, &sig));
println!("✓ Large message signature test passed");
}
#[test]
#[should_panic(expected = "Zero seed invalid")]
fn test_all_zero_kem_seed_rejected() {
let zero_seed = [0u8; 64];
KyberKeys::generate_key_pair_with_seed(zero_seed);
}
#[test]
#[should_panic(expected = "Zero seed invalid")]
fn test_all_zero_dsa_seed_rejected() {
let zero_seed = [0u8; 32];
generate_dilithium_keypair_with_seed(zero_seed);
}
#[test]
fn test_minimum_entropy_seeds() {
let mut min_seed_64 = [0u8; 64];
min_seed_64[0] = 1;
let mut min_seed_32 = [0u8; 32];
min_seed_32[0] = 1;
let keys = KyberKeys::generate_key_pair_with_seed(min_seed_64);
let (ct, ss1) = encapsulate_shared_secret(&keys.pk);
let ss2 = decapsulate_shared_secret(&keys.sk, &ct);
assert_eq!(ss1, ss2);
let (pk, sk) = generate_dilithium_keypair_with_seed(min_seed_32);
let sig = sign_message(&sk, b"test");
assert!(verify_signature(&pk, b"test", &sig));
println!("✓ Minimum entropy seed test passed");
}
}