]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/ed25519/ed25519_test.go
[dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto
[gostls13.git] / src / crypto / ed25519 / ed25519_test.go
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.
4
5 package ed25519
6
7 import (
8         "bufio"
9         "bytes"
10         "compress/gzip"
11         "crypto"
12         "crypto/rand"
13         "encoding/hex"
14         "os"
15         "strings"
16         "testing"
17 )
18
19 type zeroReader struct{}
20
21 func (zeroReader) Read(buf []byte) (int, error) {
22         for i := range buf {
23                 buf[i] = 0
24         }
25         return len(buf), nil
26 }
27
28 func TestSignVerify(t *testing.T) {
29         var zero zeroReader
30         public, private, _ := GenerateKey(zero)
31
32         message := []byte("test message")
33         sig := Sign(private, message)
34         if !Verify(public, message, sig) {
35                 t.Errorf("valid signature rejected")
36         }
37
38         wrongMessage := []byte("wrong message")
39         if Verify(public, wrongMessage, sig) {
40                 t.Errorf("signature of different message accepted")
41         }
42 }
43
44 func TestCryptoSigner(t *testing.T) {
45         var zero zeroReader
46         public, private, _ := GenerateKey(zero)
47
48         signer := crypto.Signer(private)
49
50         publicInterface := signer.Public()
51         public2, ok := publicInterface.(PublicKey)
52         if !ok {
53                 t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
54         }
55
56         if !bytes.Equal(public, public2) {
57                 t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
58         }
59
60         message := []byte("message")
61         var noHash crypto.Hash
62         signature, err := signer.Sign(zero, message, noHash)
63         if err != nil {
64                 t.Fatalf("error from Sign(): %s", err)
65         }
66
67         if !Verify(public, message, signature) {
68                 t.Errorf("Verify failed on signature from Sign()")
69         }
70 }
71
72 func TestEqual(t *testing.T) {
73         public, private, _ := GenerateKey(rand.Reader)
74
75         if !public.Equal(public) {
76                 t.Errorf("public key is not equal to itself: %q", public)
77         }
78         if !public.Equal(crypto.Signer(private).Public()) {
79                 t.Errorf("private.Public() is not Equal to public: %q", public)
80         }
81         if !private.Equal(private) {
82                 t.Errorf("private key is not equal to itself: %q", private)
83         }
84
85         otherPub, otherPriv, _ := GenerateKey(rand.Reader)
86         if public.Equal(otherPub) {
87                 t.Errorf("different public keys are Equal")
88         }
89         if private.Equal(otherPriv) {
90                 t.Errorf("different private keys are Equal")
91         }
92 }
93
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")
98         if err != nil {
99                 t.Fatal(err)
100         }
101         defer testDataZ.Close()
102         testData, err := gzip.NewReader(testDataZ)
103         if err != nil {
104                 t.Fatal(err)
105         }
106         defer testData.Close()
107
108         scanner := bufio.NewScanner(testData)
109         lineNo := 0
110
111         for scanner.Scan() {
112                 lineNo++
113
114                 line := scanner.Text()
115                 parts := strings.Split(line, ":")
116                 if len(parts) != 5 {
117                         t.Fatalf("bad number of parts on line %d", lineNo)
118                 }
119
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]
127
128                 if l := len(pubKey); l != PublicKeySize {
129                         t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
130                 }
131
132                 var priv [PrivateKeySize]byte
133                 copy(priv[:], privBytes)
134                 copy(priv[32:], pubKey)
135
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)
139                 }
140
141                 if !Verify(pubKey, msg, sig2) {
142                         t.Errorf("signature failed to verify on line %d", lineNo)
143                 }
144
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)
148                 }
149
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)
152                 }
153
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)
156                 }
157         }
158
159         if err := scanner.Err(); err != nil {
160                 t.Fatalf("error reading test data: %s", err)
161         }
162 }
163
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}
169         sig := []byte{
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,
176         }
177         publicKey := []byte{
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,
181         }
182
183         if Verify(publicKey, msg, sig) {
184                 t.Fatal("non-canonical signature accepted")
185         }
186 }
187
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")
192         }
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")
201                 }
202         }); allocs > 0 {
203                 t.Errorf("expected zero allocations, got %0.1v", allocs)
204         }
205 }
206
207 func BenchmarkKeyGeneration(b *testing.B) {
208         var zero zeroReader
209         for i := 0; i < b.N; i++ {
210                 if _, _, err := GenerateKey(zero); err != nil {
211                         b.Fatal(err)
212                 }
213         }
214 }
215
216 func BenchmarkNewKeyFromSeed(b *testing.B) {
217         seed := make([]byte, SeedSize)
218         for i := 0; i < b.N; i++ {
219                 _ = NewKeyFromSeed(seed)
220         }
221 }
222
223 func BenchmarkSigning(b *testing.B) {
224         var zero zeroReader
225         _, priv, err := GenerateKey(zero)
226         if err != nil {
227                 b.Fatal(err)
228         }
229         message := []byte("Hello, world!")
230         b.ResetTimer()
231         for i := 0; i < b.N; i++ {
232                 Sign(priv, message)
233         }
234 }
235
236 func BenchmarkVerification(b *testing.B) {
237         var zero zeroReader
238         pub, priv, err := GenerateKey(zero)
239         if err != nil {
240                 b.Fatal(err)
241         }
242         message := []byte("Hello, world!")
243         signature := Sign(priv, message)
244         b.ResetTimer()
245         for i := 0; i < b.N; i++ {
246                 Verify(pub, message, signature)
247         }
248 }