gpv_test.go raw

   1  package ring
   2  
   3  import (
   4  	"testing"
   5  )
   6  
   7  // TestGPVSignVerify verifies basic sign/verify round-trip.
   8  func TestGPVSignVerify(t *testing.T) {
   9  	gp := SmallGPVParams()
  10  	pk, sk := GPVKeyGen(gp)
  11  
  12  	msg := []byte("hello lattice world")
  13  	sig := GPVSign(sk, msg)
  14  
  15  	if !GPVVerify(pk, msg, sig) {
  16  		t.Fatal("valid signature rejected")
  17  	}
  18  }
  19  
  20  // TestGPVWrongMessage verifies signature doesn't verify for wrong message.
  21  func TestGPVWrongMessage(t *testing.T) {
  22  	gp := SmallGPVParams()
  23  	pk, sk := GPVKeyGen(gp)
  24  
  25  	msg := []byte("correct message")
  26  	sig := GPVSign(sk, msg)
  27  
  28  	if GPVVerify(pk, []byte("wrong message"), sig) {
  29  		t.Fatal("signature verified for wrong message")
  30  	}
  31  }
  32  
  33  // TestGPVWrongKey verifies signature doesn't verify with wrong key.
  34  func TestGPVWrongKey(t *testing.T) {
  35  	gp := SmallGPVParams()
  36  	_, sk1 := GPVKeyGen(gp)
  37  	pk2, _ := GPVKeyGen(gp)
  38  
  39  	msg := []byte("test message")
  40  	sig := GPVSign(sk1, msg)
  41  
  42  	if GPVVerify(pk2, msg, sig) {
  43  		t.Fatal("signature verified with wrong public key")
  44  	}
  45  }
  46  
  47  // TestGPVMultipleMessages verifies multiple sign/verify cycles.
  48  func TestGPVMultipleMessages(t *testing.T) {
  49  	gp := SmallGPVParams()
  50  	pk, sk := GPVKeyGen(gp)
  51  
  52  	messages := []string{
  53  		"",
  54  		"a",
  55  		"hello",
  56  		"the quick brown fox jumps over the lazy dog",
  57  		"lattice-based cryptography is the future",
  58  	}
  59  
  60  	for _, msg := range messages {
  61  		sig := GPVSign(sk, []byte(msg))
  62  		if !GPVVerify(pk, []byte(msg), sig) {
  63  			t.Fatalf("verification failed for message %q", msg)
  64  		}
  65  	}
  66  }
  67  
  68  // TestGPVSignatureShortness verifies that signatures are actually short.
  69  func TestGPVSignatureShortness(t *testing.T) {
  70  	gp := SmallGPVParams()
  71  	_, sk := GPVKeyGen(gp)
  72  
  73  	msg := []byte("test shortness")
  74  	sig := GPVSign(sk, msg)
  75  
  76  	zNorm := Norm(sig.E1)
  77  	cNorm := Norm(sig.E2)
  78  
  79  	t.Logf("||z||_∞ = %d, ||c||_∞ = %d, bound = %d",
  80  		zNorm, cNorm, uint32(gp.Sigma*1.5))
  81  
  82  	// z should be within the bound.
  83  	if zNorm > uint32(gp.Sigma*1.5) {
  84  		t.Errorf("z norm %d exceeds bound %d", zNorm, uint32(gp.Sigma*1.5))
  85  	}
  86  
  87  	// c should have small coefficients (±1 or 0).
  88  	if cNorm > 1 {
  89  		t.Errorf("c norm %d should be ≤ 1", cNorm)
  90  	}
  91  }
  92  
  93  // TestGPVDifferentSignatures verifies that signing the same message
  94  // produces different signatures (due to randomness).
  95  func TestGPVDifferentSignatures(t *testing.T) {
  96  	gp := SmallGPVParams()
  97  	pk, sk := GPVKeyGen(gp)
  98  
  99  	msg := []byte("determinism check")
 100  	sig1 := GPVSign(sk, msg)
 101  	sig2 := GPVSign(sk, msg)
 102  
 103  	// Both should verify.
 104  	if !GPVVerify(pk, msg, sig1) || !GPVVerify(pk, msg, sig2) {
 105  		t.Fatal("valid signatures rejected")
 106  	}
 107  
 108  	// But should be different (probabilistic signatures).
 109  	if Equal(sig1.E1, sig2.E1) && Equal(sig1.E2, sig2.E2) {
 110  		t.Fatal("two signatures are identical — randomness failure")
 111  	}
 112  }
 113  
 114  // TestGPVFalcon512Params verifies GPV works with Falcon-512 parameters.
 115  func TestGPVFalcon512Params(t *testing.T) {
 116  	gp := DefaultGPVParams()
 117  	pk, sk := GPVKeyGen(gp)
 118  
 119  	msg := []byte("Falcon-512 parameter test")
 120  	sig := GPVSign(sk, msg)
 121  
 122  	if !GPVVerify(pk, msg, sig) {
 123  		t.Fatal("Falcon-512 signature rejected")
 124  	}
 125  
 126  	zNorm := Norm(sig.E1)
 127  	t.Logf("Falcon-512: ||z||_∞ = %d, σ = %.1f, bound = %d",
 128  		zNorm, gp.Sigma, uint32(gp.Sigma*1.5))
 129  }
 130  
 131  func BenchmarkGPVKeyGen(b *testing.B) {
 132  	gp := SmallGPVParams()
 133  	for range b.N {
 134  		GPVKeyGen(gp)
 135  	}
 136  }
 137  
 138  func BenchmarkGPVSign(b *testing.B) {
 139  	gp := SmallGPVParams()
 140  	_, sk := GPVKeyGen(gp)
 141  	msg := []byte("benchmark message")
 142  	b.ResetTimer()
 143  	for range b.N {
 144  		GPVSign(sk, msg)
 145  	}
 146  }
 147  
 148  func BenchmarkGPVVerify(b *testing.B) {
 149  	gp := SmallGPVParams()
 150  	pk, sk := GPVKeyGen(gp)
 151  	msg := []byte("benchmark message")
 152  	sig := GPVSign(sk, msg)
 153  	b.ResetTimer()
 154  	for range b.N {
 155  		GPVVerify(pk, msg, sig)
 156  	}
 157  }
 158