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