github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/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 "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.ResetTimer() 52 for i := 0; i < b.N; i++ { 53 _, _, _ = Sign(rand.Reader, priv, hashed) 54 } 55 } 56 57 func BenchmarkSignP384(b *testing.B) { 58 b.ResetTimer() 59 p384 := elliptic.P384() 60 hashed := []byte("testing") 61 priv, _ := GenerateKey(p384, rand.Reader) 62 63 b.ResetTimer() 64 for i := 0; i < b.N; i++ { 65 _, _, _ = Sign(rand.Reader, priv, hashed) 66 } 67 } 68 69 func BenchmarkVerifyP256(b *testing.B) { 70 b.ResetTimer() 71 p256 := elliptic.P256() 72 hashed := []byte("testing") 73 priv, _ := GenerateKey(p256, rand.Reader) 74 r, s, _ := Sign(rand.Reader, priv, hashed) 75 76 b.ResetTimer() 77 for i := 0; i < b.N; i++ { 78 Verify(&priv.PublicKey, hashed, r, s) 79 } 80 } 81 82 func BenchmarkKeyGeneration(b *testing.B) { 83 b.ResetTimer() 84 p256 := elliptic.P256() 85 86 b.ResetTimer() 87 for i := 0; i < b.N; i++ { 88 GenerateKey(p256, rand.Reader) 89 } 90 } 91 92 func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) { 93 priv, _ := GenerateKey(c, rand.Reader) 94 95 hashed := []byte("testing") 96 r, s, err := Sign(rand.Reader, priv, hashed) 97 if err != nil { 98 t.Errorf("%s: error signing: %s", tag, err) 99 return 100 } 101 102 if !Verify(&priv.PublicKey, hashed, r, s) { 103 t.Errorf("%s: Verify failed", tag) 104 } 105 106 hashed[0] ^= 0xff 107 if Verify(&priv.PublicKey, hashed, r, s) { 108 t.Errorf("%s: Verify always works!", tag) 109 } 110 } 111 112 func TestSignAndVerify(t *testing.T) { 113 testSignAndVerify(t, elliptic.P224(), "p224") 114 if testing.Short() { 115 return 116 } 117 testSignAndVerify(t, elliptic.P256(), "p256") 118 testSignAndVerify(t, elliptic.P384(), "p384") 119 testSignAndVerify(t, elliptic.P521(), "p521") 120 } 121 122 func testNonceSafety(t *testing.T, c elliptic.Curve, tag string) { 123 priv, _ := GenerateKey(c, rand.Reader) 124 125 hashed := []byte("testing") 126 r0, s0, err := Sign(zeroReader, priv, hashed) 127 if err != nil { 128 t.Errorf("%s: error signing: %s", tag, err) 129 return 130 } 131 132 hashed = []byte("testing...") 133 r1, s1, err := Sign(zeroReader, priv, hashed) 134 if err != nil { 135 t.Errorf("%s: error signing: %s", tag, err) 136 return 137 } 138 139 if s0.Cmp(s1) == 0 { 140 // This should never happen. 141 t.Errorf("%s: the signatures on two different messages were the same", tag) 142 } 143 144 if r0.Cmp(r1) == 0 { 145 t.Errorf("%s: the nonce used for two different messages was the same", tag) 146 } 147 } 148 149 func TestNonceSafety(t *testing.T) { 150 testNonceSafety(t, elliptic.P224(), "p224") 151 if testing.Short() { 152 return 153 } 154 testNonceSafety(t, elliptic.P256(), "p256") 155 testNonceSafety(t, elliptic.P384(), "p384") 156 testNonceSafety(t, elliptic.P521(), "p521") 157 } 158 159 func testINDCCA(t *testing.T, c elliptic.Curve, tag string) { 160 priv, _ := GenerateKey(c, rand.Reader) 161 162 hashed := []byte("testing") 163 r0, s0, err := Sign(rand.Reader, priv, hashed) 164 if err != nil { 165 t.Errorf("%s: error signing: %s", tag, err) 166 return 167 } 168 169 r1, s1, err := Sign(rand.Reader, priv, hashed) 170 if err != nil { 171 t.Errorf("%s: error signing: %s", tag, err) 172 return 173 } 174 175 if s0.Cmp(s1) == 0 { 176 t.Errorf("%s: two signatures of the same message produced the same result", tag) 177 } 178 179 if r0.Cmp(r1) == 0 { 180 t.Errorf("%s: two signatures of the same message produced the same nonce", tag) 181 } 182 } 183 184 func TestINDCCA(t *testing.T) { 185 testINDCCA(t, elliptic.P224(), "p224") 186 if testing.Short() { 187 return 188 } 189 testINDCCA(t, elliptic.P256(), "p256") 190 testINDCCA(t, elliptic.P384(), "p384") 191 testINDCCA(t, elliptic.P521(), "p521") 192 } 193 194 func fromHex(s string) *big.Int { 195 r, ok := new(big.Int).SetString(s, 16) 196 if !ok { 197 panic("bad hex") 198 } 199 return r 200 } 201 202 func TestVectors(t *testing.T) { 203 // This test runs the full set of NIST test vectors from 204 // http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip 205 // 206 // The SigVer.rsp file has been edited to remove test vectors for 207 // unsupported algorithms and has been compressed. 208 209 if testing.Short() { 210 return 211 } 212 213 f, err := os.Open("testdata/SigVer.rsp.bz2") 214 if err != nil { 215 t.Fatal(err) 216 } 217 218 buf := bufio.NewReader(bzip2.NewReader(f)) 219 220 lineNo := 1 221 var h hash.Hash 222 var msg []byte 223 var hashed []byte 224 var r, s *big.Int 225 pub := new(PublicKey) 226 227 for { 228 line, err := buf.ReadString('\n') 229 if len(line) == 0 { 230 if err == io.EOF { 231 break 232 } 233 t.Fatalf("error reading from input: %s", err) 234 } 235 lineNo++ 236 // Need to remove \r\n from the end of the line. 237 if !strings.HasSuffix(line, "\r\n") { 238 t.Fatalf("bad line ending (expected \\r\\n) on line %d", lineNo) 239 } 240 line = line[:len(line)-2] 241 242 if len(line) == 0 || line[0] == '#' { 243 continue 244 } 245 246 if line[0] == '[' { 247 line = line[1 : len(line)-1] 248 parts := strings.SplitN(line, ",", 2) 249 250 switch parts[0] { 251 case "P-224": 252 pub.Curve = elliptic.P224() 253 case "P-256": 254 pub.Curve = elliptic.P256() 255 case "P-384": 256 pub.Curve = elliptic.P384() 257 case "P-521": 258 pub.Curve = elliptic.P521() 259 default: 260 pub.Curve = nil 261 } 262 263 switch parts[1] { 264 case "SHA-1": 265 h = sha1.New() 266 case "SHA-224": 267 h = sha256.New224() 268 case "SHA-256": 269 h = sha256.New() 270 case "SHA-384": 271 h = sha512.New384() 272 case "SHA-512": 273 h = sha512.New() 274 default: 275 h = nil 276 } 277 278 continue 279 } 280 281 if h == nil || pub.Curve == nil { 282 continue 283 } 284 285 switch { 286 case strings.HasPrefix(line, "Msg = "): 287 if msg, err = hex.DecodeString(line[6:]); err != nil { 288 t.Fatalf("failed to decode message on line %d: %s", lineNo, err) 289 } 290 case strings.HasPrefix(line, "Qx = "): 291 pub.X = fromHex(line[5:]) 292 case strings.HasPrefix(line, "Qy = "): 293 pub.Y = fromHex(line[5:]) 294 case strings.HasPrefix(line, "R = "): 295 r = fromHex(line[4:]) 296 case strings.HasPrefix(line, "S = "): 297 s = fromHex(line[4:]) 298 case strings.HasPrefix(line, "Result = "): 299 expected := line[9] == 'P' 300 h.Reset() 301 h.Write(msg) 302 hashed := h.Sum(hashed[:0]) 303 if Verify(pub, hashed, r, s) != expected { 304 t.Fatalf("incorrect result on line %d", lineNo) 305 } 306 default: 307 t.Fatalf("unknown variable on line %d: %s", lineNo, line) 308 } 309 } 310 } 311 312 func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) { 313 key, err := GenerateKey(curve, rand.Reader) 314 if err != nil { 315 t.Errorf("failed to generate key for %q", tag) 316 } 317 318 var hash [32]byte 319 r := new(big.Int).SetInt64(1) 320 r.Lsh(r, 550 /* larger than any supported curve */) 321 r.Neg(r) 322 323 if Verify(&key.PublicKey, hash[:], r, r) { 324 t.Errorf("bogus signature accepted for %q", tag) 325 } 326 } 327 328 func TestNegativeInputs(t *testing.T) { 329 testNegativeInputs(t, elliptic.P224(), "p224") 330 testNegativeInputs(t, elliptic.P256(), "p256") 331 testNegativeInputs(t, elliptic.P384(), "p384") 332 testNegativeInputs(t, elliptic.P521(), "p521") 333 } 334 335 func TestZeroHashSignature(t *testing.T) { 336 zeroHash := make([]byte, 64) 337 338 for _, curve := range []elliptic.Curve{elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521()} { 339 privKey, err := GenerateKey(curve, rand.Reader) 340 if err != nil { 341 panic(err) 342 } 343 344 // Sign a hash consisting of all zeros. 345 r, s, err := Sign(rand.Reader, privKey, zeroHash) 346 if err != nil { 347 panic(err) 348 } 349 350 // Confirm that it can be verified. 351 if !Verify(&privKey.PublicKey, zeroHash, r, s) { 352 t.Errorf("zero hash signature verify failed for %T", curve) 353 } 354 } 355 }