mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
crypto: delete dead mldsa/.old — unreferenced legacy cgo/tests
The canonical ML-DSA package (mldsa/) is the one way; mldsa/.old was unreferenced legacy code. Build stays green (go build ./mldsa/ ok). Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
committed by
lux
co-authored by
Hanzo Dev
parent
482faf9bea
commit
c436347937
@@ -1,20 +0,0 @@
|
|||||||
//go:build cgo
|
|
||||||
// +build cgo
|
|
||||||
|
|
||||||
package mldsa
|
|
||||||
|
|
||||||
// This file contains CGO-optimized implementations that are only compiled
|
|
||||||
// when CGO is explicitly enabled with CGO_ENABLED=1
|
|
||||||
//
|
|
||||||
// CGO optimizations reserved - currently using pure Go implementation.
|
|
||||||
// Future optimizations could include:
|
|
||||||
// - ML-DSA-44/65/87 from NIST reference implementation
|
|
||||||
// - CRYSTALS-Dilithium optimized implementations
|
|
||||||
// - AVX2/AVX512 optimizations for x86_64
|
|
||||||
// - NEON optimizations for ARM64
|
|
||||||
// - Batch verification optimizations
|
|
||||||
//
|
|
||||||
// The pure Go implementation provides:
|
|
||||||
// - Full ML-DSA compliance with FIPS 204
|
|
||||||
// - Deterministic signatures
|
|
||||||
// - Cross-platform compatibility
|
|
||||||
@@ -1,409 +0,0 @@
|
|||||||
package mldsa
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMLDSAKeyGeneration(t *testing.T) {
|
|
||||||
modes := []struct {
|
|
||||||
name string
|
|
||||||
mode Mode
|
|
||||||
pubSize int
|
|
||||||
privSize int
|
|
||||||
sigSize int
|
|
||||||
}{
|
|
||||||
{"ML-DSA-44", MLDSA44, MLDSA44PublicKeySize, MLDSA44PrivateKeySize, MLDSA44SignatureSize},
|
|
||||||
{"ML-DSA-65", MLDSA65, MLDSA65PublicKeySize, MLDSA65PrivateKeySize, MLDSA65SignatureSize},
|
|
||||||
{"ML-DSA-87", MLDSA87, MLDSA87PublicKeySize, MLDSA87PrivateKeySize, MLDSA87SignatureSize},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range modes {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
// Test key generation
|
|
||||||
privKey, err := GenerateKey(rand.Reader, tt.mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check key sizes
|
|
||||||
privBytes := privKey.Bytes()
|
|
||||||
if len(privBytes) != tt.privSize {
|
|
||||||
t.Errorf("Private key size mismatch: got %d, want %d", len(privBytes), tt.privSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
pubBytes := privKey.PublicKey.Bytes()
|
|
||||||
if len(pubBytes) != tt.pubSize {
|
|
||||||
t.Errorf("Public key size mismatch: got %d, want %d", len(pubBytes), tt.pubSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test nil reader
|
|
||||||
_, err = GenerateKey(nil, tt.mode)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("GenerateKey should fail with nil reader")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMLDSASignVerify(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
privKey, err := GenerateKey(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Test message for ML-DSA signature")
|
|
||||||
|
|
||||||
// Sign message
|
|
||||||
signature, err := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Sign failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify signature
|
|
||||||
valid := privKey.PublicKey.Verify(message, signature, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Valid signature failed verification")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test invalid signature
|
|
||||||
signature[0] ^= 0xFF
|
|
||||||
valid = privKey.PublicKey.Verify(message, signature, nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Invalid signature passed verification")
|
|
||||||
}
|
|
||||||
signature[0] ^= 0xFF // restore
|
|
||||||
|
|
||||||
// Test wrong message
|
|
||||||
wrongMessage := []byte("Wrong message")
|
|
||||||
valid = privKey.PublicKey.Verify(wrongMessage, signature, nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Signature verified with wrong message")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test empty message
|
|
||||||
emptyMessage := []byte{}
|
|
||||||
emptySig, err := privKey.Sign(rand.Reader, emptyMessage, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Sign empty message failed: %v", err)
|
|
||||||
}
|
|
||||||
valid = privKey.PublicKey.Verify(emptyMessage, emptySig, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Empty message signature failed verification")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMLDSAKeySerialization(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
// Generate original key
|
|
||||||
origKey, err := GenerateKey(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize and deserialize private key using FromBytes functions
|
|
||||||
privBytes := origKey.Bytes()
|
|
||||||
newPrivKey, err := PrivateKeyFromBytes(privBytes, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("PrivateKeyFromBytes failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check keys are equal
|
|
||||||
if !bytes.Equal(origKey.Bytes(), newPrivKey.Bytes()) {
|
|
||||||
t.Error("Private key serialization failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize and deserialize public key
|
|
||||||
pubBytes := origKey.PublicKey.Bytes()
|
|
||||||
newPubKey, err := PublicKeyFromBytes(pubBytes, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("PublicKeyFromBytes failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(origKey.PublicKey.Bytes(), newPubKey.Bytes()) {
|
|
||||||
t.Error("Public key serialization failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test signature with deserialized keys
|
|
||||||
message := []byte("Test serialization")
|
|
||||||
signature, err := newPrivKey.Sign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Sign with deserialized key failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
valid := newPubKey.Verify(message, signature, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Verification with deserialized key failed")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMLDSADeterministicSignature(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
privKey, err := GenerateKey(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Randomized signature test")
|
|
||||||
|
|
||||||
// ML-DSA requires a random source - test that nil rand is rejected
|
|
||||||
_, err = privKey.Sign(nil, message, nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Sign with nil rand should fail")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign same message multiple times with proper rand
|
|
||||||
sig1, err := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("First sign failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sig2, err := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Second sign failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: The circl ML-DSA implementation may produce the same signature
|
|
||||||
// for the same message when using the same random state.
|
|
||||||
// This is implementation-specific behavior and doesn't indicate
|
|
||||||
// a security issue - the randomness is properly used internally.
|
|
||||||
t.Logf("Signature 1 length: %d, Signature 2 length: %d", len(sig1), len(sig2))
|
|
||||||
|
|
||||||
// Both signatures should verify
|
|
||||||
if !privKey.PublicKey.Verify(message, sig1, nil) {
|
|
||||||
t.Error("First signature failed verification")
|
|
||||||
}
|
|
||||||
if !privKey.PublicKey.Verify(message, sig2, nil) {
|
|
||||||
t.Error("Second signature failed verification")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMLDSAEdgeCases(t *testing.T) {
|
|
||||||
t.Run("InvalidMode", func(t *testing.T) {
|
|
||||||
_, err := GenerateKey(rand.Reader, Mode(99))
|
|
||||||
if err == nil {
|
|
||||||
t.Error("GenerateKey should fail with invalid mode")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("NilPublicKey", func(t *testing.T) {
|
|
||||||
var pubKey *PublicKey
|
|
||||||
valid := pubKey.Verify([]byte("test"), []byte("sig"), nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Nil public key should not verify")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("NilPrivateKey", func(t *testing.T) {
|
|
||||||
var privKey *PrivateKey
|
|
||||||
_, err := privKey.Sign(rand.Reader, []byte("test"), nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Nil private key should not sign")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("EmptySignature", func(t *testing.T) {
|
|
||||||
privKey, _ := GenerateKey(rand.Reader, MLDSA44)
|
|
||||||
valid := privKey.PublicKey.Verify([]byte("test"), []byte{}, nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Empty signature should not verify")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("WrongSizeSignature", func(t *testing.T) {
|
|
||||||
privKey, _ := GenerateKey(rand.Reader, MLDSA44)
|
|
||||||
// Wrong size signature
|
|
||||||
wrongSig := make([]byte, 100)
|
|
||||||
rand.Read(wrongSig)
|
|
||||||
valid := privKey.PublicKey.Verify([]byte("test"), wrongSig, nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Wrong size signature should not verify")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMLDSALargeMessage(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
privKey, err := GenerateKey(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with large message (1MB)
|
|
||||||
largeMessage := make([]byte, 1024*1024)
|
|
||||||
rand.Read(largeMessage)
|
|
||||||
|
|
||||||
signature, err := privKey.Sign(rand.Reader, largeMessage, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Sign large message failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
valid := privKey.PublicKey.Verify(largeMessage, signature, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Large message signature failed verification")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify one byte in the middle
|
|
||||||
largeMessage[512*1024] ^= 0xFF
|
|
||||||
valid = privKey.PublicKey.Verify(largeMessage, signature, nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Modified large message passed verification")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMLDSAConcurrency(t *testing.T) {
|
|
||||||
privKey, err := GenerateKey(rand.Reader, MLDSA44)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Concurrent test message")
|
|
||||||
|
|
||||||
// Test concurrent signing
|
|
||||||
t.Run("ConcurrentSign", func(t *testing.T) {
|
|
||||||
const numGoroutines = 10
|
|
||||||
done := make(chan bool, numGoroutines)
|
|
||||||
|
|
||||||
for i := 0; i < numGoroutines; i++ {
|
|
||||||
go func(id int) {
|
|
||||||
msg := append(message, byte(id))
|
|
||||||
sig, err := privKey.Sign(rand.Reader, msg, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Goroutine %d: Sign failed: %v", id, err)
|
|
||||||
}
|
|
||||||
valid := privKey.PublicKey.Verify(msg, sig, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Errorf("Goroutine %d: Verification failed", id)
|
|
||||||
}
|
|
||||||
done <- true
|
|
||||||
}(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < numGoroutines; i++ {
|
|
||||||
<-done
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Test concurrent verification
|
|
||||||
t.Run("ConcurrentVerify", func(t *testing.T) {
|
|
||||||
signature, _ := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
const numGoroutines = 10
|
|
||||||
done := make(chan bool, numGoroutines)
|
|
||||||
|
|
||||||
for i := 0; i < numGoroutines; i++ {
|
|
||||||
go func(id int) {
|
|
||||||
valid := privKey.PublicKey.Verify(message, signature, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Errorf("Goroutine %d: Verification failed", id)
|
|
||||||
}
|
|
||||||
done <- true
|
|
||||||
}(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < numGoroutines; i++ {
|
|
||||||
<-done
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMLDSAKeyGen(b *testing.B) {
|
|
||||||
modes := []struct {
|
|
||||||
name string
|
|
||||||
mode Mode
|
|
||||||
}{
|
|
||||||
{"ML-DSA-44", MLDSA44},
|
|
||||||
{"ML-DSA-65", MLDSA65},
|
|
||||||
{"ML-DSA-87", MLDSA87},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range modes {
|
|
||||||
b.Run(m.name, func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := GenerateKey(rand.Reader, m.mode)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMLDSASign(b *testing.B) {
|
|
||||||
modes := []struct {
|
|
||||||
name string
|
|
||||||
mode Mode
|
|
||||||
}{
|
|
||||||
{"ML-DSA-44", MLDSA44},
|
|
||||||
{"ML-DSA-65", MLDSA65},
|
|
||||||
{"ML-DSA-87", MLDSA87},
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Benchmark message for ML-DSA signature performance")
|
|
||||||
|
|
||||||
for _, m := range modes {
|
|
||||||
privKey, _ := GenerateKey(rand.Reader, m.mode)
|
|
||||||
|
|
||||||
b.Run(m.name, func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMLDSAVerify(b *testing.B) {
|
|
||||||
modes := []struct {
|
|
||||||
name string
|
|
||||||
mode Mode
|
|
||||||
}{
|
|
||||||
{"ML-DSA-44", MLDSA44},
|
|
||||||
{"ML-DSA-65", MLDSA65},
|
|
||||||
{"ML-DSA-87", MLDSA87},
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Benchmark message for ML-DSA verification performance")
|
|
||||||
|
|
||||||
for _, m := range modes {
|
|
||||||
privKey, _ := GenerateKey(rand.Reader, m.mode)
|
|
||||||
signature, _ := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
|
|
||||||
b.Run(m.name, func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
valid := privKey.PublicKey.Verify(message, signature, nil)
|
|
||||||
if !valid {
|
|
||||||
b.Fatal("Verification failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper functions are now in mldsa.go
|
|
||||||
@@ -1,396 +0,0 @@
|
|||||||
package mldsa
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOptimizedKeyGeneration(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
// Test optimized key generation
|
|
||||||
privKey, err := GenerateKeyOptimized(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKeyOptimized failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify key sizes
|
|
||||||
var expectedPrivSize, expectedPubSize int
|
|
||||||
switch mode {
|
|
||||||
case MLDSA44:
|
|
||||||
expectedPrivSize = MLDSA44PrivateKeySize
|
|
||||||
expectedPubSize = MLDSA44PublicKeySize
|
|
||||||
case MLDSA65:
|
|
||||||
expectedPrivSize = MLDSA65PrivateKeySize
|
|
||||||
expectedPubSize = MLDSA65PublicKeySize
|
|
||||||
case MLDSA87:
|
|
||||||
expectedPrivSize = MLDSA87PrivateKeySize
|
|
||||||
expectedPubSize = MLDSA87PublicKeySize
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(privKey.Bytes()) != expectedPrivSize {
|
|
||||||
t.Errorf("Private key size mismatch: got %d, want %d", len(privKey.Bytes()), expectedPrivSize)
|
|
||||||
}
|
|
||||||
if len(privKey.PublicKey.Bytes()) != expectedPubSize {
|
|
||||||
t.Errorf("Public key size mismatch: got %d, want %d", len(privKey.PublicKey.Bytes()), expectedPubSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test nil reader
|
|
||||||
_, err = GenerateKeyOptimized(nil, mode)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("GenerateKeyOptimized should fail with nil reader")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test invalid mode
|
|
||||||
_, err := GenerateKeyOptimized(rand.Reader, Mode(99))
|
|
||||||
if err == nil {
|
|
||||||
t.Error("GenerateKeyOptimized should fail with invalid mode")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOptimizedSign(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
privKey, err := GenerateKey(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Test message for optimized signing")
|
|
||||||
|
|
||||||
// Test optimized signing
|
|
||||||
signature, err := privKey.OptimizedSign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("OptimizedSign failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify signature
|
|
||||||
valid := privKey.PublicKey.Verify(message, signature, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Optimized signature failed verification")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with different message
|
|
||||||
wrongMessage := []byte("Wrong message")
|
|
||||||
valid = privKey.PublicKey.Verify(wrongMessage, signature, nil)
|
|
||||||
if valid {
|
|
||||||
t.Error("Signature verified with wrong message")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBatchDSA(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
numKeys := 5
|
|
||||||
batch, err := NewBatchDSA(mode, numKeys)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewBatchDSA failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare messages
|
|
||||||
messages := make([][]byte, numKeys)
|
|
||||||
for i := range messages {
|
|
||||||
messages[i] = []byte(string(rune('A'+i)) + " Test message for batch signing")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch sign
|
|
||||||
signatures, err := batch.SignBatch(messages)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("SignBatch failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(signatures) != numKeys {
|
|
||||||
t.Errorf("Expected %d signatures, got %d", numKeys, len(signatures))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batch verify
|
|
||||||
results, err := batch.VerifyBatch(messages, signatures)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("VerifyBatch failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, valid := range results {
|
|
||||||
if !valid {
|
|
||||||
t.Errorf("Signature %d failed verification", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with tampered signature
|
|
||||||
signatures[0][0] ^= 0xFF
|
|
||||||
results, err = batch.VerifyBatch(messages, signatures)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("VerifyBatch failed: %v", err)
|
|
||||||
}
|
|
||||||
if results[0] {
|
|
||||||
t.Error("Tampered signature passed verification")
|
|
||||||
}
|
|
||||||
signatures[0][0] ^= 0xFF // restore
|
|
||||||
|
|
||||||
// Test mismatched counts
|
|
||||||
wrongMessages := make([][]byte, numKeys-1)
|
|
||||||
_, err = batch.SignBatch(wrongMessages)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("SignBatch should fail with mismatched message count")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = batch.VerifyBatch(wrongMessages, signatures)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("VerifyBatch should fail with mismatched count")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrecomputedMLDSA(t *testing.T) {
|
|
||||||
modes := []Mode{MLDSA44, MLDSA65, MLDSA87}
|
|
||||||
|
|
||||||
for _, mode := range modes {
|
|
||||||
t.Run(mode.String(), func(t *testing.T) {
|
|
||||||
privKey, err := GenerateKey(rand.Reader, mode)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateKey failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
precomputed := NewPrecomputedMLDSA(privKey)
|
|
||||||
|
|
||||||
message := []byte("Test message for caching")
|
|
||||||
|
|
||||||
// First sign (cache miss)
|
|
||||||
sig1, err := precomputed.SignCached(message)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("First SignCached failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second sign (cache hit)
|
|
||||||
sig2, err := precomputed.SignCached(message)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Second SignCached failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cached signatures should be identical
|
|
||||||
if !bytes.Equal(sig1, sig2) {
|
|
||||||
t.Error("Cached signatures are not identical")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Both should verify
|
|
||||||
valid := privKey.PublicKey.Verify(message, sig1, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("First cached signature failed verification")
|
|
||||||
}
|
|
||||||
|
|
||||||
valid = privKey.PublicKey.Verify(message, sig2, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Second cached signature failed verification")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Different message should produce different signature
|
|
||||||
message2 := []byte("Different message")
|
|
||||||
sig3, err := precomputed.SignCached(message2)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("SignCached for different message failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Equal(sig1, sig3) {
|
|
||||||
t.Error("Different messages produced same signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
valid = privKey.PublicKey.Verify(message2, sig3, nil)
|
|
||||||
if !valid {
|
|
||||||
t.Error("Third cached signature failed verification")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSignatureBufferPool(t *testing.T) {
|
|
||||||
// Test getting and putting buffers
|
|
||||||
buf1 := getSignatureBuffer(MLDSA44SignatureSize)
|
|
||||||
if len(buf1) != MLDSA44SignatureSize {
|
|
||||||
t.Errorf("Expected buffer size %d, got %d", MLDSA44SignatureSize, len(buf1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return buffer to pool
|
|
||||||
putSignatureBuffer(buf1)
|
|
||||||
|
|
||||||
// Get buffer again (should get same or similar buffer from pool)
|
|
||||||
buf2 := getSignatureBuffer(MLDSA44SignatureSize)
|
|
||||||
if len(buf2) != MLDSA44SignatureSize {
|
|
||||||
t.Errorf("Expected buffer size %d, got %d", MLDSA44SignatureSize, len(buf2))
|
|
||||||
}
|
|
||||||
putSignatureBuffer(buf2)
|
|
||||||
|
|
||||||
// Test with larger size than pool default
|
|
||||||
largeBuf := getSignatureBuffer(MLDSA87SignatureSize * 2)
|
|
||||||
if len(largeBuf) != MLDSA87SignatureSize*2 {
|
|
||||||
t.Errorf("Expected buffer size %d, got %d", MLDSA87SignatureSize*2, len(largeBuf))
|
|
||||||
}
|
|
||||||
// Small buffers should not be pooled
|
|
||||||
smallBuf := make([]byte, 100)
|
|
||||||
putSignatureBuffer(smallBuf) // Should not panic
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHelperFunctions(t *testing.T) {
|
|
||||||
t.Run("SetBytes", func(t *testing.T) {
|
|
||||||
// Test PrivateKey SetBytes
|
|
||||||
privKey := NewPrivateKey(MLDSA44)
|
|
||||||
data := make([]byte, MLDSA44PrivateKeySize)
|
|
||||||
rand.Read(data)
|
|
||||||
privKey.SetBytes(data)
|
|
||||||
if !bytes.Equal(privKey.Bytes(), data) {
|
|
||||||
t.Error("PrivateKey SetBytes failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test PublicKey SetBytes
|
|
||||||
pubKey := NewPublicKey(MLDSA44)
|
|
||||||
pubData := make([]byte, MLDSA44PublicKeySize)
|
|
||||||
rand.Read(pubData)
|
|
||||||
pubKey.SetBytes(pubData)
|
|
||||||
if !bytes.Equal(pubKey.Bytes(), pubData) {
|
|
||||||
t.Error("PublicKey SetBytes failed")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("GetKeySizes", func(t *testing.T) {
|
|
||||||
// Test private key sizes
|
|
||||||
if size := getPrivateKeySize(MLDSA44); size != MLDSA44PrivateKeySize {
|
|
||||||
t.Errorf("getPrivateKeySize(MLDSA44) = %d, want %d", size, MLDSA44PrivateKeySize)
|
|
||||||
}
|
|
||||||
if size := getPrivateKeySize(MLDSA65); size != MLDSA65PrivateKeySize {
|
|
||||||
t.Errorf("getPrivateKeySize(MLDSA65) = %d, want %d", size, MLDSA65PrivateKeySize)
|
|
||||||
}
|
|
||||||
if size := getPrivateKeySize(MLDSA87); size != MLDSA87PrivateKeySize {
|
|
||||||
t.Errorf("getPrivateKeySize(MLDSA87) = %d, want %d", size, MLDSA87PrivateKeySize)
|
|
||||||
}
|
|
||||||
if size := getPrivateKeySize(Mode(99)); size != 0 {
|
|
||||||
t.Errorf("getPrivateKeySize(invalid) = %d, want 0", size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test public key sizes
|
|
||||||
if size := getPublicKeySize(MLDSA44); size != MLDSA44PublicKeySize {
|
|
||||||
t.Errorf("getPublicKeySize(MLDSA44) = %d, want %d", size, MLDSA44PublicKeySize)
|
|
||||||
}
|
|
||||||
if size := getPublicKeySize(MLDSA65); size != MLDSA65PublicKeySize {
|
|
||||||
t.Errorf("getPublicKeySize(MLDSA65) = %d, want %d", size, MLDSA65PublicKeySize)
|
|
||||||
}
|
|
||||||
if size := getPublicKeySize(MLDSA87); size != MLDSA87PublicKeySize {
|
|
||||||
t.Errorf("getPublicKeySize(MLDSA87) = %d, want %d", size, MLDSA87PublicKeySize)
|
|
||||||
}
|
|
||||||
if size := getPublicKeySize(Mode(99)); size != 0 {
|
|
||||||
t.Errorf("getPublicKeySize(invalid) = %d, want 0", size)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkOptimizedKeyGen(b *testing.B) {
|
|
||||||
modes := []struct {
|
|
||||||
name string
|
|
||||||
mode Mode
|
|
||||||
}{
|
|
||||||
{"ML-DSA-44", MLDSA44},
|
|
||||||
{"ML-DSA-65", MLDSA65},
|
|
||||||
{"ML-DSA-87", MLDSA87},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range modes {
|
|
||||||
b.Run(m.name+"-Standard", func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := GenerateKey(rand.Reader, m.mode)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
b.Run(m.name+"-Optimized", func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := GenerateKeyOptimized(rand.Reader, m.mode)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkOptimizedSign(b *testing.B) {
|
|
||||||
modes := []struct {
|
|
||||||
name string
|
|
||||||
mode Mode
|
|
||||||
}{
|
|
||||||
{"ML-DSA-44", MLDSA44},
|
|
||||||
{"ML-DSA-65", MLDSA65},
|
|
||||||
{"ML-DSA-87", MLDSA87},
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("Benchmark message for optimized signing")
|
|
||||||
|
|
||||||
for _, m := range modes {
|
|
||||||
privKey, _ := GenerateKey(rand.Reader, m.mode)
|
|
||||||
|
|
||||||
b.Run(m.name+"-Standard", func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := privKey.Sign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
b.Run(m.name+"-Optimized", func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := privKey.OptimizedSign(rand.Reader, message, nil)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkBatchOperations(b *testing.B) {
|
|
||||||
numKeys := 10
|
|
||||||
batch, _ := NewBatchDSA(MLDSA65, numKeys)
|
|
||||||
|
|
||||||
messages := make([][]byte, numKeys)
|
|
||||||
for i := range messages {
|
|
||||||
messages[i] = make([]byte, 32)
|
|
||||||
rand.Read(messages[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
b.Run("BatchSign", func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := batch.SignBatch(messages)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
signatures, _ := batch.SignBatch(messages)
|
|
||||||
|
|
||||||
b.Run("BatchVerify", func(b *testing.B) {
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := batch.VerifyBatch(messages, signatures)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user