nonce_test.go raw

   1  // Copyright (c) 2013-2016 The btcsuite developers
   2  // Copyright (c) 2015-2020 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 secp256k1
   7  
   8  import (
   9  	"testing"
  10  
  11  	"next.orly.dev/pkg/nostr/encoders/hex"
  12  	"next.orly.dev/pkg/nostr/utils"
  13  	"github.com/minio/sha256-simd"
  14  )
  15  
  16  // hexToBytes converts the passed hex string into bytes and will panic if there
  17  // is an error.  This is only provided for the hard-coded constants so errors in
  18  // the source code can be detected. It will only (and must only) be called with
  19  // hard-coded values.
  20  func hexToBytes(s string) []byte {
  21  	b, err := hex.Dec(s)
  22  	if err != nil {
  23  		panic("invalid hex in source file: " + s)
  24  	}
  25  	return b
  26  }
  27  
  28  // TestNonceRFC6979 ensures that the deterministic nonces generated by
  29  // NonceRFC6979 produces the expected nonces, including things such as when
  30  // providing extra data and version information, short hashes, and multiple
  31  // iterations.
  32  func TestNonceRFC6979(t *testing.T) {
  33  	tests := []struct {
  34  		name       string
  35  		key        string
  36  		hash       string
  37  		extraData  string
  38  		version    string
  39  		iterations uint32
  40  		expected   string
  41  	}{
  42  		{
  43  			name:       "key 32 bytes, hash 32 bytes, no extra data, no version",
  44  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
  45  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  46  			iterations: 0,
  47  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  48  		}, {
  49  			// Should be same as key with 32 bytes due to zero padding.
  50  			name:       "key <32 bytes, hash 32 bytes, no extra data, no version",
  51  			key:        "11111111111111111111111111111111111111111111111111111111111111",
  52  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  53  			iterations: 0,
  54  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  55  		}, {
  56  			// Should be same as key with 32 bytes due to truncation.
  57  			name:       "key >32 bytes, hash 32 bytes, no extra data, no version",
  58  			key:        "001111111111111111111111111111111111111111111111111111111111111111",
  59  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  60  			iterations: 0,
  61  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  62  		}, {
  63  			name:       "hash <32 bytes (padded), no extra data, no version",
  64  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
  65  			hash:       "00000000000000000000000000000000000000000000000000000000000001",
  66  			iterations: 0,
  67  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  68  		}, {
  69  			name:       "hash >32 bytes (truncated), no extra data, no version",
  70  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
  71  			hash:       "000000000000000000000000000000000000000000000000000000000000000100",
  72  			iterations: 0,
  73  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  74  		}, {
  75  			name:       "hash 32 bytes, extra data <32 bytes (ignored), no version",
  76  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
  77  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  78  			extraData:  "00000000000000000000000000000000000000000000000000000000000002",
  79  			iterations: 0,
  80  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  81  		}, {
  82  			name:       "hash 32 bytes, extra data >32 bytes (ignored), no version",
  83  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
  84  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  85  			extraData:  "000000000000000000000000000000000000000000000000000000000000000002",
  86  			iterations: 0,
  87  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  88  		}, {
  89  			name:       "hash 32 bytes, no extra data, version <16 bytes (ignored)",
  90  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
  91  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  92  			version:    "000000000000000000000000000003",
  93  			iterations: 0,
  94  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
  95  		}, {
  96  			name:       "hash 32 bytes, no extra data, version >16 bytes (ignored)",
  97  			key:        "001111111111111111111111111111111111111111111111111111111111111122",
  98  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
  99  			version:    "0000000000000000000000000000000003",
 100  			iterations: 0,
 101  			expected:   "154e92760f77ad9af6b547edd6f14ad0fae023eb2221bc8be2911675d8a686a3",
 102  		}, {
 103  			name:       "hash 32 bytes, extra data 32 bytes, no version",
 104  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
 105  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
 106  			extraData:  "0000000000000000000000000000000000000000000000000000000000000002",
 107  			iterations: 0,
 108  			expected:   "67893461ade51cde61824b20bc293b585d058e6b9f40fb68453d5143f15116ae",
 109  		}, {
 110  			name:       "hash 32 bytes, no extra data, version 16 bytes",
 111  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
 112  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
 113  			version:    "00000000000000000000000000000003",
 114  			iterations: 0,
 115  			expected:   "7b27d6ceff87e1ded1860ca4e271a530e48514b9d3996db0af2bb8bda189007d",
 116  		}, {
 117  			// Should be same as no extra data + version specified due to padding.
 118  			name:       "hash 32 bytes, extra data 32 bytes all zero, version 16 bytes",
 119  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
 120  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
 121  			extraData:  "0000000000000000000000000000000000000000000000000000000000000000",
 122  			version:    "00000000000000000000000000000003",
 123  			iterations: 0,
 124  			expected:   "7b27d6ceff87e1ded1860ca4e271a530e48514b9d3996db0af2bb8bda189007d",
 125  		}, {
 126  			name:       "hash 32 bytes, extra data 32 bytes, version 16 bytes",
 127  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
 128  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
 129  			extraData:  "0000000000000000000000000000000000000000000000000000000000000002",
 130  			version:    "00000000000000000000000000000003",
 131  			iterations: 0,
 132  			expected:   "9b5657643dfd4b77d99dfa505ed8a17e1b9616354fc890669b4aabece2170686",
 133  		}, {
 134  			name:       "hash 32 bytes, no extra data, no version, extra iteration",
 135  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
 136  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
 137  			iterations: 1,
 138  			expected:   "66fca3fe494a6216e4a3f15cfbc1d969c60d9cdefda1a1c193edabd34aa8cd5e",
 139  		}, {
 140  			name:       "hash 32 bytes, no extra data, no version, 2 extra iterations",
 141  			key:        "0011111111111111111111111111111111111111111111111111111111111111",
 142  			hash:       "0000000000000000000000000000000000000000000000000000000000000001",
 143  			iterations: 2,
 144  			expected:   "70da248c92b5d28a52eafca1848b1a37d4cb36526c02553c9c48bb0b895fc77d",
 145  		},
 146  	}
 147  	for _, test := range tests {
 148  		secKey := hexToBytes(test.key)
 149  		hash := hexToBytes(test.hash)
 150  		extraData := hexToBytes(test.extraData)
 151  		version := hexToBytes(test.version)
 152  		wantNonce := hexToBytes(test.expected)
 153  		// Ensure deterministically generated nonce is the expected value.
 154  		gotNonce := NonceRFC6979(
 155  			secKey, hash[:], extraData, version,
 156  			test.iterations,
 157  		)
 158  		gotNonceBytes := gotNonce.Bytes()
 159  		if !utils.FastEqual(gotNonceBytes[:], wantNonce) {
 160  			t.Errorf(
 161  				"%s: unexpected nonce -- got %x, want %x", test.name,
 162  				gotNonceBytes, wantNonce,
 163  			)
 164  			continue
 165  		}
 166  	}
 167  }
 168  
 169  // TestRFC6979Compat ensures that the deterministic nonces generated by
 170  // NonceRFC6979 produces the expected nonces for known values from other
 171  // implementations.
 172  func TestRFC6979Compat(t *testing.T) {
 173  	// Test vectors matching Trezor and CoreBitcoin implementations.
 174  	// - https://github.com/trezor/trezor-crypto/blob/9fea8f8ab377dc514e40c6fd1f7c89a74c1d8dc6/tests.c#L432-L453
 175  	// - https://github.com/oleganza/CoreBitcoin/blob/e93dd71207861b5bf044415db5fa72405e7d8fbc/CoreBitcoin/BTCKey%2BTests.m#L23-L49
 176  	tests := []struct {
 177  		key   string
 178  		msg   string
 179  		nonce string
 180  	}{
 181  		{
 182  			"cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
 183  			"sample",
 184  			"2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3",
 185  		}, {
 186  			// This signature hits the case when S is higher than halforder.
 187  			// If S is not canonicalized (lowered by halforder), this test will fail.
 188  			"0000000000000000000000000000000000000000000000000000000000000001",
 189  			"Satoshi Nakamoto",
 190  			"8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15",
 191  		}, {
 192  			"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
 193  			"Satoshi Nakamoto",
 194  			"33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90",
 195  		}, {
 196  			"f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181",
 197  			"Alan Turing",
 198  			"525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1",
 199  		}, {
 200  			"0000000000000000000000000000000000000000000000000000000000000001",
 201  			"All those moments will be lost in time, like tears in rain. Time to die...",
 202  			"38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3",
 203  		}, {
 204  			"e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2",
 205  			"There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!",
 206  			"1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d",
 207  		},
 208  	}
 209  	for i, test := range tests {
 210  		secKey := hexToBytes(test.key)
 211  		hash := sha256.Sum256([]byte(test.msg))
 212  		// Ensure deterministically generated nonce is the expected value.
 213  		gotNonce := NonceRFC6979(secKey, hash[:], nil, nil, 0)
 214  		wantNonce := hexToBytes(test.nonce)
 215  		gotNonceBytes := gotNonce.Bytes()
 216  		if !utils.FastEqual(gotNonceBytes[:], wantNonce) {
 217  			t.Errorf(
 218  				"NonceRFC6979 #%d (%s): Nonce is incorrect: "+
 219  					"%x (expected %x)", i, test.msg, gotNonce,
 220  				wantNonce,
 221  			)
 222  			continue
 223  		}
 224  	}
 225  }
 226