bip340_test.go raw

   1  package secp256k1
   2  
   3  import (
   4  	"crypto/rand"
   5  	"encoding/csv"
   6  	"encoding/hex"
   7  	"os"
   8  	"strings"
   9  	"testing"
  10  )
  11  
  12  func hexToArray(t *testing.T, s string, n int) []byte {
  13  	t.Helper()
  14  	b, err := hex.DecodeString(strings.ToLower(s))
  15  	if err != nil {
  16  		t.Fatalf("bad hex %q: %v", s, err)
  17  	}
  18  	if len(b) != n {
  19  		t.Fatalf("wanted %d bytes, got %d from %q", n, len(b), s)
  20  	}
  21  	return b
  22  }
  23  
  24  func TestBIP340Vectors(t *testing.T) {
  25  	f, err := os.Open("testdata/bip340.csv")
  26  	if err != nil {
  27  		t.Fatal(err)
  28  	}
  29  	defer f.Close()
  30  	rows, err := csv.NewReader(f).ReadAll()
  31  	if err != nil {
  32  		t.Fatal(err)
  33  	}
  34  	if len(rows) < 2 {
  35  		t.Fatal("no vectors")
  36  	}
  37  	for _, row := range rows[1:] {
  38  		if len(row) < 7 {
  39  			continue
  40  		}
  41  		name := row[0]
  42  		var sk, aux, pub [32]byte
  43  		var sig [64]byte
  44  		pubB := hexToArray(t, row[2], 32)
  45  		msgB, err := hex.DecodeString(strings.ToLower(row[4]))
  46  		if err != nil {
  47  			t.Fatalf("vector %s: bad message hex: %v", name, err)
  48  		}
  49  		sigB := hexToArray(t, row[5], 64)
  50  		copy(pub[:], pubB)
  51  		copy(sig[:], sigB)
  52  		want := strings.EqualFold(row[6], "TRUE")
  53  
  54  		got := VerifyMsg(pub, msgB, sig)
  55  		if got != want {
  56  			t.Errorf("vector %s: Verify = %v, want %v", name, got, want)
  57  		}
  58  		if !want {
  59  			continue
  60  		}
  61  
  62  		// Vectors with a secret key also pin the exact signature when the
  63  		// aux_rand is used, which tests the signing path end to end.
  64  		if row[1] == "" {
  65  			continue
  66  		}
  67  		skB := hexToArray(t, row[1], 32)
  68  		copy(sk[:], skB)
  69  		auxB := hexToArray(t, row[3], 32)
  70  		copy(aux[:], auxB)
  71  
  72  		gotPub, ok := PubKey(sk)
  73  		if !ok || gotPub != pub {
  74  			t.Errorf("vector %s: PubKey mismatch", name)
  75  		}
  76  		gotSig, ok := SignAuxMsg(sk, msgB, aux)
  77  		if !ok {
  78  			t.Errorf("vector %s: SignAux failed", name)
  79  		}
  80  		if gotSig != sig {
  81  			t.Errorf("vector %s: signature mismatch\n got %x\nwant %x", name, gotSig, sig)
  82  		}
  83  	}
  84  }
  85  
  86  func TestSignVerifyRoundTrip(t *testing.T) {
  87  	for i := 0; i < 16; i++ {
  88  		var sk [32]byte
  89  		var msg [32]byte
  90  		if _, err := rand.Read(sk[:]); err != nil {
  91  			t.Fatal(err)
  92  		}
  93  		if _, err := rand.Read(msg[:]); err != nil {
  94  			t.Fatal(err)
  95  		}
  96  		pub, ok := PubKey(sk)
  97  		if !ok {
  98  			t.Fatalf("PubKey failed for key %d", i)
  99  		}
 100  		sig, ok := Sign(sk, msg)
 101  		if !ok {
 102  			t.Fatalf("Sign failed for key %d", i)
 103  		}
 104  		if !Verify(pub, msg, sig) {
 105  			t.Fatalf("fresh signature did not verify for key %d", i)
 106  		}
 107  		// A single-bit change must invalidate the signature.
 108  		sig[0] ^= 1
 109  		if Verify(pub, msg, sig) {
 110  			t.Fatalf("corrupted signature verified for key %d", i)
 111  		}
 112  	}
 113  }
 114  
 115  // TestFastAndSlowAgree cross-checks the btcec fast path against the math/big
 116  // reference in both directions. Signatures are deterministic given aux_rand,
 117  // so the two signers must produce identical bytes.
 118  func TestFastAndSlowAgree(t *testing.T) {
 119  	for i := 0; i < 8; i++ {
 120  		var sk, msg, aux [32]byte
 121  		if _, err := rand.Read(sk[:]); err != nil {
 122  			t.Fatal(err)
 123  		}
 124  		if _, err := rand.Read(msg[:]); err != nil {
 125  			t.Fatal(err)
 126  		}
 127  		if _, err := rand.Read(aux[:]); err != nil {
 128  			t.Fatal(err)
 129  		}
 130  		pub, ok := PubKey(sk)
 131  		if !ok {
 132  			t.Fatal("PubKey failed")
 133  		}
 134  
 135  		fast, ok := signFastWithAux(sk, msg, aux)
 136  		if !ok {
 137  			t.Fatal("fast sign failed")
 138  		}
 139  		if !verifySlowMsg(pub, msg[:], fast) {
 140  			t.Fatal("slow verifier rejected the fast signature")
 141  		}
 142  		slow, ok := signSlowAuxMsg(sk, msg[:], aux)
 143  		if !ok {
 144  			t.Fatal("slow sign failed")
 145  		}
 146  		if slow != fast {
 147  			t.Fatalf("signers disagree\n fast %x\n slow %x", fast, slow)
 148  		}
 149  		if !verifyFast(pub, msg, slow) {
 150  			t.Fatal("fast verifier rejected the slow signature")
 151  		}
 152  		fast[0] ^= 1
 153  		if verifySlowMsg(pub, msg[:], fast) || verifyFast(pub, msg, fast) {
 154  			t.Fatal("tampered signature accepted")
 155  		}
 156  	}
 157  }
 158