mirror of
https://github.com/saymrwulf/fips205-source.git
synced 2026-09-04 20:03:45 +00:00
prep update
This commit is contained in:
parent
fca844d470
commit
8c03d1f9c3
12 changed files with 531 additions and 490 deletions
|
|
@ -1,8 +1,10 @@
|
|||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use fips205::traits::{KeyGen, Signer, Verifier};
|
||||
use fips205::{slh_dsa_sha2_128s, slh_dsa_shake_128s, slh_dsa_sha2_128f, slh_dsa_shake_128f,
|
||||
slh_dsa_sha2_192s, slh_dsa_shake_192s, slh_dsa_sha2_192f, slh_dsa_shake_192f,
|
||||
slh_dsa_sha2_256s, slh_dsa_shake_256s, slh_dsa_sha2_256f, slh_dsa_shake_256f};
|
||||
use fips205::{
|
||||
slh_dsa_sha2_128f, slh_dsa_sha2_128s, slh_dsa_sha2_192f, slh_dsa_sha2_192s, slh_dsa_sha2_256f,
|
||||
slh_dsa_sha2_256s, slh_dsa_shake_128f, slh_dsa_shake_128s, slh_dsa_shake_192f,
|
||||
slh_dsa_shake_192s, slh_dsa_shake_256f, slh_dsa_shake_256s,
|
||||
};
|
||||
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
|
|
@ -49,31 +51,79 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function("shake_192s keygen", |b| b.iter(|| slh_dsa_shake_192s::KG::try_keygen_vt()));
|
||||
c.bench_function("shake_256s keygen", |b| b.iter(|| slh_dsa_shake_256s::KG::try_keygen_vt()));
|
||||
//
|
||||
c.bench_function("sha2_128f sign ", |b| b.iter(|| sk_sha2_128f.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("sha2_192f sign ", |b| b.iter(|| sk_sha2_192f.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("sha2_256f sign ", |b| b.iter(|| sk_sha2_256f.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("shake_128f sign ", |b| b.iter(|| sk_shake_128f.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("shake_192f sign ", |b| b.iter(|| sk_shake_192f.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("shake_256f sign ", |b| b.iter(|| sk_shake_256f.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("sha2_128s sign ", |b| b.iter(|| sk_sha2_128s.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("sha2_192s sign ", |b| b.iter(|| sk_sha2_192s.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("sha2_256s sign ", |b| b.iter(|| sk_sha2_256s.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("shake_128s sign ", |b| b.iter(|| sk_shake_128s.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("shake_192s sign ", |b| b.iter(|| sk_shake_192s.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("shake_256s sign ", |b| b.iter(|| sk_shake_256s.try_sign_ct(&message, randomize)));
|
||||
c.bench_function("sha2_128f sign ", |b| {
|
||||
b.iter(|| sk_sha2_128f.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("sha2_192f sign ", |b| {
|
||||
b.iter(|| sk_sha2_192f.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("sha2_256f sign ", |b| {
|
||||
b.iter(|| sk_sha2_256f.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("shake_128f sign ", |b| {
|
||||
b.iter(|| sk_shake_128f.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("shake_192f sign ", |b| {
|
||||
b.iter(|| sk_shake_192f.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("shake_256f sign ", |b| {
|
||||
b.iter(|| sk_shake_256f.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("sha2_128s sign ", |b| {
|
||||
b.iter(|| sk_sha2_128s.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("sha2_192s sign ", |b| {
|
||||
b.iter(|| sk_sha2_192s.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("sha2_256s sign ", |b| {
|
||||
b.iter(|| sk_sha2_256s.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("shake_128s sign ", |b| {
|
||||
b.iter(|| sk_shake_128s.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("shake_192s sign ", |b| {
|
||||
b.iter(|| sk_shake_192s.try_sign_ct(&message, randomize))
|
||||
});
|
||||
c.bench_function("shake_256s sign ", |b| {
|
||||
b.iter(|| sk_shake_256s.try_sign_ct(&message, randomize))
|
||||
});
|
||||
//
|
||||
c.bench_function("sha2_128f verify", |b| b.iter(|| pk_sha2_128f.try_verify_vt(&message, &sig_sha2_128f)));
|
||||
c.bench_function("sha2_192f verify", |b| b.iter(|| pk_sha2_192f.try_verify_vt(&message, &sig_sha2_192f)));
|
||||
c.bench_function("sha2_256f verify", |b| b.iter(|| pk_sha2_256f.try_verify_vt(&message, &sig_sha2_256f)));
|
||||
c.bench_function("shake_128f verify", |b| b.iter(|| pk_shake_128f.try_verify_vt(&message, &sig_shake_128f)));
|
||||
c.bench_function("shake_192f verify", |b| b.iter(|| pk_shake_192f.try_verify_vt(&message, &sig_shake_192f)));
|
||||
c.bench_function("shake_256f verify", |b| b.iter(|| pk_shake_256f.try_verify_vt(&message, &sig_shake_256f)));
|
||||
c.bench_function("sha2_128s verify", |b| b.iter(|| pk_sha2_128s.try_verify_vt(&message, &sig_sha2_128s)));
|
||||
c.bench_function("sha2_192s verify", |b| b.iter(|| pk_sha2_192s.try_verify_vt(&message, &sig_sha2_192s)));
|
||||
c.bench_function("sha2_256s verify", |b| b.iter(|| pk_sha2_256s.try_verify_vt(&message, &sig_sha2_256s)));
|
||||
c.bench_function("shake_128s verify", |b| b.iter(|| pk_shake_128s.try_verify_vt(&message, &sig_shake_128s)));
|
||||
c.bench_function("shake_192s verify", |b| b.iter(|| pk_shake_192s.try_verify_vt(&message, &sig_shake_192s)));
|
||||
c.bench_function("shake_256s verify", |b| b.iter(|| pk_shake_256s.try_verify_vt(&message, &sig_shake_256s)));
|
||||
c.bench_function("sha2_128f verify", |b| {
|
||||
b.iter(|| pk_sha2_128f.try_verify_vt(&message, &sig_sha2_128f))
|
||||
});
|
||||
c.bench_function("sha2_192f verify", |b| {
|
||||
b.iter(|| pk_sha2_192f.try_verify_vt(&message, &sig_sha2_192f))
|
||||
});
|
||||
c.bench_function("sha2_256f verify", |b| {
|
||||
b.iter(|| pk_sha2_256f.try_verify_vt(&message, &sig_sha2_256f))
|
||||
});
|
||||
c.bench_function("shake_128f verify", |b| {
|
||||
b.iter(|| pk_shake_128f.try_verify_vt(&message, &sig_shake_128f))
|
||||
});
|
||||
c.bench_function("shake_192f verify", |b| {
|
||||
b.iter(|| pk_shake_192f.try_verify_vt(&message, &sig_shake_192f))
|
||||
});
|
||||
c.bench_function("shake_256f verify", |b| {
|
||||
b.iter(|| pk_shake_256f.try_verify_vt(&message, &sig_shake_256f))
|
||||
});
|
||||
c.bench_function("sha2_128s verify", |b| {
|
||||
b.iter(|| pk_sha2_128s.try_verify_vt(&message, &sig_sha2_128s))
|
||||
});
|
||||
c.bench_function("sha2_192s verify", |b| {
|
||||
b.iter(|| pk_sha2_192s.try_verify_vt(&message, &sig_sha2_192s))
|
||||
});
|
||||
c.bench_function("sha2_256s verify", |b| {
|
||||
b.iter(|| pk_sha2_256s.try_verify_vt(&message, &sig_sha2_256s))
|
||||
});
|
||||
c.bench_function("shake_128s verify", |b| {
|
||||
b.iter(|| pk_shake_128s.try_verify_vt(&message, &sig_shake_128s))
|
||||
});
|
||||
c.bench_function("shake_192s verify", |b| {
|
||||
b.iter(|| pk_shake_192s.try_verify_vt(&message, &sig_shake_192s))
|
||||
});
|
||||
c.bench_function("shake_256s verify", |b| {
|
||||
b.iter(|| pk_shake_256s.try_verify_vt(&message, &sig_shake_256s))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, criterion_benchmark);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::convert::TryInto;
|
||||
use fips205;
|
||||
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
||||
use std::convert::TryInto;
|
||||
|
||||
use std::os::raw::c_int;
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ pub extern "C" fn slh_dsa_sha2_128f_keygen(
|
|||
) -> u8 {
|
||||
//use fips205::traits::{KeyGen, SerDes};
|
||||
|
||||
let (Some(public_out), Some(private_out)) = (public_out, private_out) else {
|
||||
let (Some(public_out), Some(private_out)) = (public_out, private_out) else {
|
||||
return SLH_DSA_NULL_PTR_ERROR;
|
||||
};
|
||||
let Ok((pk, sk)) = fips205::slh_dsa_sha2_128f::KG::try_keygen_vt() else {
|
||||
|
|
@ -58,8 +58,7 @@ pub extern "C" fn slh_dsa_sha2_128f_keygen(
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slh_dsa_sha2_128f_sign(
|
||||
message_buf: *const u8,
|
||||
message_len: c_int,
|
||||
message_buf: *const u8, message_len: c_int,
|
||||
private_key: Option<&mut slh_dsa_sha2_128f_private_key>,
|
||||
signature_out: Option<&mut slh_dsa_sha2_128f_signature>,
|
||||
) -> u8 {
|
||||
|
|
@ -67,9 +66,12 @@ pub extern "C" fn slh_dsa_sha2_128f_sign(
|
|||
return SLH_DSA_NULL_PTR_ERROR;
|
||||
};
|
||||
|
||||
if message_buf.is_null() {return SLH_DSA_NULL_PTR_ERROR};
|
||||
if message_buf.is_null() {
|
||||
return SLH_DSA_NULL_PTR_ERROR;
|
||||
};
|
||||
|
||||
let message = unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
||||
let message =
|
||||
unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
||||
|
||||
let Ok(sk) = fips205::slh_dsa_sha2_128f::PrivateKey::try_from_bytes(&private_key.data) else {
|
||||
return SLH_DSA_DESERIALIZATION_ERROR;
|
||||
|
|
@ -83,22 +85,24 @@ pub extern "C" fn slh_dsa_sha2_128f_sign(
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slh_dsa_sha2_128f_verify(
|
||||
message_buf: *const u8,
|
||||
message_len: c_int,
|
||||
message_buf: *const u8, message_len: c_int,
|
||||
public_key: Option<&mut slh_dsa_sha2_128f_public_key>,
|
||||
signature: Option<&mut slh_dsa_sha2_128f_signature>,
|
||||
) -> u8 {
|
||||
let (Some(public_key), Some(signature)) = (public_key, signature) else {
|
||||
return SLH_DSA_NULL_PTR_ERROR;
|
||||
};
|
||||
let message = unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
||||
let message =
|
||||
unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
||||
|
||||
let Ok(sk) = fips205::slh_dsa_sha2_128f::PublicKey::try_from_bytes(&public_key.data) else {
|
||||
return SLH_DSA_DESERIALIZATION_ERROR;
|
||||
};
|
||||
let res = sk.try_verify_vt(&message, &signature.data);
|
||||
|
||||
if res.is_ok() && res.unwrap() { SLH_DSA_OK } else { SLH_DSA_VERIFY_ERROR }
|
||||
if res.is_ok() && res.unwrap() {
|
||||
SLH_DSA_OK
|
||||
} else {
|
||||
SLH_DSA_VERIFY_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -230,12 +230,12 @@ impl Adrs {
|
|||
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
|
||||
|
||||
#[cfg(any(
|
||||
feature = "slh_dsa_shake_128f",
|
||||
feature = "slh_dsa_shake_128s",
|
||||
feature = "slh_dsa_shake_192f",
|
||||
feature = "slh_dsa_shake_192s",
|
||||
feature = "slh_dsa_shake_256f",
|
||||
feature = "slh_dsa_shake_256s"
|
||||
feature = "slh_dsa_shake_128f",
|
||||
feature = "slh_dsa_shake_128s",
|
||||
feature = "slh_dsa_shake_192f",
|
||||
feature = "slh_dsa_shake_192s",
|
||||
feature = "slh_dsa_shake_256f",
|
||||
feature = "slh_dsa_shake_256s"
|
||||
))]
|
||||
pub(crate) fn to_32_bytes(&self) -> [u8; 32] {
|
||||
let mut ret = [0u8; 32];
|
||||
|
|
@ -250,12 +250,12 @@ impl Adrs {
|
|||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "slh_dsa_sha2_128f",
|
||||
feature = "slh_dsa_sha2_128s",
|
||||
feature = "slh_dsa_sha2_192f",
|
||||
feature = "slh_dsa_sha2_192s",
|
||||
feature = "slh_dsa_sha2_256f",
|
||||
feature = "slh_dsa_sha2_256s"
|
||||
feature = "slh_dsa_sha2_128f",
|
||||
feature = "slh_dsa_sha2_128s",
|
||||
feature = "slh_dsa_sha2_192f",
|
||||
feature = "slh_dsa_sha2_192s",
|
||||
feature = "slh_dsa_sha2_256f",
|
||||
feature = "slh_dsa_sha2_256s"
|
||||
))]
|
||||
pub(crate) fn to_22_bytes(&self) -> [u8; 22] {
|
||||
let mut ret = [0u8; 22];
|
||||
|
|
|
|||
|
|
@ -262,8 +262,8 @@ macro_rules! functionality {
|
|||
fn simple_round_trips() {
|
||||
let mut message = [0u8, 1, 2, 3];
|
||||
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
|
||||
for i in 0..5 {
|
||||
message[3] = i as u8;
|
||||
for i in 0..5u8 {
|
||||
message[3] = i;
|
||||
let (pk1, sk1) = KG::try_keygen_with_rng_vt(&mut rng).unwrap();
|
||||
let pk1_bytes = pk1.into_bytes();
|
||||
let pk2 = PublicKey::try_from_bytes(&pk1_bytes).unwrap();
|
||||
|
|
@ -272,7 +272,7 @@ macro_rules! functionality {
|
|||
let sig = sk2.try_sign_with_rng_ct(&mut rng, &message, true).unwrap();
|
||||
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
||||
assert_eq!(result, true, "Signature failed to verify");
|
||||
message[3] = (i + 1) as u8;
|
||||
message[3] = (i + 1);
|
||||
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
||||
assert_eq!(result, false, "Signature should not have verified");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ pub struct XmssSig<const HP: usize, const LEN: usize, const N: usize> {
|
|||
|
||||
impl<const HP: usize, const LEN: usize, const N: usize> XmssSig<HP, LEN, N> {
|
||||
pub(crate) fn get_wots_sig(&self) -> &WotsSig<LEN, N> { &self.sig_wots }
|
||||
|
||||
pub(crate) fn get_xmss_auth(&self) -> &[[u8; N]; HP] { &self.auth }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,435 +0,0 @@
|
|||
/// Runs tests using data from exports posted by NIST in their ACVP-Server repository
|
||||
/// ACVP: Automated Cryptographic Validation Protocol
|
||||
///
|
||||
/// Repo: https://github.com/usnistgov/ACVP-Server/
|
||||
///
|
||||
/// Test files:
|
||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-keyGen-FIPS205/internalProjection.json
|
||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigGen-FIPS205/internalProjection.json
|
||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigVer-FIPS205/internalProjection.json
|
||||
///
|
||||
#[cfg(test)]
|
||||
mod acvp_json_tests {
|
||||
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use serde_json::Value;
|
||||
use std::fs::File;
|
||||
use std::panic;
|
||||
|
||||
fn dehex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let buf = String::deserialize(deserializer)?;
|
||||
hex::decode(buf).map_err(serde::de::Error::custom)
|
||||
}
|
||||
|
||||
struct TestRng {
|
||||
data: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl RngCore for TestRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn fill_bytes(&mut self, out: &mut [u8]) {
|
||||
let x = self.data.pop().expect("TestRng problem");
|
||||
out.copy_from_slice(&x)
|
||||
}
|
||||
|
||||
fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
|
||||
self.fill_bytes(out);
|
||||
Ok(()) // panic on probs is OK
|
||||
}
|
||||
}
|
||||
|
||||
impl CryptoRng for TestRng {}
|
||||
|
||||
impl TestRng {
|
||||
fn new() -> Self {
|
||||
TestRng { data: Vec::new() }
|
||||
}
|
||||
|
||||
fn push(&mut self, new_data: &[u8]) {
|
||||
let x = new_data.to_vec();
|
||||
self.data.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct KeyGenTest {
|
||||
tc_id: usize,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk_seed: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk_prf: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
pk_seed: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
pk: Vec<u8>,
|
||||
}
|
||||
|
||||
macro_rules! test_keygen {
|
||||
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
||||
for test in $test_group["tests"].as_array().unwrap() {
|
||||
let test: KeyGenTest = serde_json::from_value(test.clone()).unwrap();
|
||||
print!(
|
||||
"Testing key generation with {} test case id {}... ",
|
||||
$param_set, test.tc_id
|
||||
);
|
||||
|
||||
// Pre-load RNG
|
||||
let mut rnd = TestRng::new();
|
||||
rnd.push(&test.pk_seed);
|
||||
rnd.push(&test.sk_prf);
|
||||
rnd.push(&test.sk_seed);
|
||||
|
||||
// Generate key
|
||||
let (pk, sk) = KG::try_keygen_with_rng_vt(&mut rnd).unwrap();
|
||||
|
||||
// Check against known answers
|
||||
let pk_match = pk.into_bytes() == test.pk.as_slice();
|
||||
let sk_match = sk.into_bytes() == test.sk.as_slice();
|
||||
if pk_match && sk_match {
|
||||
println!("Passed.")
|
||||
} else {
|
||||
println!("Failed.");
|
||||
$fail_count += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_keygen_tests() {
|
||||
let mut fail_count = 0;
|
||||
let file = "tests/SLH-DSA-keyGen-FIPS205/internalProjection.json";
|
||||
let keygen_kat_file = File::open(file).expect("Error opening json file");
|
||||
let kat_json: Value =
|
||||
serde_json::from_reader(keygen_kat_file).expect("Error parsing json file");
|
||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "keyGen");
|
||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||
match param_set {
|
||||
"SLH-DSA-SHA2-128s" => {
|
||||
use fips205::slh_dsa_sha2_128s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128s" => {
|
||||
use fips205::slh_dsa_shake_128s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-128f" => {
|
||||
use fips205::slh_dsa_sha2_128f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128f" => {
|
||||
use fips205::slh_dsa_shake_128f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192s" => {
|
||||
use fips205::slh_dsa_sha2_192s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192s" => {
|
||||
use fips205::slh_dsa_shake_192s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192f" => {
|
||||
use fips205::slh_dsa_sha2_192f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192f" => {
|
||||
use fips205::slh_dsa_shake_192f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256s" => {
|
||||
use fips205::slh_dsa_sha2_256s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256s" => {
|
||||
use fips205::slh_dsa_shake_256s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256f" => {
|
||||
use fips205::slh_dsa_sha2_256f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256f" => {
|
||||
use fips205::slh_dsa_shake_256f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
_ => {
|
||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(fail_count, 0);
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct SignTest {
|
||||
tc_id: usize,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex", default)]
|
||||
additional_randomness: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
message: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
signature: Vec<u8>,
|
||||
}
|
||||
|
||||
macro_rules! test_sign {
|
||||
($test_group: ident, $param_set: ident, $deterministic:ident, $fail_count: ident) => {
|
||||
for test in $test_group["tests"].as_array().unwrap() {
|
||||
let test: SignTest = serde_json::from_value(test.clone()).unwrap();
|
||||
print!("Testing signing with {}, test case {}... ", $param_set, test.tc_id);
|
||||
|
||||
// Load private key
|
||||
let sk = PrivateKey::try_from_bytes(
|
||||
test.sk
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Wrong length private key"),
|
||||
)
|
||||
.expect("Unable to load private key");
|
||||
|
||||
// Calculate signature
|
||||
let sig_exp = if $deterministic {
|
||||
sk.try_sign_ct(&test.message, false)
|
||||
.expect("Error signing message")
|
||||
} else {
|
||||
let mut rnd = TestRng::new();
|
||||
rnd.push(test.additional_randomness.as_slice());
|
||||
sk.try_sign_with_rng_ct(&mut rnd, &test.message, true)
|
||||
.expect("Error signing message")
|
||||
};
|
||||
|
||||
// Check against known answer
|
||||
if sig_exp == test.signature.as_slice() {
|
||||
println!("Passed.");
|
||||
} else {
|
||||
println!("Failed.");
|
||||
$fail_count += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_signing_tests() {
|
||||
let mut fail_count = 0;
|
||||
let file = "tests/SLH-DSA-sigGen-FIPS205/internalProjection.json";
|
||||
let sign_kat_file = File::open(file).expect("Error opening json file");
|
||||
let kat_json: Value =
|
||||
serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigGen");
|
||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||
let deterministic = test_group["deterministic"].as_bool().unwrap();
|
||||
match param_set {
|
||||
"SLH-DSA-SHA2-128s" => {
|
||||
use fips205::slh_dsa_sha2_128s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128s" => {
|
||||
use fips205::slh_dsa_shake_128s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-128f" => {
|
||||
use fips205::slh_dsa_sha2_128f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128f" => {
|
||||
use fips205::slh_dsa_shake_128f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192s" => {
|
||||
use fips205::slh_dsa_sha2_192s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192s" => {
|
||||
use fips205::slh_dsa_shake_192s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192f" => {
|
||||
use fips205::slh_dsa_sha2_192f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192f" => {
|
||||
use fips205::slh_dsa_shake_192f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256s" => {
|
||||
use fips205::slh_dsa_sha2_256s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256s" => {
|
||||
use fips205::slh_dsa_shake_256s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256f" => {
|
||||
use fips205::slh_dsa_sha2_256f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256f" => {
|
||||
use fips205::slh_dsa_shake_256f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
_ => {
|
||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(fail_count, 0);
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct VerifyTest {
|
||||
tc_id: usize,
|
||||
test_passed: bool,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
pk: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
message: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
signature: Vec<u8>,
|
||||
reason: String,
|
||||
}
|
||||
|
||||
macro_rules! test_verify {
|
||||
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
||||
for test in $test_group["tests"].as_array().unwrap() {
|
||||
let test: VerifyTest = serde_json::from_value(test.clone()).unwrap();
|
||||
print!(
|
||||
"Testing signing with {}, test case {}... ",
|
||||
$param_set,
|
||||
test.tc_id,
|
||||
);
|
||||
|
||||
if test.test_passed == false {
|
||||
println!("\nExpecting failed validation for: {}", test.reason);
|
||||
}
|
||||
|
||||
let is_valid: Result<bool, _> = panic::catch_unwind(|| {
|
||||
// Load public key
|
||||
let pk = PublicKey::try_from_bytes(
|
||||
test.pk
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Wrong length public key"),
|
||||
)
|
||||
.expect("Unable to load public key");
|
||||
|
||||
// Verify signature
|
||||
pk.try_verify_vt(
|
||||
test.message.as_slice(),
|
||||
test.signature
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Signature length incorrect"),
|
||||
)
|
||||
.expect("Verification failed")
|
||||
});
|
||||
|
||||
// Check against known answer
|
||||
let is_valid = match is_valid {
|
||||
Ok(true) => true,
|
||||
Ok(false) => false,
|
||||
Err(_) => false,
|
||||
};
|
||||
if is_valid == test.test_passed {
|
||||
println!("Passed.");
|
||||
} else {
|
||||
println!("Failed.");
|
||||
$fail_count += 1;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_verification_tests() {
|
||||
let mut fail_count = 0;
|
||||
let file = "tests/SLH-DSA-sigVer-FIPS205/internalProjection.json";
|
||||
let sign_kat_file = File::open(file).expect("Error opening json file");
|
||||
let kat_json: Value =
|
||||
serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigVer");
|
||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||
match param_set {
|
||||
"SLH-DSA-SHA2-128s" => {
|
||||
use fips205::slh_dsa_sha2_128s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128s" => {
|
||||
use fips205::slh_dsa_shake_128s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-128f" => {
|
||||
use fips205::slh_dsa_sha2_128f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128f" => {
|
||||
use fips205::slh_dsa_shake_128f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192s" => {
|
||||
use fips205::slh_dsa_sha2_192s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192s" => {
|
||||
use fips205::slh_dsa_shake_192s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192f" => {
|
||||
use fips205::slh_dsa_sha2_192f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192f" => {
|
||||
use fips205::slh_dsa_shake_192f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256s" => {
|
||||
use fips205::slh_dsa_sha2_256s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256s" => {
|
||||
use fips205::slh_dsa_shake_256s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256f" => {
|
||||
use fips205::slh_dsa_sha2_256f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256f" => {
|
||||
use fips205::slh_dsa_shake_256f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
_ => {
|
||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(fail_count, 0);
|
||||
}
|
||||
}
|
||||
1
tests/integration.rs
Normal file
1
tests/integration.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
mod nist_acvp_vectors;
|
||||
File diff suppressed because one or more lines are too long
416
tests/nist_acvp_vectors/mod.rs
Normal file
416
tests/nist_acvp_vectors/mod.rs
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
/// Runs tests using data from exports posted by NIST in their ACVP-Server repository
|
||||
/// ACVP: Automated Cryptographic Validation Protocol
|
||||
///
|
||||
/// Repo: https://github.com/usnistgov/ACVP-Server/
|
||||
///
|
||||
/// Test files:
|
||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-keyGen-FIPS205/internalProjection.json
|
||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigGen-FIPS205/internalProjection.json
|
||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigVer-FIPS205/internalProjection.json
|
||||
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use serde_json::Value;
|
||||
use std::fs::File;
|
||||
use std::panic;
|
||||
|
||||
fn dehex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let buf = String::deserialize(deserializer)?;
|
||||
hex::decode(buf).map_err(serde::de::Error::custom)
|
||||
}
|
||||
|
||||
struct TestRng {
|
||||
data: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl RngCore for TestRng {
|
||||
fn next_u32(&mut self) -> u32 { unimplemented!() }
|
||||
|
||||
fn next_u64(&mut self) -> u64 { unimplemented!() }
|
||||
|
||||
fn fill_bytes(&mut self, out: &mut [u8]) {
|
||||
let x = self.data.pop().expect("TestRng problem");
|
||||
out.copy_from_slice(&x)
|
||||
}
|
||||
|
||||
fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
|
||||
self.fill_bytes(out);
|
||||
Ok(()) // panic on probs is OK
|
||||
}
|
||||
}
|
||||
|
||||
impl CryptoRng for TestRng {}
|
||||
|
||||
impl TestRng {
|
||||
fn new() -> Self { TestRng { data: Vec::new() } }
|
||||
|
||||
fn push(&mut self, new_data: &[u8]) {
|
||||
let x = new_data.to_vec();
|
||||
self.data.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct KeyGenTest {
|
||||
tc_id: usize,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk_seed: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk_prf: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
pk_seed: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
pk: Vec<u8>,
|
||||
}
|
||||
|
||||
macro_rules! test_keygen {
|
||||
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
||||
for test in $test_group["tests"].as_array().unwrap() {
|
||||
let test: KeyGenTest = serde_json::from_value(test.clone()).unwrap();
|
||||
print!("Testing key generation with {} test case id {}... ", $param_set, test.tc_id);
|
||||
|
||||
// Pre-load RNG
|
||||
let mut rnd = TestRng::new();
|
||||
rnd.push(&test.pk_seed);
|
||||
rnd.push(&test.sk_prf);
|
||||
rnd.push(&test.sk_seed);
|
||||
|
||||
// Generate key
|
||||
let (pk, sk) = KG::try_keygen_with_rng_vt(&mut rnd).unwrap();
|
||||
|
||||
// Check against known answers
|
||||
let pk_match = pk.into_bytes() == test.pk.as_slice();
|
||||
let sk_match = sk.into_bytes() == test.sk.as_slice();
|
||||
if pk_match && sk_match {
|
||||
println!("Passed.")
|
||||
} else {
|
||||
println!("Failed.");
|
||||
$fail_count += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_keygen_tests() {
|
||||
let mut fail_count = 0;
|
||||
let file = "tests/nist_acvp_vectors/SLH-DSA-keyGen-FIPS205/internalProjection.json";
|
||||
let keygen_kat_file = File::open(file).expect("Error opening json file");
|
||||
let kat_json: Value =
|
||||
serde_json::from_reader(keygen_kat_file).expect("Error parsing json file");
|
||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "keyGen");
|
||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||
match param_set {
|
||||
"SLH-DSA-SHA2-128s" => {
|
||||
use fips205::slh_dsa_sha2_128s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128s" => {
|
||||
use fips205::slh_dsa_shake_128s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-128f" => {
|
||||
use fips205::slh_dsa_sha2_128f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128f" => {
|
||||
use fips205::slh_dsa_shake_128f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192s" => {
|
||||
use fips205::slh_dsa_sha2_192s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192s" => {
|
||||
use fips205::slh_dsa_shake_192s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192f" => {
|
||||
use fips205::slh_dsa_sha2_192f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192f" => {
|
||||
use fips205::slh_dsa_shake_192f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256s" => {
|
||||
use fips205::slh_dsa_sha2_256s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256s" => {
|
||||
use fips205::slh_dsa_shake_256s::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256f" => {
|
||||
use fips205::slh_dsa_sha2_256f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256f" => {
|
||||
use fips205::slh_dsa_shake_256f::KG;
|
||||
test_keygen!(test_group, param_set, fail_count);
|
||||
}
|
||||
_ => {
|
||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(fail_count, 0);
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct SignTest {
|
||||
tc_id: usize,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
sk: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex", default)]
|
||||
additional_randomness: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
message: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
signature: Vec<u8>,
|
||||
}
|
||||
|
||||
macro_rules! test_sign {
|
||||
($test_group: ident, $param_set: ident, $deterministic:ident, $fail_count: ident) => {
|
||||
for test in $test_group["tests"].as_array().unwrap() {
|
||||
let test: SignTest = serde_json::from_value(test.clone()).unwrap();
|
||||
print!("Testing signing with {}, test case {}... ", $param_set, test.tc_id);
|
||||
|
||||
// Load private key
|
||||
let sk = PrivateKey::try_from_bytes(
|
||||
test.sk
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Wrong length private key"),
|
||||
)
|
||||
.expect("Unable to load private key");
|
||||
|
||||
// Calculate signature
|
||||
let sig_exp = if $deterministic {
|
||||
sk.try_sign_ct(&test.message, false)
|
||||
.expect("Error signing message")
|
||||
} else {
|
||||
let mut rnd = TestRng::new();
|
||||
rnd.push(test.additional_randomness.as_slice());
|
||||
sk.try_sign_with_rng_ct(&mut rnd, &test.message, true)
|
||||
.expect("Error signing message")
|
||||
};
|
||||
|
||||
// Check against known answer
|
||||
if sig_exp == test.signature.as_slice() {
|
||||
println!("Passed.");
|
||||
} else {
|
||||
println!("Failed.");
|
||||
$fail_count += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_signing_tests() {
|
||||
let mut fail_count = 0;
|
||||
let file = "tests/nist_acvp_vectors/SLH-DSA-sigGen-FIPS205/internalProjection.json";
|
||||
let sign_kat_file = File::open(file).expect("Error opening json file");
|
||||
let kat_json: Value = serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigGen");
|
||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||
let deterministic = test_group["deterministic"].as_bool().unwrap();
|
||||
match param_set {
|
||||
"SLH-DSA-SHA2-128s" => {
|
||||
use fips205::slh_dsa_sha2_128s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128s" => {
|
||||
use fips205::slh_dsa_shake_128s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-128f" => {
|
||||
use fips205::slh_dsa_sha2_128f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128f" => {
|
||||
use fips205::slh_dsa_shake_128f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192s" => {
|
||||
use fips205::slh_dsa_sha2_192s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192s" => {
|
||||
use fips205::slh_dsa_shake_192s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192f" => {
|
||||
use fips205::slh_dsa_sha2_192f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192f" => {
|
||||
use fips205::slh_dsa_shake_192f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256s" => {
|
||||
use fips205::slh_dsa_sha2_256s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256s" => {
|
||||
use fips205::slh_dsa_shake_256s::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256f" => {
|
||||
use fips205::slh_dsa_sha2_256f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256f" => {
|
||||
use fips205::slh_dsa_shake_256f::PrivateKey;
|
||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||
}
|
||||
_ => {
|
||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(fail_count, 0);
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct VerifyTest {
|
||||
tc_id: usize,
|
||||
test_passed: bool,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
pk: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
message: Vec<u8>,
|
||||
#[serde(deserialize_with = "dehex")]
|
||||
signature: Vec<u8>,
|
||||
reason: String,
|
||||
}
|
||||
|
||||
macro_rules! test_verify {
|
||||
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
||||
for test in $test_group["tests"].as_array().unwrap() {
|
||||
let test: VerifyTest = serde_json::from_value(test.clone()).unwrap();
|
||||
print!("Testing signing with {}, test case {}... ", $param_set, test.tc_id,);
|
||||
|
||||
if test.test_passed == false {
|
||||
println!("\nExpecting failed validation for: {}", test.reason);
|
||||
}
|
||||
|
||||
let is_valid: Result<bool, _> = panic::catch_unwind(|| {
|
||||
// Load public key
|
||||
let pk = PublicKey::try_from_bytes(
|
||||
test.pk
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Wrong length public key"),
|
||||
)
|
||||
.expect("Unable to load public key");
|
||||
|
||||
// Verify signature
|
||||
pk.try_verify_vt(
|
||||
test.message.as_slice(),
|
||||
test.signature
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Signature length incorrect"),
|
||||
)
|
||||
.expect("Verification failed")
|
||||
});
|
||||
|
||||
// Check against known answer
|
||||
let is_valid = match is_valid {
|
||||
Ok(true) => true,
|
||||
Ok(false) => false,
|
||||
Err(_) => false,
|
||||
};
|
||||
if is_valid == test.test_passed {
|
||||
println!("Passed.");
|
||||
} else {
|
||||
println!("Failed.");
|
||||
$fail_count += 1;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_verification_tests() {
|
||||
let mut fail_count = 0;
|
||||
let file = "tests/nist_acvp_vectors/SLH-DSA-sigVer-FIPS205/internalProjection.json";
|
||||
let sign_kat_file = File::open(file).expect("Error opening json file");
|
||||
let kat_json: Value = serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigVer");
|
||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||
match param_set {
|
||||
"SLH-DSA-SHA2-128s" => {
|
||||
use fips205::slh_dsa_sha2_128s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128s" => {
|
||||
use fips205::slh_dsa_shake_128s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-128f" => {
|
||||
use fips205::slh_dsa_sha2_128f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-128f" => {
|
||||
use fips205::slh_dsa_shake_128f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192s" => {
|
||||
use fips205::slh_dsa_sha2_192s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192s" => {
|
||||
use fips205::slh_dsa_shake_192s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-192f" => {
|
||||
use fips205::slh_dsa_sha2_192f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-192f" => {
|
||||
use fips205::slh_dsa_shake_192f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256s" => {
|
||||
use fips205::slh_dsa_sha2_256s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256s" => {
|
||||
use fips205::slh_dsa_shake_256s::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHA2-256f" => {
|
||||
use fips205::slh_dsa_sha2_256f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
"SLH-DSA-SHAKE-256f" => {
|
||||
use fips205::slh_dsa_shake_256f::PublicKey;
|
||||
test_verify!(test_group, param_set, fail_count);
|
||||
}
|
||||
_ => {
|
||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(fail_count, 0);
|
||||
}
|
||||
Loading…
Reference in a new issue