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