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