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