...
Run Format

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

View as plain text