use crate::kat_json::{Value, hex_to_32, hex_to_bytes, parse_rsp, read_json, vector_path};
use crate::ml_dsa::{MlDsa44, MlDsa65, MlDsa87, Params, dsa};
fn run_siggen<P: Params>(param_set: &str) {
let data = read_json(&vector_path("ML-DSA-sigGen-FIPS204/internalProjection.json"));
let mut tested = 0;
for group in data.get_array("testGroups") {
if group.get_str("parameterSet") != param_set {
continue;
}
if group.get_str("signatureInterface") != "internal" {
continue;
}
let det = matches!(group.get("deterministic"), Some(Value::Bool(true)));
for tc in group.get_array("tests").iter() {
if !tc.has("message") {
continue;
}
let sk = hex_to_bytes(tc.get_str("sk"));
let m_prime = hex_to_bytes(tc.get_str("message"));
let expected = hex_to_bytes(tc.get_str("signature"));
let rnd = if det { [0u8; 32] } else { hex_to_32(tc.get_str("rnd")) };
let sig = dsa::sign_internal::<P>(&sk, &m_prime, &rnd)
.unwrap_or_else(|_| panic!("{param_set} tc {}: sign_internal failed", tc.get_u64("tcId")));
assert_eq!(
sig.as_slice(),
expected.as_slice(),
"{param_set} tc {}: sig mismatch",
tc.get_u64("tcId")
);
tested += 1;
}
}
eprintln!("{param_set} siggen (internal): {tested} vectors passed");
assert!(tested > 0, "{param_set}: no internal sigGen vectors exercised");
}
fn run_sigver<P: Params>(param_set: &str) {
let data = read_json(&vector_path("ML-DSA-sigVer-FIPS204/internalProjection.json"));
let mut tested = 0;
for group in data.get_array("testGroups") {
if group.get_str("parameterSet") != param_set {
continue;
}
if group.get_str("signatureInterface") != "internal" {
continue;
}
for tc in group.get_array("tests").iter() {
if !tc.has("message") {
continue;
}
let pk = hex_to_bytes(tc.get_str("pk"));
let m_prime = hex_to_bytes(tc.get_str("message"));
let sig = hex_to_bytes(tc.get_str("signature"));
let test_passed = matches!(tc.get("testPassed"), Some(Value::Bool(true)) | None);
let verified = dsa::verify_internal::<P>(&pk, &m_prime, &sig).unwrap_or(false);
assert_eq!(
verified,
test_passed,
"{param_set} tc {}: verify expected {test_passed} got {verified}",
tc.get_u64("tcId")
);
tested += 1;
}
}
eprintln!("{param_set} sigver (internal): {tested} vectors tested");
assert!(tested > 0, "{param_set}: no internal sigVer vectors exercised");
}
fn run_det_raw<P: Params>(file: &str, label: &str) {
let vectors = parse_rsp(&vector_path(file));
let mut ok = 0u32;
for v in &vectors {
let count = v.get("count").map(String::as_str).unwrap_or("?");
let xi = hex_to_32(v.get("xi").expect("missing xi"));
let msg = hex_to_bytes(v.get("msg").expect("missing msg")); let sm = hex_to_bytes(v.get("sm").expect("missing sm"));
let (_pk, sk) = dsa::keygen_internal::<P>(&xi);
let sig = dsa::sign_internal::<P>(&sk, &msg, &[0u8; 32])
.unwrap_or_else(|_| panic!("{label} count {count}: sign failed"));
let expected_sig = &sm[..sm.len() - msg.len()]; assert_eq!(sig.as_slice(), expected_sig, "{label} count {count}: sig mismatch");
ok += 1;
}
eprintln!("{label}: {ok} det_raw vectors passed (sign_internal)");
assert!(ok > 0, "{label}: no det_raw vectors exercised");
}
#[test]
fn siggen_internal_44() {
run_siggen::<MlDsa44>("ML-DSA-44");
}
#[test]
fn siggen_internal_65() {
run_siggen::<MlDsa65>("ML-DSA-65");
}
#[test]
fn siggen_internal_87() {
run_siggen::<MlDsa87>("ML-DSA-87");
}
#[test]
fn sigver_internal_44() {
run_sigver::<MlDsa44>("ML-DSA-44");
}
#[test]
fn sigver_internal_65() {
run_sigver::<MlDsa65>("ML-DSA-65");
}
#[test]
fn sigver_internal_87() {
run_sigver::<MlDsa87>("ML-DSA-87");
}
#[test]
fn det_raw_44() {
run_det_raw::<MlDsa44>("kat/kat_MLDSA_44_det_raw.rsp", "ML-DSA-44-det-raw");
}
#[test]
fn det_raw_65() {
run_det_raw::<MlDsa65>("kat/kat_MLDSA_65_det_raw.rsp", "ML-DSA-65-det-raw");
}
#[test]
fn det_raw_87() {
run_det_raw::<MlDsa87>("kat/kat_MLDSA_87_det_raw.rsp", "ML-DSA-87-det-raw");
}