1
2
3
4
5 package ecdsa
6
7 import (
8 "bufio"
9 "compress/bzip2"
10 "crypto/elliptic"
11 "crypto/rand"
12 "crypto/sha1"
13 "crypto/sha256"
14 "crypto/sha512"
15 "encoding/hex"
16 "hash"
17 "io"
18 "math/big"
19 "os"
20 "strings"
21 "testing"
22 )
23
24 func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) {
25 tests := []struct {
26 name string
27 curve elliptic.Curve
28 }{
29 {"P256", elliptic.P256()},
30 {"P224", elliptic.P224()},
31 {"P384", elliptic.P384()},
32 {"P521", elliptic.P521()},
33 }
34 if testing.Short() {
35 tests = tests[:1]
36 }
37 for _, test := range tests {
38 curve := test.curve
39 t.Run(test.name, func(t *testing.T) {
40 t.Parallel()
41 f(t, curve)
42 })
43 }
44 }
45
46 func TestKeyGeneration(t *testing.T) {
47 testAllCurves(t, testKeyGeneration)
48 }
49
50 func testKeyGeneration(t *testing.T, c elliptic.Curve) {
51 priv, err := GenerateKey(c, rand.Reader)
52 if err != nil {
53 t.Fatal(err)
54 }
55 if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) {
56 t.Errorf("public key invalid: %s", err)
57 }
58 }
59
60 func TestSignAndVerify(t *testing.T) {
61 testAllCurves(t, testSignAndVerify)
62 }
63
64 func testSignAndVerify(t *testing.T, c elliptic.Curve) {
65 priv, _ := GenerateKey(c, rand.Reader)
66
67 hashed := []byte("testing")
68 r, s, err := Sign(rand.Reader, priv, hashed)
69 if err != nil {
70 t.Errorf("error signing: %s", err)
71 return
72 }
73
74 if !Verify(&priv.PublicKey, hashed, r, s) {
75 t.Errorf("Verify failed")
76 }
77
78 hashed[0] ^= 0xff
79 if Verify(&priv.PublicKey, hashed, r, s) {
80 t.Errorf("Verify always works!")
81 }
82 }
83
84 func TestSignAndVerifyASN1(t *testing.T) {
85 testAllCurves(t, testSignAndVerifyASN1)
86 }
87
88 func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) {
89 priv, _ := GenerateKey(c, rand.Reader)
90
91 hashed := []byte("testing")
92 sig, err := SignASN1(rand.Reader, priv, hashed)
93 if err != nil {
94 t.Errorf("error signing: %s", err)
95 return
96 }
97
98 if !VerifyASN1(&priv.PublicKey, hashed, sig) {
99 t.Errorf("VerifyASN1 failed")
100 }
101
102 hashed[0] ^= 0xff
103 if VerifyASN1(&priv.PublicKey, hashed, sig) {
104 t.Errorf("VerifyASN1 always works!")
105 }
106 }
107
108 func TestNonceSafety(t *testing.T) {
109 testAllCurves(t, testNonceSafety)
110 }
111
112 func testNonceSafety(t *testing.T, c elliptic.Curve) {
113 priv, _ := GenerateKey(c, rand.Reader)
114
115 hashed := []byte("testing")
116 r0, s0, err := Sign(zeroReader, priv, hashed)
117 if err != nil {
118 t.Errorf("error signing: %s", err)
119 return
120 }
121
122 hashed = []byte("testing...")
123 r1, s1, err := Sign(zeroReader, priv, hashed)
124 if err != nil {
125 t.Errorf("error signing: %s", err)
126 return
127 }
128
129 if s0.Cmp(s1) == 0 {
130
131 t.Errorf("the signatures on two different messages were the same")
132 }
133
134 if r0.Cmp(r1) == 0 {
135 t.Errorf("the nonce used for two different messages was the same")
136 }
137 }
138
139 func TestINDCCA(t *testing.T) {
140 testAllCurves(t, testINDCCA)
141 }
142
143 func testINDCCA(t *testing.T, c elliptic.Curve) {
144 priv, _ := GenerateKey(c, rand.Reader)
145
146 hashed := []byte("testing")
147 r0, s0, err := Sign(rand.Reader, priv, hashed)
148 if err != nil {
149 t.Errorf("error signing: %s", err)
150 return
151 }
152
153 r1, s1, err := Sign(rand.Reader, priv, hashed)
154 if err != nil {
155 t.Errorf("error signing: %s", err)
156 return
157 }
158
159 if s0.Cmp(s1) == 0 {
160 t.Errorf("two signatures of the same message produced the same result")
161 }
162
163 if r0.Cmp(r1) == 0 {
164 t.Errorf("two signatures of the same message produced the same nonce")
165 }
166 }
167
168 func fromHex(s string) *big.Int {
169 r, ok := new(big.Int).SetString(s, 16)
170 if !ok {
171 panic("bad hex")
172 }
173 return r
174 }
175
176 func TestVectors(t *testing.T) {
177
178
179
180
181
182
183 if testing.Short() {
184 return
185 }
186
187 f, err := os.Open("testdata/SigVer.rsp.bz2")
188 if err != nil {
189 t.Fatal(err)
190 }
191
192 buf := bufio.NewReader(bzip2.NewReader(f))
193
194 lineNo := 1
195 var h hash.Hash
196 var msg []byte
197 var hashed []byte
198 var r, s *big.Int
199 pub := new(PublicKey)
200
201 for {
202 line, err := buf.ReadString('\n')
203 if len(line) == 0 {
204 if err == io.EOF {
205 break
206 }
207 t.Fatalf("error reading from input: %s", err)
208 }
209 lineNo++
210
211 if !strings.HasSuffix(line, "\r\n") {
212 t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo)
213 }
214 line = line[:len(line)-2]
215
216 if len(line) == 0 || line[0] == '#' {
217 continue
218 }
219
220 if line[0] == '[' {
221 line = line[1 : len(line)-1]
222 parts := strings.SplitN(line, ",", 2)
223
224 switch parts[0] {
225 case "P-224":
226 pub.Curve = elliptic.P224()
227 case "P-256":
228 pub.Curve = elliptic.P256()
229 case "P-384":
230 pub.Curve = elliptic.P384()
231 case "P-521":
232 pub.Curve = elliptic.P521()
233 default:
234 pub.Curve = nil
235 }
236
237 switch parts[1] {
238 case "SHA-1":
239 h = sha1.New()
240 case "SHA-224":
241 h = sha256.New224()
242 case "SHA-256":
243 h = sha256.New()
244 case "SHA-384":
245 h = sha512.New384()
246 case "SHA-512":
247 h = sha512.New()
248 default:
249 h = nil
250 }
251
252 continue
253 }
254
255 if h == nil || pub.Curve == nil {
256 continue
257 }
258
259 switch {
260 case strings.HasPrefix(line, "Msg = "):
261 if msg, err = hex.DecodeString(line[6:]); err != nil {
262 t.Fatalf("failed to decode message on line %d: %s", lineNo, err)
263 }
264 case strings.HasPrefix(line, "Qx = "):
265 pub.X = fromHex(line[5:])
266 case strings.HasPrefix(line, "Qy = "):
267 pub.Y = fromHex(line[5:])
268 case strings.HasPrefix(line, "R = "):
269 r = fromHex(line[4:])
270 case strings.HasPrefix(line, "S = "):
271 s = fromHex(line[4:])
272 case strings.HasPrefix(line, "Result = "):
273 expected := line[9] == 'P'
274 h.Reset()
275 h.Write(msg)
276 hashed := h.Sum(hashed[:0])
277 if Verify(pub, hashed, r, s) != expected {
278 t.Fatalf("incorrect result on line %d", lineNo)
279 }
280 default:
281 t.Fatalf("unknown variable on line %d: %s", lineNo, line)
282 }
283 }
284 }
285
286 func TestNegativeInputs(t *testing.T) {
287 testAllCurves(t, testNegativeInputs)
288 }
289
290 func testNegativeInputs(t *testing.T, curve elliptic.Curve) {
291 key, err := GenerateKey(curve, rand.Reader)
292 if err != nil {
293 t.Errorf("failed to generate key")
294 }
295
296 var hash [32]byte
297 r := new(big.Int).SetInt64(1)
298 r.Lsh(r, 550 )
299 r.Neg(r)
300
301 if Verify(&key.PublicKey, hash[:], r, r) {
302 t.Errorf("bogus signature accepted")
303 }
304 }
305
306 func TestZeroHashSignature(t *testing.T) {
307 testAllCurves(t, testZeroHashSignature)
308 }
309
310 func testZeroHashSignature(t *testing.T, curve elliptic.Curve) {
311 zeroHash := make([]byte, 64)
312
313 privKey, err := GenerateKey(curve, rand.Reader)
314 if err != nil {
315 panic(err)
316 }
317
318
319 r, s, err := Sign(rand.Reader, privKey, zeroHash)
320 if err != nil {
321 panic(err)
322 }
323
324
325 if !Verify(&privKey.PublicKey, zeroHash, r, s) {
326 t.Errorf("zero hash signature verify failed for %T", curve)
327 }
328 }
329
330 func benchmarkAllCurves(t *testing.B, f func(*testing.B, elliptic.Curve)) {
331 tests := []struct {
332 name string
333 curve elliptic.Curve
334 }{
335 {"P256", elliptic.P256()},
336 {"P224", elliptic.P224()},
337 {"P384", elliptic.P384()},
338 {"P521", elliptic.P521()},
339 }
340 for _, test := range tests {
341 curve := test.curve
342 t.Run(test.name, func(t *testing.B) {
343 f(t, curve)
344 })
345 }
346 }
347
348 func BenchmarkSign(b *testing.B) {
349 benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) {
350 priv, err := GenerateKey(curve, rand.Reader)
351 if err != nil {
352 b.Fatal(err)
353 }
354 hashed := []byte("testing")
355
356 b.ReportAllocs()
357 b.ResetTimer()
358 for i := 0; i < b.N; i++ {
359 sig, err := SignASN1(rand.Reader, priv, hashed)
360 if err != nil {
361 b.Fatal(err)
362 }
363
364 hashed[0] = sig[0]
365 }
366 })
367 }
368
369 func BenchmarkVerify(b *testing.B) {
370 benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) {
371 priv, err := GenerateKey(curve, rand.Reader)
372 if err != nil {
373 b.Fatal(err)
374 }
375 hashed := []byte("testing")
376 r, s, err := Sign(rand.Reader, priv, hashed)
377 if err != nil {
378 b.Fatal(err)
379 }
380
381 b.ReportAllocs()
382 b.ResetTimer()
383 for i := 0; i < b.N; i++ {
384 if !Verify(&priv.PublicKey, hashed, r, s) {
385 b.Fatal("verify failed")
386 }
387 }
388 })
389 }
390
391 func BenchmarkGenerateKey(b *testing.B) {
392 benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) {
393 b.ReportAllocs()
394 b.ResetTimer()
395 for i := 0; i < b.N; i++ {
396 if _, err := GenerateKey(curve, rand.Reader); err != nil {
397 b.Fatal(err)
398 }
399 }
400 })
401 }
402
View as plain text