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  }