github.com/dorkamotorka/go/src@v0.0.0-20230614113921-187095f0e316/crypto/ecdsa/ecdsa_test.go (about) 1 // Copyright 2011 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 ecdsa 6 7 import ( 8 "bufio" 9 "bytes" 10 "compress/bzip2" 11 "crypto/elliptic" 12 "crypto/rand" 13 "crypto/sha1" 14 "crypto/sha256" 15 "crypto/sha512" 16 "encoding/hex" 17 "hash" 18 "io" 19 "math/big" 20 "os" 21 "strings" 22 "testing" 23 ) 24 25 func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { 26 tests := []struct { 27 name string 28 curve elliptic.Curve 29 }{ 30 {"P256", elliptic.P256()}, 31 {"P224", elliptic.P224()}, 32 {"P384", elliptic.P384()}, 33 {"P521", elliptic.P521()}, 34 {"P256/Generic", genericParamsForCurve(elliptic.P256())}, 35 } 36 if testing.Short() { 37 tests = tests[:1] 38 } 39 for _, test := range tests { 40 curve := test.curve 41 t.Run(test.name, func(t *testing.T) { 42 t.Parallel() 43 f(t, curve) 44 }) 45 } 46 } 47 48 // genericParamsForCurve returns the dereferenced CurveParams for 49 // the specified curve. This is used to avoid the logic for 50 // upgrading a curve to its specific implementation, forcing 51 // usage of the generic implementation. 52 func genericParamsForCurve(c elliptic.Curve) *elliptic.CurveParams { 53 d := *(c.Params()) 54 return &d 55 } 56 57 func TestKeyGeneration(t *testing.T) { 58 testAllCurves(t, testKeyGeneration) 59 } 60 61 func testKeyGeneration(t *testing.T, c elliptic.Curve) { 62 priv, err := GenerateKey(c, rand.Reader) 63 if err != nil { 64 t.Fatal(err) 65 } 66 if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { 67 t.Errorf("public key invalid: %s", err) 68 } 69 } 70 71 func TestSignAndVerify(t *testing.T) { 72 testAllCurves(t, testSignAndVerify) 73 } 74 75 func testSignAndVerify(t *testing.T, c elliptic.Curve) { 76 priv, _ := GenerateKey(c, rand.Reader) 77 78 hashed := []byte("testing") 79 r, s, err := Sign(rand.Reader, priv, hashed) 80 if err != nil { 81 t.Errorf("error signing: %s", err) 82 return 83 } 84 85 if !Verify(&priv.PublicKey, hashed, r, s) { 86 t.Errorf("Verify failed") 87 } 88 89 hashed[0] ^= 0xff 90 if Verify(&priv.PublicKey, hashed, r, s) { 91 t.Errorf("Verify always works!") 92 } 93 } 94 95 func TestSignAndVerifyASN1(t *testing.T) { 96 testAllCurves(t, testSignAndVerifyASN1) 97 } 98 99 func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) { 100 priv, _ := GenerateKey(c, rand.Reader) 101 102 hashed := []byte("testing") 103 sig, err := SignASN1(rand.Reader, priv, hashed) 104 if err != nil { 105 t.Errorf("error signing: %s", err) 106 return 107 } 108 109 if !VerifyASN1(&priv.PublicKey, hashed, sig) { 110 t.Errorf("VerifyASN1 failed") 111 } 112 113 hashed[0] ^= 0xff 114 if VerifyASN1(&priv.PublicKey, hashed, sig) { 115 t.Errorf("VerifyASN1 always works!") 116 } 117 } 118 119 func TestNonceSafety(t *testing.T) { 120 testAllCurves(t, testNonceSafety) 121 } 122 123 func testNonceSafety(t *testing.T, c elliptic.Curve) { 124 priv, _ := GenerateKey(c, rand.Reader) 125 126 hashed := []byte("testing") 127 r0, s0, err := Sign(zeroReader, priv, hashed) 128 if err != nil { 129 t.Errorf("error signing: %s", err) 130 return 131 } 132 133 hashed = []byte("testing...") 134 r1, s1, err := Sign(zeroReader, priv, hashed) 135 if err != nil { 136 t.Errorf("error signing: %s", err) 137 return 138 } 139 140 if s0.Cmp(s1) == 0 { 141 // This should never happen. 142 t.Errorf("the signatures on two different messages were the same") 143 } 144 145 if r0.Cmp(r1) == 0 { 146 t.Errorf("the nonce used for two different messages was the same") 147 } 148 } 149 150 func TestINDCCA(t *testing.T) { 151 testAllCurves(t, testINDCCA) 152 } 153 154 func testINDCCA(t *testing.T, c elliptic.Curve) { 155 priv, _ := GenerateKey(c, rand.Reader) 156 157 hashed := []byte("testing") 158 r0, s0, err := Sign(rand.Reader, priv, hashed) 159 if err != nil { 160 t.Errorf("error signing: %s", err) 161 return 162 } 163 164 r1, s1, err := Sign(rand.Reader, priv, hashed) 165 if err != nil { 166 t.Errorf("error signing: %s", err) 167 return 168 } 169 170 if s0.Cmp(s1) == 0 { 171 t.Errorf("two signatures of the same message produced the same result") 172 } 173 174 if r0.Cmp(r1) == 0 { 175 t.Errorf("two signatures of the same message produced the same nonce") 176 } 177 } 178 179 func fromHex(s string) *big.Int { 180 r, ok := new(big.Int).SetString(s, 16) 181 if !ok { 182 panic("bad hex") 183 } 184 return r 185 } 186 187 func TestVectors(t *testing.T) { 188 // This test runs the full set of NIST test vectors from 189 // https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip 190 // 191 // The SigVer.rsp file has been edited to remove test vectors for 192 // unsupported algorithms and has been compressed. 193 194 if testing.Short() { 195 return 196 } 197 198 f, err := os.Open("testdata/SigVer.rsp.bz2") 199 if err != nil { 200 t.Fatal(err) 201 } 202 203 buf := bufio.NewReader(bzip2.NewReader(f)) 204 205 lineNo := 1 206 var h hash.Hash 207 var msg []byte 208 var hashed []byte 209 var r, s *big.Int 210 pub := new(PublicKey) 211 212 for { 213 line, err := buf.ReadString('\n') 214 if len(line) == 0 { 215 if err == io.EOF { 216 break 217 } 218 t.Fatalf("error reading from input: %s", err) 219 } 220 lineNo++ 221 // Need to remove \r\n from the end of the line. 222 if !strings.HasSuffix(line, "\r\n") { 223 t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo) 224 } 225 line = line[:len(line)-2] 226 227 if len(line) == 0 || line[0] == '#' { 228 continue 229 } 230 231 if line[0] == '[' { 232 line = line[1 : len(line)-1] 233 curve, hash, _ := strings.Cut(line, ",") 234 235 switch curve { 236 case "P-224": 237 pub.Curve = elliptic.P224() 238 case "P-256": 239 pub.Curve = elliptic.P256() 240 case "P-384": 241 pub.Curve = elliptic.P384() 242 case "P-521": 243 pub.Curve = elliptic.P521() 244 default: 245 pub.Curve = nil 246 } 247 248 switch hash { 249 case "SHA-1": 250 h = sha1.New() 251 case "SHA-224": 252 h = sha256.New224() 253 case "SHA-256": 254 h = sha256.New() 255 case "SHA-384": 256 h = sha512.New384() 257 case "SHA-512": 258 h = sha512.New() 259 default: 260 h = nil 261 } 262 263 continue 264 } 265 266 if h == nil || pub.Curve == nil { 267 continue 268 } 269 270 switch { 271 case strings.HasPrefix(line, "Msg = "): 272 if msg, err = hex.DecodeString(line[6:]); err != nil { 273 t.Fatalf("failed to decode message on line %d: %s", lineNo, err) 274 } 275 case strings.HasPrefix(line, "Qx = "): 276 pub.X = fromHex(line[5:]) 277 case strings.HasPrefix(line, "Qy = "): 278 pub.Y = fromHex(line[5:]) 279 case strings.HasPrefix(line, "R = "): 280 r = fromHex(line[4:]) 281 case strings.HasPrefix(line, "S = "): 282 s = fromHex(line[4:]) 283 case strings.HasPrefix(line, "Result = "): 284 expected := line[9] == 'P' 285 h.Reset() 286 h.Write(msg) 287 hashed := h.Sum(hashed[:0]) 288 if Verify(pub, hashed, r, s) != expected { 289 t.Fatalf("incorrect result on line %d", lineNo) 290 } 291 default: 292 t.Fatalf("unknown variable on line %d: %s", lineNo, line) 293 } 294 } 295 } 296 297 func TestNegativeInputs(t *testing.T) { 298 testAllCurves(t, testNegativeInputs) 299 } 300 301 func testNegativeInputs(t *testing.T, curve elliptic.Curve) { 302 key, err := GenerateKey(curve, rand.Reader) 303 if err != nil { 304 t.Errorf("failed to generate key") 305 } 306 307 var hash [32]byte 308 r := new(big.Int).SetInt64(1) 309 r.Lsh(r, 550 /* larger than any supported curve */) 310 r.Neg(r) 311 312 if Verify(&key.PublicKey, hash[:], r, r) { 313 t.Errorf("bogus signature accepted") 314 } 315 } 316 317 func TestZeroHashSignature(t *testing.T) { 318 testAllCurves(t, testZeroHashSignature) 319 } 320 321 func testZeroHashSignature(t *testing.T, curve elliptic.Curve) { 322 zeroHash := make([]byte, 64) 323 324 privKey, err := GenerateKey(curve, rand.Reader) 325 if err != nil { 326 panic(err) 327 } 328 329 // Sign a hash consisting of all zeros. 330 r, s, err := Sign(rand.Reader, privKey, zeroHash) 331 if err != nil { 332 panic(err) 333 } 334 335 // Confirm that it can be verified. 336 if !Verify(&privKey.PublicKey, zeroHash, r, s) { 337 t.Errorf("zero hash signature verify failed for %T", curve) 338 } 339 } 340 341 func TestRandomPoint(t *testing.T) { 342 t.Run("P-224", func(t *testing.T) { testRandomPoint(t, p224()) }) 343 t.Run("P-256", func(t *testing.T) { testRandomPoint(t, p256()) }) 344 t.Run("P-384", func(t *testing.T) { testRandomPoint(t, p384()) }) 345 t.Run("P-521", func(t *testing.T) { testRandomPoint(t, p521()) }) 346 } 347 348 func testRandomPoint[Point nistPoint[Point]](t *testing.T, c *nistCurve[Point]) { 349 t.Cleanup(func() { testingOnlyRejectionSamplingLooped = nil }) 350 var loopCount int 351 testingOnlyRejectionSamplingLooped = func() { loopCount++ } 352 353 // A sequence of all ones will generate 2^N-1, which should be rejected. 354 // (Unless, for example, we are masking too many bits.) 355 r := io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0xff}, 100)), rand.Reader) 356 if k, p, err := randomPoint(c, r); err != nil { 357 t.Fatal(err) 358 } else if k.IsZero() == 1 { 359 t.Error("k is zero") 360 } else if p.Bytes()[0] != 4 { 361 t.Error("p is infinity") 362 } 363 if loopCount == 0 { 364 t.Error("overflow was not rejected") 365 } 366 loopCount = 0 367 368 // A sequence of all zeroes will generate zero, which should be rejected. 369 r = io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0}, 100)), rand.Reader) 370 if k, p, err := randomPoint(c, r); err != nil { 371 t.Fatal(err) 372 } else if k.IsZero() == 1 { 373 t.Error("k is zero") 374 } else if p.Bytes()[0] != 4 { 375 t.Error("p is infinity") 376 } 377 if loopCount == 0 { 378 t.Error("zero was not rejected") 379 } 380 loopCount = 0 381 382 // P-256 has a 2⁻³² chance or randomly hitting a rejection. For P-224 it's 383 // 2⁻¹¹², for P-384 it's 2⁻¹⁹⁴, and for P-521 it's 2⁻²⁶², so if we hit in 384 // tests, something is horribly wrong. (For example, we are masking the 385 // wrong bits.) 386 if c.curve == elliptic.P256() { 387 return 388 } 389 if k, p, err := randomPoint(c, rand.Reader); err != nil { 390 t.Fatal(err) 391 } else if k.IsZero() == 1 { 392 t.Error("k is zero") 393 } else if p.Bytes()[0] != 4 { 394 t.Error("p is infinity") 395 } 396 if loopCount > 0 { 397 t.Error("unexpected rejection") 398 } 399 } 400 401 func TestZeroSignature(t *testing.T) { 402 testAllCurves(t, testZeroSignature) 403 } 404 405 func testZeroSignature(t *testing.T, curve elliptic.Curve) { 406 privKey, err := GenerateKey(curve, rand.Reader) 407 if err != nil { 408 panic(err) 409 } 410 411 if Verify(&privKey.PublicKey, make([]byte, 64), big.NewInt(0), big.NewInt(0)) { 412 t.Errorf("Verify with r,s=0 succeeded: %T", curve) 413 } 414 } 415 416 func TestNegtativeSignature(t *testing.T) { 417 testAllCurves(t, testNegativeSignature) 418 } 419 420 func testNegativeSignature(t *testing.T, curve elliptic.Curve) { 421 zeroHash := make([]byte, 64) 422 423 privKey, err := GenerateKey(curve, rand.Reader) 424 if err != nil { 425 panic(err) 426 } 427 r, s, err := Sign(rand.Reader, privKey, zeroHash) 428 if err != nil { 429 panic(err) 430 } 431 432 r = r.Neg(r) 433 if Verify(&privKey.PublicKey, zeroHash, r, s) { 434 t.Errorf("Verify with r=-r succeeded: %T", curve) 435 } 436 } 437 438 func TestRPlusNSignature(t *testing.T) { 439 testAllCurves(t, testRPlusNSignature) 440 } 441 442 func testRPlusNSignature(t *testing.T, curve elliptic.Curve) { 443 zeroHash := make([]byte, 64) 444 445 privKey, err := GenerateKey(curve, rand.Reader) 446 if err != nil { 447 panic(err) 448 } 449 r, s, err := Sign(rand.Reader, privKey, zeroHash) 450 if err != nil { 451 panic(err) 452 } 453 454 r = r.Add(r, curve.Params().N) 455 if Verify(&privKey.PublicKey, zeroHash, r, s) { 456 t.Errorf("Verify with r=r+n succeeded: %T", curve) 457 } 458 } 459 460 func TestRMinusNSignature(t *testing.T) { 461 testAllCurves(t, testRMinusNSignature) 462 } 463 464 func testRMinusNSignature(t *testing.T, curve elliptic.Curve) { 465 zeroHash := make([]byte, 64) 466 467 privKey, err := GenerateKey(curve, rand.Reader) 468 if err != nil { 469 panic(err) 470 } 471 r, s, err := Sign(rand.Reader, privKey, zeroHash) 472 if err != nil { 473 panic(err) 474 } 475 476 r = r.Sub(r, curve.Params().N) 477 if Verify(&privKey.PublicKey, zeroHash, r, s) { 478 t.Errorf("Verify with r=r-n succeeded: %T", curve) 479 } 480 } 481 482 func randomPointForCurve(curve elliptic.Curve, rand io.Reader) error { 483 switch curve.Params() { 484 case elliptic.P224().Params(): 485 _, _, err := randomPoint(p224(), rand) 486 return err 487 case elliptic.P256().Params(): 488 _, _, err := randomPoint(p256(), rand) 489 return err 490 case elliptic.P384().Params(): 491 _, _, err := randomPoint(p384(), rand) 492 return err 493 case elliptic.P521().Params(): 494 _, _, err := randomPoint(p521(), rand) 495 return err 496 default: 497 panic("unknown curve") 498 } 499 } 500 501 func benchmarkAllCurves(b *testing.B, f func(*testing.B, elliptic.Curve)) { 502 tests := []struct { 503 name string 504 curve elliptic.Curve 505 }{ 506 {"P256", elliptic.P256()}, 507 {"P384", elliptic.P384()}, 508 {"P521", elliptic.P521()}, 509 } 510 for _, test := range tests { 511 curve := test.curve 512 b.Run(test.name, func(b *testing.B) { 513 f(b, curve) 514 }) 515 } 516 } 517 518 func BenchmarkSign(b *testing.B) { 519 benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { 520 r := bufio.NewReaderSize(rand.Reader, 1<<15) 521 priv, err := GenerateKey(curve, r) 522 if err != nil { 523 b.Fatal(err) 524 } 525 hashed := []byte("testing") 526 527 b.ReportAllocs() 528 b.ResetTimer() 529 for i := 0; i < b.N; i++ { 530 sig, err := SignASN1(r, priv, hashed) 531 if err != nil { 532 b.Fatal(err) 533 } 534 // Prevent the compiler from optimizing out the operation. 535 hashed[0] = sig[0] 536 } 537 }) 538 } 539 540 func BenchmarkVerify(b *testing.B) { 541 benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { 542 r := bufio.NewReaderSize(rand.Reader, 1<<15) 543 priv, err := GenerateKey(curve, r) 544 if err != nil { 545 b.Fatal(err) 546 } 547 hashed := []byte("testing") 548 sig, err := SignASN1(r, priv, hashed) 549 if err != nil { 550 b.Fatal(err) 551 } 552 553 b.ReportAllocs() 554 b.ResetTimer() 555 for i := 0; i < b.N; i++ { 556 if !VerifyASN1(&priv.PublicKey, hashed, sig) { 557 b.Fatal("verify failed") 558 } 559 } 560 }) 561 } 562 563 func BenchmarkGenerateKey(b *testing.B) { 564 benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { 565 r := bufio.NewReaderSize(rand.Reader, 1<<15) 566 b.ReportAllocs() 567 b.ResetTimer() 568 for i := 0; i < b.N; i++ { 569 if _, err := GenerateKey(curve, r); err != nil { 570 b.Fatal(err) 571 } 572 } 573 }) 574 }