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