github.com/fisco-bcos/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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 "compress/bzip2" 10 "github.com/FISCO-BCOS/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 testNonceSafety(t *testing.T, c elliptic.Curve, tag string) { 135 priv, _ := GenerateKey(c, rand.Reader) 136 137 hashed := []byte("testing") 138 r0, s0, err := Sign(zeroReader, priv, hashed) 139 if err != nil { 140 t.Errorf("%s: error signing: %s", tag, err) 141 return 142 } 143 144 hashed = []byte("testing...") 145 r1, s1, err := Sign(zeroReader, priv, hashed) 146 if err != nil { 147 t.Errorf("%s: error signing: %s", tag, err) 148 return 149 } 150 151 if s0.Cmp(s1) == 0 { 152 // This should never happen. 153 t.Errorf("%s: the signatures on two different messages were the same", tag) 154 } 155 156 if r0.Cmp(r1) == 0 { 157 t.Errorf("%s: the nonce used for two different messages was the same", tag) 158 } 159 } 160 161 func TestNonceSafety(t *testing.T) { 162 testNonceSafety(t, elliptic.P224(), "p224") 163 if testing.Short() { 164 return 165 } 166 testNonceSafety(t, elliptic.P256(), "p256") 167 testNonceSafety(t, elliptic.P384(), "p384") 168 testNonceSafety(t, elliptic.P521(), "p521") 169 } 170 171 func testINDCCA(t *testing.T, c elliptic.Curve, tag string) { 172 priv, _ := GenerateKey(c, rand.Reader) 173 174 hashed := []byte("testing") 175 r0, s0, err := Sign(rand.Reader, priv, hashed) 176 if err != nil { 177 t.Errorf("%s: error signing: %s", tag, err) 178 return 179 } 180 181 r1, s1, err := Sign(rand.Reader, priv, hashed) 182 if err != nil { 183 t.Errorf("%s: error signing: %s", tag, err) 184 return 185 } 186 187 if s0.Cmp(s1) == 0 { 188 t.Errorf("%s: two signatures of the same message produced the same result", tag) 189 } 190 191 if r0.Cmp(r1) == 0 { 192 t.Errorf("%s: two signatures of the same message produced the same nonce", tag) 193 } 194 } 195 196 func TestINDCCA(t *testing.T) { 197 testINDCCA(t, elliptic.P224(), "p224") 198 if testing.Short() { 199 return 200 } 201 testINDCCA(t, elliptic.P256(), "p256") 202 testINDCCA(t, elliptic.P384(), "p384") 203 testINDCCA(t, elliptic.P521(), "p521") 204 } 205 206 func fromHex(s string) *big.Int { 207 r, ok := new(big.Int).SetString(s, 16) 208 if !ok { 209 panic("bad hex") 210 } 211 return r 212 } 213 214 func TestVectors(t *testing.T) { 215 // This test runs the full set of NIST test vectors from 216 // https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip 217 // 218 // The SigVer.rsp file has been edited to remove test vectors for 219 // unsupported algorithms and has been compressed. 220 221 if testing.Short() { 222 return 223 } 224 225 f, err := os.Open("testdata/SigVer.rsp.bz2") 226 if err != nil { 227 t.Fatal(err) 228 } 229 230 buf := bufio.NewReader(bzip2.NewReader(f)) 231 232 lineNo := 1 233 var h hash.Hash 234 var msg []byte 235 var hashed []byte 236 var r, s *big.Int 237 pub := new(PublicKey) 238 239 for { 240 line, err := buf.ReadString('\n') 241 if len(line) == 0 { 242 if err == io.EOF { 243 break 244 } 245 t.Fatalf("error reading from input: %s", err) 246 } 247 lineNo++ 248 // Need to remove \r\n from the end of the line. 249 if !strings.HasSuffix(line, "\r\n") { 250 t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo) 251 } 252 line = line[:len(line)-2] 253 254 if len(line) == 0 || line[0] == '#' { 255 continue 256 } 257 258 if line[0] == '[' { 259 line = line[1 : len(line)-1] 260 parts := strings.SplitN(line, ",", 2) 261 262 switch parts[0] { 263 case "P-224": 264 pub.Curve = elliptic.P224() 265 case "P-256": 266 pub.Curve = elliptic.P256() 267 case "P-384": 268 pub.Curve = elliptic.P384() 269 case "P-521": 270 pub.Curve = elliptic.P521() 271 default: 272 pub.Curve = nil 273 } 274 275 switch parts[1] { 276 case "SHA-1": 277 h = sha1.New() 278 case "SHA-224": 279 h = sha256.New224() 280 case "SHA-256": 281 h = sha256.New() 282 case "SHA-384": 283 h = sha512.New384() 284 case "SHA-512": 285 h = sha512.New() 286 default: 287 h = nil 288 } 289 290 continue 291 } 292 293 if h == nil || pub.Curve == nil { 294 continue 295 } 296 297 switch { 298 case strings.HasPrefix(line, "Msg = "): 299 if msg, err = hex.DecodeString(line[6:]); err != nil { 300 t.Fatalf("failed to decode message on line %d: %s", lineNo, err) 301 } 302 case strings.HasPrefix(line, "Qx = "): 303 pub.X = fromHex(line[5:]) 304 case strings.HasPrefix(line, "Qy = "): 305 pub.Y = fromHex(line[5:]) 306 case strings.HasPrefix(line, "R = "): 307 r = fromHex(line[4:]) 308 case strings.HasPrefix(line, "S = "): 309 s = fromHex(line[4:]) 310 case strings.HasPrefix(line, "Result = "): 311 expected := line[9] == 'P' 312 h.Reset() 313 h.Write(msg) 314 hashed := h.Sum(hashed[:0]) 315 if Verify(pub, hashed, r, s) != expected { 316 t.Fatalf("incorrect result on line %d", lineNo) 317 } 318 default: 319 t.Fatalf("unknown variable on line %d: %s", lineNo, line) 320 } 321 } 322 } 323 324 func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) { 325 key, err := GenerateKey(curve, rand.Reader) 326 if err != nil { 327 t.Errorf("failed to generate key for %q", tag) 328 } 329 330 var hash [32]byte 331 r := new(big.Int).SetInt64(1) 332 r.Lsh(r, 550 /* larger than any supported curve */) 333 r.Neg(r) 334 335 if Verify(&key.PublicKey, hash[:], r, r) { 336 t.Errorf("bogus signature accepted for %q", tag) 337 } 338 } 339 340 func TestNegativeInputs(t *testing.T) { 341 testNegativeInputs(t, elliptic.P224(), "p224") 342 testNegativeInputs(t, elliptic.P256(), "p256") 343 testNegativeInputs(t, elliptic.P384(), "p384") 344 testNegativeInputs(t, elliptic.P521(), "p521") 345 } 346 347 func TestZeroHashSignature(t *testing.T) { 348 zeroHash := make([]byte, 64) 349 350 for _, curve := range []elliptic.Curve{elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521()} { 351 privKey, err := GenerateKey(curve, rand.Reader) 352 if err != nil { 353 panic(err) 354 } 355 356 // Sign a hash consisting of all zeros. 357 r, s, err := Sign(rand.Reader, privKey, zeroHash) 358 if err != nil { 359 panic(err) 360 } 361 362 // Confirm that it can be verified. 363 if !Verify(&privKey.PublicKey, zeroHash, r, s) { 364 t.Errorf("zero hash signature verify failed for %T", curve) 365 } 366 } 367 }