...

Source file src/crypto/ecdsa/ecdsa_test.go

Documentation: crypto/ecdsa

		 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 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  		// This should never happen.
	 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  	// This test runs the full set of NIST test vectors from
	 178  	// https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
	 179  	//
	 180  	// The SigVer.rsp file has been edited to remove test vectors for
	 181  	// unsupported algorithms and has been compressed.
	 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  		// Need to remove \r\n from the end of the line.
	 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 /* larger than any supported curve */)
	 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  	// Sign a hash consisting of all zeros.
	 319  	r, s, err := Sign(rand.Reader, privKey, zeroHash)
	 320  	if err != nil {
	 321  		panic(err)
	 322  	}
	 323  
	 324  	// Confirm that it can be verified.
	 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  			// Prevent the compiler from optimizing out the operation.
	 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