signature_test.go raw

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