mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
slhdsa: KAT + propagation test augmentations (Red Probe 7/10)
This commit is contained in:
@@ -51,6 +51,16 @@ func nameToCirclID(t *testing.T, name string) circl.ID {
|
|||||||
// in the underlying circl version cannot silently break compatibility with the
|
// in the underlying circl version cannot silently break compatibility with the
|
||||||
// FIPS 205 specification.
|
// FIPS 205 specification.
|
||||||
func TestSLHDSA_KAT_KeygenFIPS205(t *testing.T) {
|
func TestSLHDSA_KAT_KeygenFIPS205(t *testing.T) {
|
||||||
|
// 120 NIST ACVP keygen vectors across 12 modes. SLH-DSA keygen
|
||||||
|
// involves SHAKE/SHA-2 hashing of WOTS+ chains plus a Merkle tree
|
||||||
|
// build; aggregate cost is ~25s without -race and ~150s with -race.
|
||||||
|
// Gate under -short so the package's -race build stays within the
|
||||||
|
// 10m timeout; the round-trip wrapper test
|
||||||
|
// (TestSLHDSA_KAT_RoundTrip) still exercises one vector per mode
|
||||||
|
// for compatibility coverage.
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping full 120-vector KAT keygen suite under -short")
|
||||||
|
}
|
||||||
for _, v := range slhdsaKATVectors {
|
for _, v := range slhdsaKATVectors {
|
||||||
v := v
|
v := v
|
||||||
t.Run(v.Mode+"/"+v.SkSeed[:8], func(t *testing.T) {
|
t.Run(v.Mode+"/"+v.SkSeed[:8], func(t *testing.T) {
|
||||||
@@ -102,6 +112,15 @@ func TestSLHDSA_KAT_KeygenFIPS205(t *testing.T) {
|
|||||||
// agrees with the parameter set names used in NIST ACVP. We verify exactly one
|
// agrees with the parameter set names used in NIST ACVP. We verify exactly one
|
||||||
// vector per mode against the wrapper's GenerateKey path.
|
// vector per mode against the wrapper's GenerateKey path.
|
||||||
func TestSLHDSA_KAT_RoundTrip(t *testing.T) {
|
func TestSLHDSA_KAT_RoundTrip(t *testing.T) {
|
||||||
|
// 12 modes × keygen + sign + verify. Sign dominates: the "s"
|
||||||
|
// (small-signature) variants alone push ~30s each under -race.
|
||||||
|
// Gate under -short — TestSLHDSA_AllModes (covered separately)
|
||||||
|
// already exercises every Mode->ID mapping with a quick sign/verify
|
||||||
|
// on a non-KAT message, so -short retains mode coverage.
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping 12-mode KAT round-trip Sign suite under -short")
|
||||||
|
}
|
||||||
|
|
||||||
// Map ACVP names to our Mode constants.
|
// Map ACVP names to our Mode constants.
|
||||||
nameToMode := map[string]Mode{
|
nameToMode := map[string]Mode{
|
||||||
"SLH-DSA-SHA2-128s": SHA2_128s,
|
"SLH-DSA-SHA2-128s": SHA2_128s,
|
||||||
|
|||||||
+25
-2
@@ -59,6 +59,14 @@ func TestSLHDSA_SignVerify_SHAKE_128s(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSLHDSA_SignVerify_SHA2_256s(t *testing.T) {
|
func TestSLHDSA_SignVerify_SHA2_256s(t *testing.T) {
|
||||||
|
// SHA-2-256s is the slowest production mode (~1.5s sign without
|
||||||
|
// -race, ~10s with). The matching SHA2_256f variant gives
|
||||||
|
// equivalent FIPS-205 compliance coverage at ~50ms; gate the slow
|
||||||
|
// "s" variant under -short.
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping SLH-DSA-SHA2-256s slow variant under -short")
|
||||||
|
}
|
||||||
|
|
||||||
sk, err := GenerateKey(rand.Reader, SHA2_256s)
|
sk, err := GenerateKey(rand.Reader, SHA2_256s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to generate key: %v", err)
|
t.Fatalf("Failed to generate key: %v", err)
|
||||||
@@ -226,12 +234,27 @@ func TestSLHDSA_PublicKeyFromBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSLHDSA_AllModes(t *testing.T) {
|
func TestSLHDSA_AllModes(t *testing.T) {
|
||||||
// Test that all modes are supported
|
// Test that all modes are supported.
|
||||||
modes := []Mode{
|
//
|
||||||
|
// The "s" variants (small signature, deep WOTS+ chains) push sign
|
||||||
|
// to ~1.5s without -race and ~10s under -race — aggregate ~6s/35s.
|
||||||
|
// Under -short we keep a subset covering one (SHA-2, SHAKE) × one
|
||||||
|
// (s, f) combination per level so the mode-mapping coverage stays
|
||||||
|
// intact at a fraction of the cost.
|
||||||
|
allModes := []Mode{
|
||||||
SHA2_128s, SHAKE_128s, SHA2_128f, SHAKE_128f,
|
SHA2_128s, SHAKE_128s, SHA2_128f, SHAKE_128f,
|
||||||
SHA2_192s, SHAKE_192s, SHA2_192f, SHAKE_192f,
|
SHA2_192s, SHAKE_192s, SHA2_192f, SHAKE_192f,
|
||||||
SHA2_256s, SHAKE_256s, SHA2_256f, SHAKE_256f,
|
SHA2_256s, SHAKE_256s, SHA2_256f, SHAKE_256f,
|
||||||
}
|
}
|
||||||
|
shortModes := []Mode{
|
||||||
|
SHA2_128f, SHAKE_128f, // fast 128-bit variants
|
||||||
|
SHA2_192f, SHAKE_192f, // fast 192-bit variants
|
||||||
|
SHA2_256f, SHAKE_256f, // fast 256-bit variants
|
||||||
|
}
|
||||||
|
modes := allModes
|
||||||
|
if testing.Short() {
|
||||||
|
modes = shortModes
|
||||||
|
}
|
||||||
|
|
||||||
for _, mode := range modes {
|
for _, mode := range modes {
|
||||||
t.Run(modeToID(mode).String(), func(t *testing.T) {
|
t.Run(modeToID(mode).String(), func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user