use crate::kat_json::{Value, hex_to_bytes, read_json, vector_path};
use crate::slh_dsa::{
Params, Sha2_128f, Sha2_128s, Sha2_192f, Sha2_192s, Sha2_256f, Sha2_256s, Shake128f, Shake128s, Shake192f,
Shake192s, Shake256f, Shake256s, slh,
};
fn run_siggen<P: Params>(param_set: &str) {
let data = read_json(&vector_path("SLH-DSA-sigGen-FIPS205/internalProjection.json"));
let mut tested = 0;
let n = P::N;
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 addrnd = if det {
sk[2 * n..3 * n].to_vec()
} else {
hex_to_bytes(tc.get_str("additionalRandomness"))
};
let sig = slh::slh_sign_internal::<P>(&m_prime, &sk, &addrnd)
.expect("KAT runs without sca-fors-redundancy — sign_internal is infallible");
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("SLH-DSA-sigVer-FIPS205/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 = slh::slh_verify_internal::<P>(&m_prime, &sig, &pk);
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");
}
macro_rules! internal_kat {
($sig:ident, $ver:ident, $p:ty, $name:literal) => {
#[test]
fn $sig() {
run_siggen::<$p>($name);
}
#[test]
fn $ver() {
run_sigver::<$p>($name);
}
};
}
internal_kat!(
siggen_internal_shake_128s,
sigver_internal_shake_128s,
Shake128s,
"SLH-DSA-SHAKE-128s"
);
internal_kat!(
siggen_internal_shake_128f,
sigver_internal_shake_128f,
Shake128f,
"SLH-DSA-SHAKE-128f"
);
internal_kat!(
siggen_internal_shake_192s,
sigver_internal_shake_192s,
Shake192s,
"SLH-DSA-SHAKE-192s"
);
internal_kat!(
siggen_internal_shake_192f,
sigver_internal_shake_192f,
Shake192f,
"SLH-DSA-SHAKE-192f"
);
internal_kat!(
siggen_internal_shake_256s,
sigver_internal_shake_256s,
Shake256s,
"SLH-DSA-SHAKE-256s"
);
internal_kat!(
siggen_internal_shake_256f,
sigver_internal_shake_256f,
Shake256f,
"SLH-DSA-SHAKE-256f"
);
internal_kat!(
siggen_internal_sha2_128s,
sigver_internal_sha2_128s,
Sha2_128s,
"SLH-DSA-SHA2-128s"
);
internal_kat!(
siggen_internal_sha2_128f,
sigver_internal_sha2_128f,
Sha2_128f,
"SLH-DSA-SHA2-128f"
);
internal_kat!(
siggen_internal_sha2_192s,
sigver_internal_sha2_192s,
Sha2_192s,
"SLH-DSA-SHA2-192s"
);
internal_kat!(
siggen_internal_sha2_192f,
sigver_internal_sha2_192f,
Sha2_192f,
"SLH-DSA-SHA2-192f"
);
internal_kat!(
siggen_internal_sha2_256s,
sigver_internal_sha2_256s,
Sha2_256s,
"SLH-DSA-SHA2-256s"
);
internal_kat!(
siggen_internal_sha2_256f,
sigver_internal_sha2_256f,
Sha2_256f,
"SLH-DSA-SHA2-256f"
);