1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
19 type zeroReader struct{}
21 func (zeroReader) Read(buf []byte) (int, error) {
28 func TestSignVerify(t *testing.T) {
30 public, private, _ := GenerateKey(zero)
32 message := []byte("test message")
33 sig := Sign(private, message)
34 if !Verify(public, message, sig) {
35 t.Errorf("valid signature rejected")
38 wrongMessage := []byte("wrong message")
39 if Verify(public, wrongMessage, sig) {
40 t.Errorf("signature of different message accepted")
44 func TestCryptoSigner(t *testing.T) {
46 public, private, _ := GenerateKey(zero)
48 signer := crypto.Signer(private)
50 publicInterface := signer.Public()
51 public2, ok := publicInterface.(PublicKey)
53 t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
56 if !bytes.Equal(public, public2) {
57 t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
60 message := []byte("message")
61 var noHash crypto.Hash
62 signature, err := signer.Sign(zero, message, noHash)
64 t.Fatalf("error from Sign(): %s", err)
67 if !Verify(public, message, signature) {
68 t.Errorf("Verify failed on signature from Sign()")
72 func TestEqual(t *testing.T) {
73 public, private, _ := GenerateKey(rand.Reader)
75 if !public.Equal(public) {
76 t.Errorf("public key is not equal to itself: %q", public)
78 if !public.Equal(crypto.Signer(private).Public()) {
79 t.Errorf("private.Public() is not Equal to public: %q", public)
81 if !private.Equal(private) {
82 t.Errorf("private key is not equal to itself: %q", private)
85 otherPub, otherPriv, _ := GenerateKey(rand.Reader)
86 if public.Equal(otherPub) {
87 t.Errorf("different public keys are Equal")
89 if private.Equal(otherPriv) {
90 t.Errorf("different private keys are Equal")
94 func TestGolden(t *testing.T) {
95 // sign.input.gz is a selection of test cases from
96 // https://ed25519.cr.yp.to/python/sign.input
97 testDataZ, err := os.Open("testdata/sign.input.gz")
101 defer testDataZ.Close()
102 testData, err := gzip.NewReader(testDataZ)
106 defer testData.Close()
108 scanner := bufio.NewScanner(testData)
114 line := scanner.Text()
115 parts := strings.Split(line, ":")
117 t.Fatalf("bad number of parts on line %d", lineNo)
120 privBytes, _ := hex.DecodeString(parts[0])
121 pubKey, _ := hex.DecodeString(parts[1])
122 msg, _ := hex.DecodeString(parts[2])
123 sig, _ := hex.DecodeString(parts[3])
124 // The signatures in the test vectors also include the message
125 // at the end, but we just want R and S.
126 sig = sig[:SignatureSize]
128 if l := len(pubKey); l != PublicKeySize {
129 t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
132 var priv [PrivateKeySize]byte
133 copy(priv[:], privBytes)
134 copy(priv[32:], pubKey)
136 sig2 := Sign(priv[:], msg)
137 if !bytes.Equal(sig, sig2[:]) {
138 t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
141 if !Verify(pubKey, msg, sig2) {
142 t.Errorf("signature failed to verify on line %d", lineNo)
145 priv2 := NewKeyFromSeed(priv[:32])
146 if !bytes.Equal(priv[:], priv2) {
147 t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2)
150 if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) {
151 t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2)
154 if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) {
155 t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed)
159 if err := scanner.Err(); err != nil {
160 t.Fatalf("error reading test data: %s", err)
164 func TestMalleability(t *testing.T) {
165 // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
166 // that s be in [0, order). This prevents someone from adding a multiple of
167 // order to s and obtaining a second valid signature for the same message.
168 msg := []byte{0x54, 0x65, 0x73, 0x74}
170 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
171 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
172 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
173 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
174 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
175 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
178 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
179 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
180 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
183 if Verify(publicKey, msg, sig) {
184 t.Fatal("non-canonical signature accepted")
188 func TestAllocations(t *testing.T) {
189 t.Skip("skipping allocations test on Go+BoringCrypto, as cgo causes allocations")
190 if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") {
191 t.Skip("skipping allocations test without relevant optimizations")
193 if allocs := testing.AllocsPerRun(100, func() {
194 seed := make([]byte, SeedSize)
195 message := []byte("Hello, world!")
196 priv := NewKeyFromSeed(seed)
197 pub := priv.Public().(PublicKey)
198 signature := Sign(priv, message)
199 if !Verify(pub, message, signature) {
200 t.Fatal("signature didn't verify")
203 t.Errorf("expected zero allocations, got %0.1v", allocs)
207 func BenchmarkKeyGeneration(b *testing.B) {
209 for i := 0; i < b.N; i++ {
210 if _, _, err := GenerateKey(zero); err != nil {
216 func BenchmarkNewKeyFromSeed(b *testing.B) {
217 seed := make([]byte, SeedSize)
218 for i := 0; i < b.N; i++ {
219 _ = NewKeyFromSeed(seed)
223 func BenchmarkSigning(b *testing.B) {
225 _, priv, err := GenerateKey(zero)
229 message := []byte("Hello, world!")
231 for i := 0; i < b.N; i++ {
236 func BenchmarkVerification(b *testing.B) {
238 pub, priv, err := GenerateKey(zero)
242 message := []byte("Hello, world!")
243 signature := Sign(priv, message)
245 for i := 0; i < b.N; i++ {
246 Verify(pub, message, signature)