...

Source file src/github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa/signature_test.go

Documentation: github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Copyright (c) 2015-2023 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package ecdsa
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/hex"
    11  	"errors"
    12  	"math/rand"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/decred/dcrd/crypto/blake256"
    17  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    18  )
    19  
    20  // hexToBytes converts the passed hex string into bytes and will panic if there
    21  // is an error.  This is only provided for the hard-coded constants so errors in
    22  // the source code can be detected. It will only (and must only) be called with
    23  // hard-coded values.
    24  func hexToBytes(s string) []byte {
    25  	b, err := hex.DecodeString(s)
    26  	if err != nil {
    27  		panic("invalid hex in source file: " + s)
    28  	}
    29  	return b
    30  }
    31  
    32  // TestSignatureParsing ensures that signatures are properly parsed according
    33  // to DER rules.  The error paths are tested as well.
    34  func TestSignatureParsing(t *testing.T) {
    35  	tests := []struct {
    36  		name string
    37  		sig  []byte
    38  		err  error
    39  	}{{
    40  		// signature from Decred blockchain tx
    41  		// 76634e947f49dfc6228c3e8a09cd3e9e15893439fc06df7df0fc6f08d659856c:0
    42  		name: "valid signature 1",
    43  		sig: hexToBytes("3045022100cd496f2ab4fe124f977ffe3caa09f7576d8a34156" +
    44  			"b4e55d326b4dffc0399a094022013500a0510b5094bff220c74656879b8ca03" +
    45  			"69d3da78004004c970790862fc03"),
    46  		err: nil,
    47  	}, {
    48  		// signature from Decred blockchain tx
    49  		// 76634e947f49dfc6228c3e8a09cd3e9e15893439fc06df7df0fc6f08d659856c:1
    50  		name: "valid signature 2",
    51  		sig: hexToBytes("3044022036334e598e51879d10bf9ce3171666bc2d1bbba6164" +
    52  			"cf46dd1d882896ba35d5d022056c39af9ea265c1b6d7eab5bc977f06f81e35c" +
    53  			"dcac16f3ec0fd218e30f2bad2a"),
    54  		err: nil,
    55  	}, {
    56  		name: "empty",
    57  		sig:  nil,
    58  		err:  ErrSigTooShort,
    59  	}, {
    60  		name: "too short",
    61  		sig:  hexToBytes("30050201000200"),
    62  		err:  ErrSigTooShort,
    63  	}, {
    64  		name: "too long",
    65  		sig: hexToBytes("3045022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
    66  			"49f2a1ac584fd546bef074022030e09575e7a1541aa018876a4003cefe1b061a" +
    67  			"90556b5140c63e0ef8481352480101"),
    68  		err: ErrSigTooLong,
    69  	}, {
    70  		name: "bad ASN.1 sequence id",
    71  		sig: hexToBytes("3145022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
    72  			"49f2a1ac584fd546bef074022030e09575e7a1541aa018876a4003cefe1b061a" +
    73  			"90556b5140c63e0ef848135248"),
    74  		err: ErrSigInvalidSeqID,
    75  	}, {
    76  		name: "mismatched data length (short one byte)",
    77  		sig: hexToBytes("3044022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
    78  			"49f2a1ac584fd546bef074022030e09575e7a1541aa018876a4003cefe1b061a" +
    79  			"90556b5140c63e0ef848135248"),
    80  		err: ErrSigInvalidDataLen,
    81  	}, {
    82  		name: "mismatched data length (long one byte)",
    83  		sig: hexToBytes("3046022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
    84  			"49f2a1ac584fd546bef074022030e09575e7a1541aa018876a4003cefe1b061a" +
    85  			"90556b5140c63e0ef848135248"),
    86  		err: ErrSigInvalidDataLen,
    87  	}, {
    88  		name: "bad R ASN.1 int marker",
    89  		sig: hexToBytes("304403204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d6" +
    90  			"24c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56c" +
    91  			"bbac4622082221a8768d1d09"),
    92  		err: ErrSigInvalidRIntID,
    93  	}, {
    94  		name: "zero R length",
    95  		sig: hexToBytes("30240200022030e09575e7a1541aa018876a4003cefe1b061a90" +
    96  			"556b5140c63e0ef848135248"),
    97  		err: ErrSigZeroRLen,
    98  	}, {
    99  		name: "negative R (too little padding)",
   100  		sig: hexToBytes("30440220b2ec8d34d473c3aa2ab5eb7cc4a0783977e5db8c8daf" +
   101  			"777e0b6d7bfa6b6623f302207df6f09af2c40460da2c2c5778f636d3b2e27e20" +
   102  			"d10d90f5a5afb45231454700"),
   103  		err: ErrSigNegativeR,
   104  	}, {
   105  		name: "too much R padding",
   106  		sig: hexToBytes("304402200077f6e93de5ed43cf1dfddaa79fca4b766e1a8fc879" +
   107  			"b0333d377f62538d7eb5022054fed940d227ed06d6ef08f320976503848ed1f5" +
   108  			"2d0dd6d17f80c9c160b01d86"),
   109  		err: ErrSigTooMuchRPadding,
   110  	}, {
   111  		name: "bad S ASN.1 int marker",
   112  		sig: hexToBytes("3045022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
   113  			"49f2a1ac584fd546bef074032030e09575e7a1541aa018876a4003cefe1b061a" +
   114  			"90556b5140c63e0ef848135248"),
   115  		err: ErrSigInvalidSIntID,
   116  	}, {
   117  		name: "missing S ASN.1 int marker",
   118  		sig: hexToBytes("3023022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
   119  			"49f2a1ac584fd546bef074"),
   120  		err: ErrSigMissingSTypeID,
   121  	}, {
   122  		name: "S length missing",
   123  		sig: hexToBytes("3024022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
   124  			"49f2a1ac584fd546bef07402"),
   125  		err: ErrSigMissingSLen,
   126  	}, {
   127  		name: "invalid S length (short one byte)",
   128  		sig: hexToBytes("3045022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
   129  			"49f2a1ac584fd546bef074021f30e09575e7a1541aa018876a4003cefe1b061a" +
   130  			"90556b5140c63e0ef848135248"),
   131  		err: ErrSigInvalidSLen,
   132  	}, {
   133  		name: "invalid S length (long one byte)",
   134  		sig: hexToBytes("3045022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
   135  			"49f2a1ac584fd546bef074022130e09575e7a1541aa018876a4003cefe1b061a" +
   136  			"90556b5140c63e0ef848135248"),
   137  		err: ErrSigInvalidSLen,
   138  	}, {
   139  		name: "zero S length",
   140  		sig: hexToBytes("3025022100f5353150d31a63f4a0d06d1f5a01ac65f7267a719e" +
   141  			"49f2a1ac584fd546bef0740200"),
   142  		err: ErrSigZeroSLen,
   143  	}, {
   144  		name: "negative S (too little padding)",
   145  		sig: hexToBytes("304402204fc10344934662ca0a93a84d14d650d8a21cf2ab91f6" +
   146  			"08e8783d2999c955443202208441aacd6b17038ff3f6700b042934f9a6fea0ce" +
   147  			"c2051b51dc709e52a5bb7d61"),
   148  		err: ErrSigNegativeS,
   149  	}, {
   150  		name: "too much S padding",
   151  		sig: hexToBytes("304402206ad2fdaf8caba0f2cb2484e61b81ced77474b4c2aa06" +
   152  			"9c852df1351b3314fe20022000695ad175b09a4a41cd9433f6b2e8e83253d6a7" +
   153  			"402096ba313a7be1f086dde5"),
   154  		err: ErrSigTooMuchSPadding,
   155  	}, {
   156  		name: "R == 0",
   157  		sig: hexToBytes("30250201000220181522ec8eca07de4860a4acdd12909d831cc5" +
   158  			"6cbbac4622082221a8768d1d09"),
   159  		err: ErrSigRIsZero,
   160  	}, {
   161  		name: "R == N",
   162  		sig: hexToBytes("3045022100fffffffffffffffffffffffffffffffebaaedce6af" +
   163  			"48a03bbfd25e8cd03641410220181522ec8eca07de4860a4acdd12909d831cc5" +
   164  			"6cbbac4622082221a8768d1d09"),
   165  		err: ErrSigRTooBig,
   166  	}, {
   167  		name: "R > N (>32 bytes)",
   168  		sig: hexToBytes("3045022101cd496f2ab4fe124f977ffe3caa09f756283910fc1a" +
   169  			"96f60ee6873e88d3cfe1d50220181522ec8eca07de4860a4acdd12909d831cc5" +
   170  			"6cbbac4622082221a8768d1d09"),
   171  		err: ErrSigRTooBig,
   172  	}, {
   173  		name: "R > N",
   174  		sig: hexToBytes("3045022100fffffffffffffffffffffffffffffffebaaedce6af" +
   175  			"48a03bbfd25e8cd03641420220181522ec8eca07de4860a4acdd12909d831cc5" +
   176  			"6cbbac4622082221a8768d1d09"),
   177  		err: ErrSigRTooBig,
   178  	}, {
   179  		name: "S == 0",
   180  		sig: hexToBytes("302502204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d6" +
   181  			"24c6c61548ab5fb8cd41020100"),
   182  		err: ErrSigSIsZero,
   183  	}, {
   184  		name: "S == N",
   185  		sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d6" +
   186  			"24c6c61548ab5fb8cd41022100fffffffffffffffffffffffffffffffebaaedc" +
   187  			"e6af48a03bbfd25e8cd0364141"),
   188  		err: ErrSigSTooBig,
   189  	}, {
   190  		name: "S > N (>32 bytes)",
   191  		sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d6" +
   192  			"24c6c61548ab5fb8cd4102210113500a0510b5094bff220c74656879b784b246" +
   193  			"ba89c0a07bc49bcf05d8993d44"),
   194  		err: ErrSigSTooBig,
   195  	}, {
   196  		name: "S > N",
   197  		sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d6" +
   198  			"24c6c61548ab5fb8cd41022100fffffffffffffffffffffffffffffffebaaedc" +
   199  			"e6af48a03bbfd25e8cd0364142"),
   200  		err: ErrSigSTooBig,
   201  	}}
   202  
   203  	for _, test := range tests {
   204  		_, err := ParseDERSignature(test.sig)
   205  		if !errors.Is(err, test.err) {
   206  			t.Errorf("%s mismatched err -- got %v, want %v", test.name, err,
   207  				test.err)
   208  			continue
   209  		}
   210  	}
   211  }
   212  
   213  // TestSignatureSerialize ensures that serializing signatures works as expected.
   214  func TestSignatureSerialize(t *testing.T) {
   215  	tests := []struct {
   216  		name     string
   217  		ecsig    *Signature
   218  		expected []byte
   219  	}{{
   220  		// signature from bitcoin blockchain tx
   221  		// 0437cd7f8525ceed2324359c2d0ba26006d92d85
   222  		"valid 1 - r and s most significant bits are zero",
   223  		&Signature{
   224  			r: *hexToModNScalar("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"),
   225  			s: *hexToModNScalar("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"),
   226  		},
   227  		hexToBytes("304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d62" +
   228  			"4c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc" +
   229  			"56cbbac4622082221a8768d1d09"),
   230  	}, {
   231  		// signature from bitcoin blockchain tx
   232  		// cb00f8a0573b18faa8c4f467b049f5d202bf1101d9ef2633bc611be70376a4b4
   233  		"valid 2 - r most significant bit is one",
   234  		&Signature{
   235  			r: *hexToModNScalar("82235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
   236  			s: *hexToModNScalar("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
   237  		},
   238  		hexToBytes("304502210082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c" +
   239  			"30a23b0afbb8d178abcf3022024bf68e256c534ddfaf966bf908deb94430" +
   240  			"5596f7bdcc38d69acad7f9c868724"),
   241  	}, {
   242  		// signature from bitcoin blockchain tx
   243  		// fda204502a3345e08afd6af27377c052e77f1fefeaeb31bdd45f1e1237ca5470
   244  		//
   245  		// Note that signatures with an S component that is > half the group
   246  		// order are neither allowed nor produced in Decred, so this has been
   247  		// modified to expect the equally valid low S signature variant.
   248  		"valid 3 - s most significant bit is one",
   249  		&Signature{
   250  			r: *hexToModNScalar("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"),
   251  			s: *hexToModNScalar("c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"),
   252  		},
   253  		hexToBytes("304402201cadddc2838598fee7dc35a12b340c6bde8b389f7bfd1" +
   254  			"9a1252a17c4b5ed2d7102203e5dae44134eb4fa757428809a2178199e66f" +
   255  			"38daa53df51eaa380cab4222b95"),
   256  	}, {
   257  		"zero signature",
   258  		&Signature{
   259  			r: *new(secp256k1.ModNScalar).SetInt(0),
   260  			s: *new(secp256k1.ModNScalar).SetInt(0),
   261  		},
   262  		hexToBytes("3006020100020100"),
   263  	}}
   264  
   265  	for i, test := range tests {
   266  		result := test.ecsig.Serialize()
   267  		if !bytes.Equal(result, test.expected) {
   268  			t.Errorf("Serialize #%d (%s) unexpected result:\n"+
   269  				"got:  %x\nwant: %x", i, test.name, result,
   270  				test.expected)
   271  		}
   272  	}
   273  }
   274  
   275  // signTest describes tests for producing and verifying ECDSA signatures for a
   276  // selected set of private keys, messages, and nonces that have been verified
   277  // independently with the Sage computer algebra system.  It is defined
   278  // separately since it is intended for use in both normal and compact signature
   279  // tests.
   280  type signTest struct {
   281  	name     string // test description
   282  	key      string // hex encoded private key
   283  	msg      string // hex encoded message to sign before hashing
   284  	hash     string // hex encoded hash of the message to sign
   285  	nonce    string // hex encoded nonce to use in the signature calculation
   286  	rfc6979  bool   // whether or not the nonce is an RFC6979 nonce
   287  	wantSigR string // hex encoded expected signature R
   288  	wantSigS string // hex encoded expected signature S
   289  	wantCode byte   // expected public key recovery code
   290  }
   291  
   292  // signTests returns several tests for ECDSA signatures that use a selected set
   293  // of private keys, messages, and nonces that have been verified independently
   294  // with the Sage computer algebra system.  It is defined here versus inside a
   295  // specific test function scope so it can be shared for both normal and compact
   296  // signature tests.
   297  func signTests(t *testing.T) []signTest {
   298  	t.Helper()
   299  
   300  	tests := []signTest{{
   301  		name:     "key 0x1, blake256(0x01020304), rfc6979 nonce",
   302  		key:      "0000000000000000000000000000000000000000000000000000000000000001",
   303  		msg:      "01020304",
   304  		hash:     "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   305  		nonce:    "4154324ecd4158938f1df8b5b659aeb639c7fbc36005934096e514af7d64bcc2",
   306  		rfc6979:  true,
   307  		wantSigR: "c6c4137b0e5fbfc88ae3f293d7e80c8566c43ae20340075d44f75b009c943d09",
   308  		wantSigS: "00ba213513572e35943d5acdd17215561b03f11663192a7252196cc8b2a99560",
   309  		wantCode: 0,
   310  	}, {
   311  		name:     "key 0x1, blake256(0x01020304), random nonce",
   312  		key:      "0000000000000000000000000000000000000000000000000000000000000001",
   313  		msg:      "01020304",
   314  		hash:     "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   315  		nonce:    "a6df66500afeb7711d4c8e2220960855d940a5ed57260d2c98fbf6066cca283e",
   316  		rfc6979:  false,
   317  		wantSigR: "b073759a96a835b09b79e7b93c37fdbe48fb82b000c4a0e1404ba5d1fbc15d0a",
   318  		wantSigS: "7e34928a3e3832ec21e7711644d9388f7deb6340ead661d7056b0665974b87f3",
   319  		wantCode: pubKeyRecoveryCodeOddnessBit,
   320  	}, {
   321  		name:     "key 0x2, blake256(0x01020304), rfc6979 nonce",
   322  		key:      "0000000000000000000000000000000000000000000000000000000000000002",
   323  		msg:      "01020304",
   324  		hash:     "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   325  		nonce:    "55f96f24cf7531f527edfe3b9222eca12d575367c32a7f593a828dc3651acf49",
   326  		rfc6979:  true,
   327  		wantSigR: "e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59",
   328  		wantSigS: "44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   329  		wantCode: pubKeyRecoveryCodeOddnessBit,
   330  	}, {
   331  		name:     "key 0x2, blake256(0x01020304), random nonce",
   332  		key:      "0000000000000000000000000000000000000000000000000000000000000002",
   333  		msg:      "01020304",
   334  		hash:     "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   335  		nonce:    "679a6d36e7fe6c02d7668af86d78186e8f9ccc04371ac1c8c37939d1f5cae07a",
   336  		rfc6979:  false,
   337  		wantSigR: "4a090d82f48ca12d9e7aa24b5dcc187ee0db2920496f671d63e86036aaa7997e",
   338  		wantSigS: "261ffe8ba45007fc5fbbba6b4c6ed41beafb48b09fa8af1d6a3fbc6ccefbad",
   339  		wantCode: 0,
   340  	}, {
   341  		name:     "key 0x1, blake256(0x0102030405), rfc6979 nonce",
   342  		key:      "0000000000000000000000000000000000000000000000000000000000000001",
   343  		msg:      "0102030405",
   344  		hash:     "dc063eba3c8d52a159e725c1a161506f6cb6b53478ad5ef3f08d534efa871d9f",
   345  		nonce:    "aa87a543c68f2568bb107c9946afa5233bf94fb6a7a063544505282621021629",
   346  		rfc6979:  true,
   347  		wantSigR: "dda8308cdbda2edf51ccf598b42b42b19597e102eb2ed4a04a16dd57084d3b40",
   348  		wantSigS: "0b6d67bab4929624e28f690407a15efc551354544fdc179970ff401eec2e5dc9",
   349  		wantCode: pubKeyRecoveryCodeOddnessBit,
   350  	}, {
   351  		name:     "key 0x1, blake256(0x0102030405), random nonce",
   352  		key:      "0000000000000000000000000000000000000000000000000000000000000001",
   353  		msg:      "0102030405",
   354  		hash:     "dc063eba3c8d52a159e725c1a161506f6cb6b53478ad5ef3f08d534efa871d9f",
   355  		nonce:    "65f880c892fdb6e7f74f76b18c7c942cfd037ef9cf97c39c36e08bbc36b41616",
   356  		rfc6979:  false,
   357  		wantSigR: "72e5666f4e9d1099447b825cf737ee32112f17a67e2ca7017ae098da31dfbb8b",
   358  		wantSigS: "1a7326da661a62f66358dcf53300afdc8e8407939dae1192b5b0899b0254311b",
   359  		wantCode: pubKeyRecoveryCodeOddnessBit,
   360  	}, {
   361  		name:     "key 0x2, blake256(0x0102030405), rfc6979 nonce",
   362  		key:      "0000000000000000000000000000000000000000000000000000000000000002",
   363  		msg:      "0102030405",
   364  		hash:     "dc063eba3c8d52a159e725c1a161506f6cb6b53478ad5ef3f08d534efa871d9f",
   365  		nonce:    "a13d652abd54b6e862548e5d12716df14dc192d93f3fa13536fdf4e56c54f233",
   366  		rfc6979:  true,
   367  		wantSigR: "122663fd29e41a132d3c8329cf05d61ebcca9351074cc277dcd868faba58d87d",
   368  		wantSigS: "353a44f2d949c04981e4e4d9c1f93a9e0644e63a5eaa188288c5ad68fd288d40",
   369  		wantCode: 0,
   370  	}, {
   371  		name:     "key 0x2, blake256(0x0102030405), random nonce",
   372  		key:      "0000000000000000000000000000000000000000000000000000000000000002",
   373  		msg:      "0102030405",
   374  		hash:     "dc063eba3c8d52a159e725c1a161506f6cb6b53478ad5ef3f08d534efa871d9f",
   375  		nonce:    "026ece4cfb704733dd5eef7898e44c33bd5a0d749eb043f48705e40fa9e9afa0",
   376  		rfc6979:  false,
   377  		wantSigR: "3c4c5a2f217ea758113fd4e89eb756314dfad101a300f48e5bd764d3b6e0f8bf",
   378  		wantSigS: "6513e82442f133cb892514926ed9158328ead488ff1b027a31827603a65009df",
   379  		wantCode: pubKeyRecoveryCodeOddnessBit,
   380  	}, {
   381  		name:     "random key 1, blake256(0x01), rfc6979 nonce",
   382  		key:      "a1becef2069444a9dc6331c3247e113c3ee142edda683db8643f9cb0af7cbe33",
   383  		msg:      "01",
   384  		hash:     "4a6c419a1e25c85327115c4ace586decddfe2990ed8f3d4d801871158338501d",
   385  		nonce:    "edb3a01063a0c6ccfc0d77295077cbd322cf364bfa64b7eeea3b20305135d444",
   386  		rfc6979:  true,
   387  		wantSigR: "ef392791d87afca8256c4c9c68d981248ee34a09069f50fa8dfc19ae34cd92ce",
   388  		wantSigS: "0a2b9cb69fd794f7f204c272293b8585a294916a21a11fd94ec04acae2dc6d21",
   389  		wantCode: 0,
   390  	}, {
   391  		name:     "random key 2, blake256(0x02), rfc6979 nonce",
   392  		key:      "59930b76d4b15767ec0e8c8e5812aa2e57db30c6af7963e2a6295ba02af5416b",
   393  		msg:      "02",
   394  		hash:     "49af37ab5270015fe25276ea5a3bb159d852943df23919522a202205fb7d175c",
   395  		nonce:    "af2a59085976494567ef0fc2ecede587b2d1d8e9898cc46e72d7f3e33156e057",
   396  		rfc6979:  true,
   397  		wantSigR: "886c9cccb356b3e1deafef2c276a4f8717ab73c1244c3f673cfbff5897de0e06",
   398  		wantSigS: "609394185495f978ae84b69be90c69947e5dd8dcb4726da604fcbd139d81fc55",
   399  		wantCode: 0,
   400  	}, {
   401  		name:     "random key 3, blake256(0x03), rfc6979 nonce",
   402  		key:      "c5b205c36bb7497d242e96ec19a2a4f086d8daa919135cf490d2b7c0230f0e91",
   403  		msg:      "03",
   404  		hash:     "b706d561742ad3671703c247eb927ee8a386369c79644131cdeb2c5c26bf6c5d",
   405  		nonce:    "82d82b696a386d6d7a111c4cb943bfd39de8e5f6195e7eed9d3edb40fe1419fa",
   406  		rfc6979:  true,
   407  		wantSigR: "6589d5950cec1fe2e7e20593b5ffa3556de20c176720a1796aa77a0cec1ec5a7",
   408  		wantSigS: "2a26deba3241de852e786f5b4e2b98d3efb958d91fe9773b331dbcca9e8be800",
   409  		wantCode: 0,
   410  	}, {
   411  		name:     "random key 4, blake256(0x04), rfc6979 nonce",
   412  		key:      "65b46d4eb001c649a86309286aaf94b18386effe62c2e1586d9b1898ccf0099b",
   413  		msg:      "04",
   414  		hash:     "4c6eb9e38415034f4c93d3304d10bef38bf0ad420eefd0f72f940f11c5857786",
   415  		nonce:    "7afd696a9e770961d2b2eaec77ab7c22c734886fa57bc4a50a9f1946168cd06f",
   416  		rfc6979:  true,
   417  		wantSigR: "81db1d6dca08819ad936d3284a359091e57c036648d477b96af9d8326965a7d1",
   418  		wantSigS: "1bdf719c4be69351ba7617a187ac246912101aea4b5a7d6dfc234478622b43c6",
   419  		wantCode: pubKeyRecoveryCodeOddnessBit,
   420  	}, {
   421  		name:     "random key 5, blake256(0x05), rfc6979 nonce",
   422  		key:      "915cb9ba4675de06a182088b182abcf79fa8ac989328212c6b866fa3ec2338f9",
   423  		msg:      "05",
   424  		hash:     "bdd15db13448905791a70b68137445e607cca06cc71c7a58b9b2e84a06c54d08",
   425  		nonce:    "2a6ae70ea5cf1b932331901d640ece54551f5f33bf9484d5f95c676b5612b527",
   426  		rfc6979:  true,
   427  		wantSigR: "47fd51aecbc743477cb59aa29d18d11d75fb206ae1cdd044216e4f294e33d5b6",
   428  		wantSigS: "3d50edc03066584d50b8d19d681865a23960b37502ede5bf452bdca56744334a",
   429  		wantCode: pubKeyRecoveryCodeOddnessBit,
   430  	}, {
   431  		name:     "random key 6, blake256(0x06), rfc6979 nonce",
   432  		key:      "93e9d81d818f08ba1f850c6dfb82256b035b42f7d43c1fe090804fb009aca441",
   433  		msg:      "06",
   434  		hash:     "19b7506ad9c189a9f8b063d2aee15953d335f5c88480f8515d7d848e7771c4ae",
   435  		nonce:    "0b847a0ae0cbe84dfca66621f04f04b0f2ec190dce10d43ba8c3915c0fcd90ed",
   436  		rfc6979:  true,
   437  		wantSigR: "c99800bc7ac7ea11afe5d7a264f4c26edd63ae9c7ecd6d0d19992980bcda1d34",
   438  		wantSigS: "2844d4c9020ddf9e96b86c1a04788e0f371bd562291fd17ee017db46259d04fb",
   439  		wantCode: pubKeyRecoveryCodeOddnessBit,
   440  	}, {
   441  		name:     "random key 7, blake256(0x07), rfc6979 nonce",
   442  		key:      "c249bbd5f533672b7dcd514eb1256854783531c2b85fe60bf4ce6ea1f26afc2b",
   443  		msg:      "07",
   444  		hash:     "53d661e71e47a0a7e416591200175122d83f8af31be6a70af7417ad6f54d0038",
   445  		nonce:    "0f8e20694fe766d7b79e5ac141e3542f2f3c3d2cc6d0f60e0ec263a46dbe6d49",
   446  		rfc6979:  true,
   447  		wantSigR: "7a57a5222fb7d615eaa0041193f682262cebfa9b448f9c519d3644d0a3348521",
   448  		wantSigS: "574923b7b5aec66b62f1589002db29342c9f5ed56d5e80f5361c0307ff1561fa",
   449  		wantCode: 0,
   450  	}, {
   451  		name:     "random key 8, blake256(0x08), rfc6979 nonce",
   452  		key:      "ec0be92fcec66cf1f97b5c39f83dfd4ddcad0dad468d3685b5eec556c6290bcc",
   453  		msg:      "08",
   454  		hash:     "9bff7982eab6f7883322edf7bdc86a23c87ca1c07906fbb1584f57b197dc6253",
   455  		nonce:    "ab7df49257d18f5f1b730cc7448f46bd82eb43e6e220f521fa7d23802310e24d",
   456  		rfc6979:  true,
   457  		wantSigR: "64f90b09c8b1763a3eeefd156e5d312f80a98c24017811c0163b1c0b01323668",
   458  		wantSigS: "7d7bf4ff295ecfc9578eadc8378b0eea0c0362ad083b0fd1c9b3c06f4537f6ff",
   459  		wantCode: pubKeyRecoveryCodeOddnessBit,
   460  	}, {
   461  		name:     "random key 9, blake256(0x09), rfc6979 nonce",
   462  		key:      "6847b071a7cba6a85099b26a9c3e57a964e4990620e1e1c346fecc4472c4d834",
   463  		msg:      "09",
   464  		hash:     "4c2231813064f8500edae05b40195416bd543fd3e76c16d6efb10c816d92e8b6",
   465  		nonce:    "48ea6c907e1cda596048d812439ccf416eece9a7de400c8a0e40bd48eb7e613a",
   466  		rfc6979:  true,
   467  		wantSigR: "81fc600775d3cdcaa14f8629537299b8226a0c8bfce9320ce64a8d14e3f95bae",
   468  		wantSigS: "3607997d36b48bce957ae9b3d450e0969f6269554312a82bf9499efc8280ea6d",
   469  		wantCode: 0,
   470  	}, {
   471  		name:     "random key 10, blake256(0x0a), rfc6979 nonce",
   472  		key:      "b7548540f52fe20c161a0d623097f827608c56023f50442cc00cc50ad674f6b5",
   473  		msg:      "0a",
   474  		hash:     "e81db4f0d76e02805155441f50c861a8f86374f3ae34c7a3ff4111d3a634ecb1",
   475  		nonce:    "95c07e315cd5457e84270ca01019563c8eeaffb18ab4f23e88a44a0ff01c5f6f",
   476  		rfc6979:  true,
   477  		wantSigR: "0d4cbf2da84f7448b083fce9b9c4e1834b5e2e98defcec7ec87e87c739f5fe78",
   478  		wantSigS: "0997db60683e12b4494702347fc7ae7f599e5a95c629c146e0fc615a1a2acac5",
   479  		wantCode: pubKeyRecoveryCodeOddnessBit,
   480  	}}
   481  
   482  	// Ensure the test data is sane by comparing the provided hashed message and
   483  	// nonce, in the case RFC6979 was used, to their calculated values.  These
   484  	// values could just be calculated instead of specified in the test data,
   485  	// but it's nice to have all of the calculated values available in the test
   486  	// data for cross implementation testing and verification.
   487  	for _, test := range tests {
   488  		msg := hexToBytes(test.msg)
   489  		hash := hexToBytes(test.hash)
   490  
   491  		calcHash := blake256.Sum256(msg)
   492  		if !bytes.Equal(calcHash[:], hash) {
   493  			t.Errorf("%s: mismatched test hash -- expected: %x, given: %x",
   494  				test.name, calcHash[:], hash)
   495  			continue
   496  		}
   497  		if test.rfc6979 {
   498  			privKeyBytes := hexToBytes(test.key)
   499  			nonceBytes := hexToBytes(test.nonce)
   500  			calcNonce := secp256k1.NonceRFC6979(privKeyBytes, hash, nil, nil, 0)
   501  			calcNonceBytes := calcNonce.Bytes()
   502  			if !bytes.Equal(calcNonceBytes[:], nonceBytes) {
   503  				t.Errorf("%s: mismatched test nonce -- expected: %x, given: %x",
   504  					test.name, calcNonceBytes, nonceBytes)
   505  				continue
   506  			}
   507  		}
   508  	}
   509  
   510  	return tests
   511  }
   512  
   513  // TestSignAndVerify ensures the ECDSA signing function produces the expected
   514  // signatures for a selected set of private keys, messages, and nonces that have
   515  // been verified independently with the Sage computer algebra system.  It also
   516  // ensures verifying the signature works as expected.
   517  func TestSignAndVerify(t *testing.T) {
   518  	t.Parallel()
   519  
   520  	tests := signTests(t)
   521  	for _, test := range tests {
   522  		privKey := secp256k1.NewPrivateKey(hexToModNScalar(test.key))
   523  		hash := hexToBytes(test.hash)
   524  		nonce := hexToModNScalar(test.nonce)
   525  		wantSigR := hexToModNScalar(test.wantSigR)
   526  		wantSigS := hexToModNScalar(test.wantSigS)
   527  		wantSig := NewSignature(wantSigR, wantSigS).Serialize()
   528  
   529  		// Sign the hash of the message with the given private key and nonce.
   530  		gotSig, recoveryCode, success := sign(&privKey.Key, nonce, hash)
   531  		if !success {
   532  			t.Errorf("%s: unexpected error when signing", test.name)
   533  			continue
   534  		}
   535  
   536  		// Ensure the generated signature is the expected value.
   537  		gotSigBytes := gotSig.Serialize()
   538  		if !bytes.Equal(gotSigBytes, wantSig) {
   539  			t.Errorf("%s: unexpected signature -- got %x, want %x", test.name,
   540  				gotSigBytes, wantSig)
   541  			continue
   542  		}
   543  
   544  		// Ensure the generated public key recovery code is the expected value.
   545  		if recoveryCode != test.wantCode {
   546  			t.Errorf("%s: unexpected recovery code -- got %x, want %x",
   547  				test.name, recoveryCode, test.wantCode)
   548  			continue
   549  		}
   550  
   551  		// Ensure the R method returns the expected value.
   552  		gotSigR := gotSig.R()
   553  		if !gotSigR.Equals(wantSigR) {
   554  			t.Errorf("%s: unexpected R component -- got %064x, want %064x",
   555  				test.name, gotSigR.Bytes(), wantSigR.Bytes())
   556  		}
   557  
   558  		// Ensure the S method returns the expected value.
   559  		gotSigS := gotSig.S()
   560  		if !gotSigS.Equals(wantSigS) {
   561  			t.Errorf("%s: unexpected S component -- got %064x, want %064x",
   562  				test.name, gotSigS.Bytes(), wantSigS.Bytes())
   563  		}
   564  
   565  		// Ensure the produced signature verifies.
   566  		pubKey := privKey.PubKey()
   567  		if !gotSig.Verify(hash, pubKey) {
   568  			t.Errorf("%s: signature failed to verify", test.name)
   569  			continue
   570  		}
   571  
   572  		// Ensure the signature generated by the exported method is the expected
   573  		// value as well in the case RFC6979 was used.
   574  		if test.rfc6979 {
   575  			gotSig = Sign(privKey, hash)
   576  			gotSigBytes := gotSig.Serialize()
   577  			if !bytes.Equal(gotSigBytes, wantSig) {
   578  				t.Errorf("%s: unexpected signature -- got %x, want %x",
   579  					test.name, gotSigBytes, wantSig)
   580  				continue
   581  			}
   582  		}
   583  	}
   584  }
   585  
   586  // TestSignAndVerifyRandom ensures ECDSA signing and verification work as
   587  // expected for randomly-generated private keys and messages.  It also ensures
   588  // invalid signatures are not improperly verified by mutating the valid
   589  // signature and changing the message the signature covers.
   590  func TestSignAndVerifyRandom(t *testing.T) {
   591  	t.Parallel()
   592  
   593  	// Use a unique random seed each test instance and log it if the tests fail.
   594  	seed := time.Now().Unix()
   595  	rng := rand.New(rand.NewSource(seed))
   596  	defer func(t *testing.T, seed int64) {
   597  		if t.Failed() {
   598  			t.Logf("random seed: %d", seed)
   599  		}
   600  	}(t, seed)
   601  
   602  	for i := 0; i < 100; i++ {
   603  		// Generate a random private key.
   604  		var buf [32]byte
   605  		if _, err := rng.Read(buf[:]); err != nil {
   606  			t.Fatalf("failed to read random private key: %v", err)
   607  		}
   608  		var privKeyScalar secp256k1.ModNScalar
   609  		privKeyScalar.SetBytes(&buf)
   610  		privKey := secp256k1.NewPrivateKey(&privKeyScalar)
   611  
   612  		// Generate a random hash to sign.
   613  		var hash [32]byte
   614  		if _, err := rng.Read(hash[:]); err != nil {
   615  			t.Fatalf("failed to read random hash: %v", err)
   616  		}
   617  
   618  		// Sign the hash with the private key and then ensure the produced
   619  		// signature is valid for the hash and public key associated with the
   620  		// private key.
   621  		sig := Sign(privKey, hash[:])
   622  		pubKey := privKey.PubKey()
   623  		if !sig.Verify(hash[:], pubKey) {
   624  			t.Fatalf("failed to verify signature\nsig: %x\nhash: %x\n"+
   625  				"private key: %x\npublic key: %x", sig.Serialize(), hash,
   626  				privKey.Serialize(), pubKey.SerializeCompressed())
   627  		}
   628  
   629  		// Change a random bit in the signature and ensure the bad signature
   630  		// fails to verify the original message.
   631  		badSig := *sig
   632  		randByte := rng.Intn(32)
   633  		randBit := rng.Intn(7)
   634  		if randComponent := rng.Intn(2); randComponent == 0 {
   635  			badSigBytes := badSig.r.Bytes()
   636  			badSigBytes[randByte] ^= 1 << randBit
   637  			badSig.r.SetBytes(&badSigBytes)
   638  		} else {
   639  			badSigBytes := badSig.s.Bytes()
   640  			badSigBytes[randByte] ^= 1 << randBit
   641  			badSig.s.SetBytes(&badSigBytes)
   642  		}
   643  		if badSig.Verify(hash[:], pubKey) {
   644  			t.Fatalf("verified bad signature\nsig: %x\nhash: %x\n"+
   645  				"private key: %x\npublic key: %x", badSig.Serialize(), hash,
   646  				privKey.Serialize(), pubKey.SerializeCompressed())
   647  		}
   648  
   649  		// Change a random bit in the hash that was originally signed and ensure
   650  		// the original good signature fails to verify the new bad message.
   651  		badHash := make([]byte, len(hash))
   652  		copy(badHash, hash[:])
   653  		randByte = rng.Intn(len(badHash))
   654  		randBit = rng.Intn(7)
   655  		badHash[randByte] ^= 1 << randBit
   656  		if sig.Verify(badHash, pubKey) {
   657  			t.Fatalf("verified signature for bad hash\nsig: %x\nhash: %x\n"+
   658  				"pubkey: %x", sig.Serialize(), badHash,
   659  				pubKey.SerializeCompressed())
   660  		}
   661  	}
   662  }
   663  
   664  // TestSignFailures ensures the internal ECDSA signing function returns an
   665  // unsuccessful result when particular combinations of values are unable to
   666  // produce a valid signature.
   667  func TestSignFailures(t *testing.T) {
   668  	t.Parallel()
   669  
   670  	tests := []struct {
   671  		name  string // test description
   672  		key   string // hex encoded private key
   673  		hash  string // hex encoded hash of the message to sign
   674  		nonce string // hex encoded nonce to use in the signature calculation
   675  	}{{
   676  		name:  "zero R is invalid (forced by using zero nonce)",
   677  		key:   "0000000000000000000000000000000000000000000000000000000000000001",
   678  		hash:  "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   679  		nonce: "0000000000000000000000000000000000000000000000000000000000000000",
   680  	}, {
   681  		name:  "zero S is invalid (forced by key/hash/nonce choice)",
   682  		key:   "0000000000000000000000000000000000000000000000000000000000000001",
   683  		hash:  "393bec84f1a04037751c0d6c2817f37953eaa204ac0898de7adb038c33a20438",
   684  		nonce: "4154324ecd4158938f1df8b5b659aeb639c7fbc36005934096e514af7d64bcc2",
   685  	}}
   686  
   687  	for _, test := range tests {
   688  		privKey := hexToModNScalar(test.key)
   689  		hash := hexToBytes(test.hash)
   690  		nonce := hexToModNScalar(test.nonce)
   691  
   692  		// Ensure the signing is NOT successful.
   693  		sig, _, success := sign(privKey, nonce, hash)
   694  		if success {
   695  			t.Errorf("%s: unexpected success -- got sig %x", test.name,
   696  				sig.Serialize())
   697  			continue
   698  		}
   699  	}
   700  }
   701  
   702  // TestVerifyFailures ensures the ECDSA verification function returns an
   703  // unsuccessful result for edge conditions.
   704  func TestVerifyFailures(t *testing.T) {
   705  	t.Parallel()
   706  
   707  	tests := []struct {
   708  		name string // test description
   709  		key  string // hex encoded private key
   710  		hash string // hex encoded hash of the message to sign
   711  		r, s string // hex encoded r and s components of signature to verify
   712  	}{{
   713  		name: "signature R is 0",
   714  		key:  "0000000000000000000000000000000000000000000000000000000000000001",
   715  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   716  		r:    "0000000000000000000000000000000000000000000000000000000000000000",
   717  		s:    "00ba213513572e35943d5acdd17215561b03f11663192a7252196cc8b2a99560",
   718  	}, {
   719  		name: "signature S is 0",
   720  		key:  "0000000000000000000000000000000000000000000000000000000000000001",
   721  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   722  		r:    "c6c4137b0e5fbfc88ae3f293d7e80c8566c43ae20340075d44f75b009c943d09",
   723  		s:    "0000000000000000000000000000000000000000000000000000000000000000",
   724  	}, {
   725  		name: "u1G + u2Q is the point at infinity",
   726  		key:  "0000000000000000000000000000000000000000000000000000000000000001",
   727  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   728  		r:    "3cfe45621a29fac355260a14b9adc0fe43ac2f13e918fc9ddfa117e964b61a8a",
   729  		s:    "00ba213513572e35943d5acdd17215561b03f11663192a7252196cc8b2a99560",
   730  	}, {
   731  		name: "signature R < P-N, but invalid",
   732  		key:  "0000000000000000000000000000000000000000000000000000000000000001",
   733  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   734  		r:    "000000000000000000000000000000014551231950b75fc4402da1722fc9baed",
   735  		s:    "00ba213513572e35943d5acdd17215561b03f11663192a7252196cc8b2a99560",
   736  	}}
   737  
   738  	for _, test := range tests {
   739  		privKey := hexToModNScalar(test.key)
   740  		hash := hexToBytes(test.hash)
   741  		r := hexToModNScalar(test.r)
   742  		s := hexToModNScalar(test.s)
   743  		sig := NewSignature(r, s)
   744  
   745  		// Ensure the verification is NOT successful.
   746  		pubKey := secp256k1.NewPrivateKey(privKey).PubKey()
   747  		if sig.Verify(hash, pubKey) {
   748  			t.Errorf("%s: unexpected success for invalid signature: %x",
   749  				test.name, sig.Serialize())
   750  			continue
   751  		}
   752  	}
   753  }
   754  
   755  // TestSignatureIsEqual ensures that equality testing between two signatures
   756  // works as expected.
   757  func TestSignatureIsEqual(t *testing.T) {
   758  	sig1 := &Signature{
   759  		r: *hexToModNScalar("82235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
   760  		s: *hexToModNScalar("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
   761  	}
   762  	sig1Copy := &Signature{
   763  		r: *hexToModNScalar("82235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"),
   764  		s: *hexToModNScalar("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"),
   765  	}
   766  	sig2 := &Signature{
   767  		r: *hexToModNScalar("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"),
   768  		s: *hexToModNScalar("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"),
   769  	}
   770  
   771  	if !sig1.IsEqual(sig1) {
   772  		t.Fatalf("bad self signature equality check: %v == %v", sig1, sig1Copy)
   773  	}
   774  	if !sig1.IsEqual(sig1Copy) {
   775  		t.Fatalf("bad signature equality check: %v == %v", sig1, sig1Copy)
   776  	}
   777  
   778  	if sig1.IsEqual(sig2) {
   779  		t.Fatalf("bad signature equality check: %v != %v", sig1, sig2)
   780  	}
   781  }
   782  
   783  // TestSignAndRecoverCompact ensures compact (recoverable public key) ECDSA
   784  // signing and public key recovery works as expected for a selected set of
   785  // private keys, messages, and nonces that have been verified independently with
   786  // the Sage computer algebra system.
   787  func TestSignAndRecoverCompact(t *testing.T) {
   788  	t.Parallel()
   789  
   790  	tests := signTests(t)
   791  	for _, test := range tests {
   792  		// Skip tests using nonces that are not RFC6979.
   793  		if !test.rfc6979 {
   794  			continue
   795  		}
   796  
   797  		// Parse test data.
   798  		privKey := secp256k1.NewPrivateKey(hexToModNScalar(test.key))
   799  		pubKey := privKey.PubKey()
   800  		hash := hexToBytes(test.hash)
   801  		wantSig := hexToBytes("00" + test.wantSigR + test.wantSigS)
   802  
   803  		// Test compact signatures for both the compressed and uncompressed
   804  		// versions of the public key.
   805  		for _, compressed := range []bool{true, false} {
   806  			// Populate the expected compact signature recovery code.
   807  			wantRecoveryCode := compactSigMagicOffset + test.wantCode
   808  			if compressed {
   809  				wantRecoveryCode += compactSigCompPubKey
   810  			}
   811  			wantSig[0] = wantRecoveryCode
   812  
   813  			// Sign the hash of the message with the given private key and
   814  			// ensure the generated signature is the expected value per the
   815  			// specified compressed flag.
   816  			gotSig := SignCompact(privKey, hash, compressed)
   817  			if !bytes.Equal(gotSig, wantSig) {
   818  				t.Errorf("%s: unexpected signature -- got %x, want %x",
   819  					test.name, gotSig, wantSig)
   820  				continue
   821  			}
   822  
   823  			// Ensure the recovered public key and flag that indicates whether
   824  			// or not the signature was for a compressed public key are the
   825  			// expected values.
   826  			gotPubKey, gotCompressed, err := RecoverCompact(gotSig, hash)
   827  			if err != nil {
   828  				t.Errorf("%s: unexpected error when recovering: %v", test.name,
   829  					err)
   830  				continue
   831  			}
   832  			if gotCompressed != compressed {
   833  				t.Errorf("%s: unexpected compressed flag -- got %v, want %v",
   834  					test.name, gotCompressed, compressed)
   835  				continue
   836  			}
   837  			if !gotPubKey.IsEqual(pubKey) {
   838  				t.Errorf("%s: unexpected public key -- got %x, want %x",
   839  					test.name, gotPubKey.SerializeUncompressed(),
   840  					pubKey.SerializeUncompressed())
   841  				continue
   842  			}
   843  		}
   844  	}
   845  }
   846  
   847  // TestRecoverCompactErrors ensures several error paths in compact signature
   848  // recovery are detected as expected.  When possible, the signatures are
   849  // otherwise valid with the exception of the specific failure to ensure it's
   850  // robust against things like fault attacks.
   851  func TestRecoverCompactErrors(t *testing.T) {
   852  	t.Parallel()
   853  
   854  	tests := []struct {
   855  		name string // test description
   856  		sig  string // hex encoded signature to recover pubkey from
   857  		hash string // hex encoded hash of message
   858  		err  error  // expected error
   859  	}{{
   860  		name: "empty signature",
   861  		sig:  "",
   862  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   863  		err:  ErrSigInvalidLen,
   864  	}, {
   865  		// Signature created from private key 0x02, blake256(0x01020304).
   866  		name: "no compact sig recovery code (otherwise valid sig)",
   867  		sig: "e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   868  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   869  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   870  		err:  ErrSigInvalidLen,
   871  	}, {
   872  		// Signature created from private key 0x02, blake256(0x01020304).
   873  		name: "signature one byte too long (S padded with leading zero)",
   874  		sig: "1f" +
   875  			"e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   876  			"0044b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   877  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   878  		err:  ErrSigInvalidLen,
   879  	}, {
   880  		// Signature created from private key 0x02, blake256(0x01020304).
   881  		name: "compact sig recovery code too low (otherwise valid sig)",
   882  		sig: "1a" +
   883  			"e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   884  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   885  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   886  		err:  ErrSigInvalidRecoveryCode,
   887  	}, {
   888  		// Signature created from private key 0x02, blake256(0x01020304).
   889  		name: "compact sig recovery code too high (otherwise valid sig)",
   890  		sig: "23" +
   891  			"e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   892  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   893  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   894  		err:  ErrSigInvalidRecoveryCode,
   895  	}, {
   896  		// Signature invented since finding a signature with an r value that is
   897  		// exactly the group order prior to the modular reduction is not
   898  		// calculable without breaking the underlying crypto.
   899  		name: "R == group order",
   900  		sig: "1f" +
   901  			"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" +
   902  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   903  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   904  		err:  ErrSigRTooBig,
   905  	}, {
   906  		// Signature invented since finding a signature with an r value that
   907  		// would be valid modulo the group order and is still 32 bytes is not
   908  		// calculable without breaking the underlying crypto.
   909  		name: "R > group order and still 32 bytes (order + 1)",
   910  		sig: "1f" +
   911  			"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142" +
   912  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   913  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   914  		err:  ErrSigRTooBig,
   915  	}, {
   916  		// Signature invented since the only way a signature could have an r
   917  		// value of zero is if the nonce were zero which is invalid.
   918  		name: "R == 0",
   919  		sig: "1f" +
   920  			"0000000000000000000000000000000000000000000000000000000000000000" +
   921  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   922  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   923  		err:  ErrSigRIsZero,
   924  	}, {
   925  		// Signature invented since finding a signature with an s value that is
   926  		// exactly the group order prior to the modular reduction is not
   927  		// calculable without breaking the underlying crypto.
   928  		name: "S == group order",
   929  		sig: "1f" +
   930  			"e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   931  			"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
   932  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   933  		err:  ErrSigSTooBig,
   934  	}, {
   935  		// Signature invented since finding a signature with an s value that
   936  		// would be valid modulo the group order and is still 32 bytes is not
   937  		// calculable without breaking the underlying crypto.
   938  		name: "S > group order and still 32 bytes (order + 1)",
   939  		sig: "1f" +
   940  			"e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   941  			"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142",
   942  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   943  		err:  ErrSigSTooBig,
   944  	}, {
   945  		// Signature created by forcing the key/hash/nonce choices such that s
   946  		// is zero and is therefore invalid.  The signing code will not produce
   947  		// such a signature in practice.
   948  		name: "S == 0",
   949  		sig: "1f" +
   950  			"e6f137b52377250760cc702e19b7aee3c63b0e7d95a91939b14ab3b5c4771e59" +
   951  			"0000000000000000000000000000000000000000000000000000000000000000",
   952  		hash: "393bec84f1a04037751c0d6c2817f37953eaa204ac0898de7adb038c33a20438",
   953  		err:  ErrSigSIsZero,
   954  	}, {
   955  		// Signature invented since finding a private key needed to create a
   956  		// valid signature with an r value that is >= group order prior to the
   957  		// modular reduction is not possible without breaking the underlying
   958  		// crypto.
   959  		name: "R >= field prime minus group order with overflow bit",
   960  		sig: "21" +
   961  			"000000000000000000000000000000014551231950b75fc4402da1722fc9baee" +
   962  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   963  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   964  		err:  ErrSigOverflowsPrime,
   965  	}, {
   966  		// Signature invented since finding a private key needed to create a
   967  		// valid signature with an r value that is > group order prior to the
   968  		// modular reduction is not possible without breaking the underlying
   969  		// crypto.
   970  		name: "R > group order with overflow bit",
   971  		sig: "21" +
   972  			"000000000000000000000000000000014551231950b75fc4402da1722fc9baed" +
   973  			"44b9bc4620afa158b7efdfea5234ff2d5f2f78b42886f02cf581827ee55318ea",
   974  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   975  		err:  ErrPointNotOnCurve,
   976  	}, {
   977  		// Signature created from private key 0x01, blake256(0x0102030407) over
   978  		// the secp256r1 curve (note the r1 instead of k1).
   979  		name: "pubkey not on the curve, signature valid for secp256r1 instead",
   980  		sig: "1f" +
   981  			"2a81d1b3facc22185267d3f8832c5104902591bc471253f1cfc5eb25f4f740f2" +
   982  			"72e65d019f9b09d769149e2be0b55de9b0224d34095bddc6a5dba90bfda33c45",
   983  		hash: "9165e957708bc95cf62d020769c150b2d7b08e7ab7981860815b1eaabd41d695",
   984  		err:  ErrPointNotOnCurve,
   985  	}, {
   986  		// Signature created from private key 0x01, blake256(0x01020304) and
   987  		// manually setting s = -e*k^-1.
   988  		name: "calculated pubkey point at infinity",
   989  		sig: "1f" +
   990  			"c6c4137b0e5fbfc88ae3f293d7e80c8566c43ae20340075d44f75b009c943d09" +
   991  			"1281d8d90a5774045abd57b453c7eadbc830dbadec89ae8dd7639b9cc55641d0",
   992  		hash: "c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7",
   993  		err:  ErrPointNotOnCurve,
   994  	}}
   995  
   996  	for _, test := range tests {
   997  		// Parse test data.
   998  		hash := hexToBytes(test.hash)
   999  		sig := hexToBytes(test.sig)
  1000  
  1001  		// Ensure the expected error is hit.
  1002  		_, _, err := RecoverCompact(sig, hash)
  1003  		if !errors.Is(err, test.err) {
  1004  			t.Errorf("%s: mismatched err -- got %v, want %v", test.name, err,
  1005  				test.err)
  1006  			continue
  1007  		}
  1008  	}
  1009  }
  1010  
  1011  // TestSignAndRecoverCompactRandom ensures compact (recoverable public key)
  1012  // ECDSA signing and recovery work as expected for randomly-generated private
  1013  // keys and messages.  It also ensures mutated signatures and messages do not
  1014  // improperly recover the original public key.
  1015  func TestSignAndRecoverCompactRandom(t *testing.T) {
  1016  	t.Parallel()
  1017  
  1018  	// Use a unique random seed each test instance and log it if the tests fail.
  1019  	seed := time.Now().Unix()
  1020  	rng := rand.New(rand.NewSource(seed))
  1021  	defer func(t *testing.T, seed int64) {
  1022  		if t.Failed() {
  1023  			t.Logf("random seed: %d", seed)
  1024  		}
  1025  	}(t, seed)
  1026  
  1027  	for i := 0; i < 100; i++ {
  1028  		// Generate a random private key.
  1029  		var buf [32]byte
  1030  		if _, err := rng.Read(buf[:]); err != nil {
  1031  			t.Fatalf("failed to read random private key: %v", err)
  1032  		}
  1033  		var privKeyScalar secp256k1.ModNScalar
  1034  		privKeyScalar.SetBytes(&buf)
  1035  		privKey := secp256k1.NewPrivateKey(&privKeyScalar)
  1036  		wantPubKey := privKey.PubKey()
  1037  
  1038  		// Generate a random hash to sign.
  1039  		var hash [32]byte
  1040  		if _, err := rng.Read(hash[:]); err != nil {
  1041  			t.Fatalf("failed to read random hash: %v", err)
  1042  		}
  1043  
  1044  		// Test compact signatures for both the compressed and uncompressed
  1045  		// versions of the public key.
  1046  		for _, compressed := range []bool{true, false} {
  1047  			// Sign the hash with the private key and then ensure the original
  1048  			// public key and compressed flag is recovered from the produced
  1049  			// signature.
  1050  			gotSig := SignCompact(privKey, hash[:], compressed)
  1051  
  1052  			gotPubKey, gotCompressed, err := RecoverCompact(gotSig, hash[:])
  1053  			if err != nil {
  1054  				t.Fatalf("unexpected err: %v\nsig: %x\nhash: %x\nprivate key: %x",
  1055  					err, gotSig, hash, privKey.Serialize())
  1056  			}
  1057  			if gotCompressed != compressed {
  1058  				t.Fatalf("unexpected compressed flag: %v\nsig: %x\nhash: %x\n"+
  1059  					"private key: %x", gotCompressed, gotSig, hash,
  1060  					privKey.Serialize())
  1061  			}
  1062  			if !gotPubKey.IsEqual(wantPubKey) {
  1063  				t.Fatalf("unexpected recovered public key: %x\nsig: %x\nhash: "+
  1064  					"%x\nprivate key: %x", gotPubKey.SerializeUncompressed(),
  1065  					gotSig, hash, privKey.Serialize())
  1066  			}
  1067  
  1068  			// Change a random bit in the signature and ensure the bad signature
  1069  			// fails to recover the original public key.
  1070  			badSig := make([]byte, len(gotSig))
  1071  			copy(badSig, gotSig)
  1072  			randByte := rng.Intn(len(badSig)-1) + 1
  1073  			randBit := rng.Intn(7)
  1074  			badSig[randByte] ^= 1 << randBit
  1075  			badPubKey, _, err := RecoverCompact(badSig, hash[:])
  1076  			if err == nil && badPubKey.IsEqual(wantPubKey) {
  1077  				t.Fatalf("recovered public key for bad sig: %x\nhash: %x\n"+
  1078  					"private key: %x", badSig, hash, privKey.Serialize())
  1079  			}
  1080  
  1081  			// Change a random bit in the hash that was originally signed and
  1082  			// ensure the original good signature fails to recover the original
  1083  			// public key.
  1084  			badHash := make([]byte, len(hash))
  1085  			copy(badHash, hash[:])
  1086  			randByte = rng.Intn(len(badHash))
  1087  			randBit = rng.Intn(7)
  1088  			badHash[randByte] ^= 1 << randBit
  1089  			badPubKey, _, err = RecoverCompact(gotSig, badHash)
  1090  			if err == nil && badPubKey.IsEqual(wantPubKey) {
  1091  				t.Fatalf("recovered public key for bad hash: %x\nsig: %x\n"+
  1092  					"private key: %x", badHash, gotSig, privKey.Serialize())
  1093  			}
  1094  		}
  1095  	}
  1096  }
  1097  

View as plain text