#![cfg(all(feature = "ml-dsa", feature = "fips_140_3"))]
use crate::error::{Result, PqcError};
use crate::generate_dilithium_keypair_with_seed;
fn test_vector_1_public_key() -> Result<()> {
const SEED: [u8; 32] = [
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 (pk, _sk) = generate_dilithium_keypair_with_seed(SEED);
let pk_bytes = pk.as_slice();
println!("DILITHIUM_PK: {:02x?}", pk_bytes);
if pk_bytes.len() != crate::ML_DSA_65_PK_BYTES {
return Err(PqcError::CastFailure);
}
let has_nonzero_data = pk_bytes.iter().any(|&b| b != 0);
if !has_nonzero_data {
return Err(PqcError::CastFailure);
}
let (pk2, _sk2) = generate_dilithium_keypair_with_seed(SEED);
let pk2_bytes = pk2.as_slice();
if pk_bytes != pk2_bytes {
return Err(PqcError::CastFailure);
}
Ok(())
}
fn test_vector_2_secret_key() -> Result<()> {
const SEED: [u8; 32] = [
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 (_pk, sk) = generate_dilithium_keypair_with_seed(SEED);
let sk_bytes = sk.as_slice();
println!("DILITHIUM_SK: {:02x?}", sk_bytes);
if sk_bytes.len() != crate::ML_DSA_65_SK_BYTES {
return Err(PqcError::CastFailure);
}
let has_nonzero_data = sk_bytes.iter().any(|&b| b != 0);
if !has_nonzero_data {
return Err(PqcError::CastFailure);
}
let (_pk2, sk2) = generate_dilithium_keypair_with_seed(SEED);
let sk2_bytes = sk2.as_slice();
if sk_bytes != sk2_bytes {
return Err(PqcError::CastFailure);
}
Ok(())
}
fn test_vector_3_signature() -> Result<()> {
const SEED: [u8; 32] = [
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,
];
const MESSAGE: &[u8] = b"FIPS 140-3 KAT";
let (pk, sk) = generate_dilithium_keypair_with_seed(SEED);
const SIGN_SEED: [u8; 32] = [
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
]; let signature = crate::sign_message_with_randomness(&sk, MESSAGE, SIGN_SEED);
let sig_bytes = signature.as_slice();
println!("DILITHIUM_SIG: {:02x?}", sig_bytes);
if sig_bytes.len() != crate::ML_DSA_65_SIG_BYTES {
return Err(PqcError::CastFailure);
}
let has_nonzero_data = sig_bytes.iter().any(|&b| b != 0);
if !has_nonzero_data {
return Err(PqcError::CastFailure);
}
let is_valid = crate::verify_signature(&pk, MESSAGE, &signature);
if !is_valid {
return Err(PqcError::CastFailure);
}
let signature2 = crate::sign_message_with_randomness(&sk, MESSAGE, SIGN_SEED);
let sig2_bytes = signature2.as_slice();
if sig_bytes != sig2_bytes {
return Err(PqcError::CastFailure);
}
const WRONG_MESSAGE: &[u8] = b"FIPS 140-3 KAX"; let is_invalid = crate::verify_signature(&pk, WRONG_MESSAGE, &signature);
if is_invalid {
return Err(PqcError::CastFailure);
}
Ok(())
}
pub fn run_dilithium_verify_kat() -> Result<()> {
test_vector_1_public_key()?;
test_vector_2_secret_key()?;
test_vector_3_signature()?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dilithium_kat() {
let result = run_dilithium_verify_kat();
assert!(result.is_ok(), "KAT should pass: {:?}", result.err());
}
#[test]
fn test_vector_1() {
let result = test_vector_1_public_key();
assert!(result.is_ok(), "Test vector 1 should pass: {:?}", result.err());
}
#[test]
fn test_vector_2() {
let result = test_vector_2_secret_key();
assert!(result.is_ok(), "Test vector 2 should pass: {:?}", result.err());
}
#[test]
fn test_vector_3() {
let result = test_vector_3_signature();
assert!(result.is_ok(), "Test vector 3 should pass: {:?}", result.err());
}
}