1
2
3
4
5 package secp256k1
6
7 import (
8 "math/big"
9 "math/rand"
10 "testing"
11 "time"
12 )
13
14
15
16 func randBytes(t *testing.T, rng *rand.Rand, numBytes uint8) []byte {
17 t.Helper()
18
19 buf := make([]byte, numBytes)
20 if _, err := rng.Read(buf); err != nil {
21 t.Fatalf("failed to read random: %v", err)
22 }
23
24 return buf
25 }
26
27
28
29 func TestIsOnCurveAdaptor(t *testing.T) {
30 s256 := S256()
31 if !s256.IsOnCurve(s256.Params().Gx, s256.Params().Gy) {
32 t.Fatal("generator point does not claim to be on the curve")
33 }
34 }
35
36
37
38 func isValidAffinePoint(x, y *big.Int) bool {
39 if x.Sign() == 0 && y.Sign() == 0 {
40 return true
41 }
42 return S256().IsOnCurve(x, y)
43 }
44
45
46
47
48 func TestAddAffineAdaptor(t *testing.T) {
49 tests := []struct {
50 name string
51 x1, y1 string
52 x2, y2 string
53 x3, y3 string
54 }{{
55
56 name: "∞ + P = P",
57 x1: "0",
58 y1: "0",
59 x2: "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
60 y2: "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
61 x3: "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
62 y3: "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
63 }, {
64
65 name: "P + ∞ = P",
66 x1: "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
67 y1: "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
68 x2: "0",
69 y2: "0",
70 x3: "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
71 y3: "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
72 }, {
73
74 name: "P(x1, y1) + P(x2, y2)",
75 x1: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
76 y1: "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
77 x2: "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
78 y2: "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
79 x3: "fd5b88c21d3143518d522cd2796f3d726793c88b3e05636bc829448e053fed69",
80 y3: "21cf4f6a5be5ff6380234c50424a970b1f7e718f5eb58f68198c108d642a137f",
81 }, {
82
83 name: "P(x, y) + P(x, -y) = ∞",
84 x1: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
85 y1: "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
86 x2: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
87 y2: "f48e156428cf0276dc092da5856e182288d7569f97934a56fe44be60f0d359fd",
88 x3: "0",
89 y3: "0",
90 }, {
91
92 name: "P(x, y) + P(x, y) = 2P",
93 x1: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
94 y1: "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
95 x2: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
96 y2: "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
97 x3: "59477d88ae64a104dbb8d31ec4ce2d91b2fe50fa628fb6a064e22582196b365b",
98 y3: "938dc8c0f13d1e75c987cb1a220501bd614b0d3dd9eb5c639847e1240216e3b6",
99 }}
100
101 curve := S256()
102 for _, test := range tests {
103
104 x1, y1 := fromHex(test.x1), fromHex(test.y1)
105 x2, y2 := fromHex(test.x2), fromHex(test.y2)
106 x3, y3 := fromHex(test.x3), fromHex(test.y3)
107
108
109
110 if !isValidAffinePoint(x1, y1) {
111 t.Errorf("%s: first point is not on curve", test.name)
112 continue
113 }
114 if !isValidAffinePoint(x2, y2) {
115 t.Errorf("%s: second point is not on curve", test.name)
116 continue
117 }
118 if !isValidAffinePoint(x3, y3) {
119 t.Errorf("%s: expected point is not on curve", test.name)
120 continue
121 }
122
123
124 rx, ry := curve.Add(x1, y1, x2, y2)
125 if rx.Cmp(x3) != 0 || ry.Cmp(y3) != 0 {
126 t.Errorf("%s: wrong result\ngot: (%x, %x)\nwant: (%x, %x)",
127 test.name, rx, ry, x3, y3)
128 continue
129 }
130 }
131 }
132
133
134
135
136 func TestDoubleAffineAdaptor(t *testing.T) {
137 tests := []struct {
138 name string
139 x1, y1 string
140 x3, y3 string
141 }{{
142
143 name: "2*∞ = ∞ (point at infinity)",
144 x1: "0",
145 y1: "0",
146 x3: "0",
147 y3: "0",
148 }, {
149 name: "random point 1",
150 x1: "e41387ffd8baaeeb43c2faa44e141b19790e8ac1f7ff43d480dc132230536f86",
151 y1: "1b88191d430f559896149c86cbcb703193105e3cf3213c0c3556399836a2b899",
152 x3: "88da47a089d333371bd798c548ef7caae76e737c1980b452d367b3cfe3082c19",
153 y3: "3b6f659b09a362821dfcfefdbfbc2e59b935ba081b6c249eb147b3c2100b1bc1",
154 }, {
155 name: "random point 2",
156 x1: "b3589b5d984f03ef7c80aeae444f919374799edf18d375cab10489a3009cff0c",
157 y1: "c26cf343875b3630e15bccc61202815b5d8f1fd11308934a584a5babe69db36a",
158 x3: "e193860172998751e527bb12563855602a227fc1f612523394da53b746bb2fb1",
159 y3: "2bfcf13d2f5ab8bb5c611fab5ebbed3dc2f057062b39a335224c22f090c04789",
160 }, {
161 name: "random point 3",
162 x1: "2b31a40fbebe3440d43ac28dba23eee71c62762c3fe3dbd88b4ab82dc6a82340",
163 y1: "9ba7deb02f5c010e217607fd49d58db78ec273371ea828b49891ce2fd74959a1",
164 x3: "2c8d5ef0d343b1a1a48aa336078eadda8481cb048d9305dc4fdf7ee5f65973a2",
165 y3: "bb4914ac729e26d3cd8f8dc8f702f3f4bb7e0e9c5ae43335f6e94c2de6c3dc95",
166 }, {
167 name: "random point 4",
168 x1: "61c64b760b51981fab54716d5078ab7dffc93730b1d1823477e27c51f6904c7a",
169 y1: "ef6eb16ea1a36af69d7f66524c75a3a5e84c13be8fbc2e811e0563c5405e49bd",
170 x3: "5f0dcdd2595f5ad83318a0f9da481039e36f135005420393e72dfca985b482f4",
171 y3: "a01c849b0837065c1cb481b0932c441f49d1cab1b4b9f355c35173d93f110ae0",
172 }}
173
174 curve := S256()
175 for _, test := range tests {
176
177 x1, y1 := fromHex(test.x1), fromHex(test.y1)
178 x3, y3 := fromHex(test.x3), fromHex(test.y3)
179
180
181
182 if !isValidAffinePoint(x1, y1) {
183 t.Errorf("%s: first point is not on the curve", test.name)
184 continue
185 }
186 if !isValidAffinePoint(x3, y3) {
187 t.Errorf("%s: expected point is not on the curve", test.name)
188 continue
189 }
190
191
192 rx, ry := curve.Double(x1, y1)
193 if rx.Cmp(x3) != 0 || ry.Cmp(y3) != 0 {
194 t.Errorf("%s: wrong result\ngot: (%x, %x)\nwant: (%x, %x)",
195 test.name, rx, ry, x3, y3)
196 continue
197 }
198 }
199 }
200
201
202
203
204 func TestScalarBaseMultAdaptor(t *testing.T) {
205 tests := []struct {
206 name string
207 k string
208 rx, ry string
209 }{{
210 name: "zero",
211 k: "0000000000000000000000000000000000000000000000000000000000000000",
212 rx: "0000000000000000000000000000000000000000000000000000000000000000",
213 ry: "0000000000000000000000000000000000000000000000000000000000000000",
214 }, {
215 name: "one (aka 1*G = G)",
216 k: "0000000000000000000000000000000000000000000000000000000000000001",
217 rx: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
218 ry: "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
219 }, {
220 name: "group order - 1 (aka -1*G = -G)",
221 k: "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
222 rx: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
223 ry: "b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777",
224 }, {
225 name: "known good point 1",
226 k: "aa5e28d6a97a2479a65527f7290311a3624d4cc0fa1578598ee3c2613bf99522",
227 rx: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
228 ry: "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
229 }, {
230 name: "known good point 2",
231 k: "7e2b897b8cebc6361663ad410835639826d590f393d90a9538881735256dfae3",
232 rx: "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
233 ry: "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
234 }, {
235 name: "known good point 3",
236 k: "6461e6df0fe7dfd05329f41bf771b86578143d4dd1f7866fb4ca7e97c5fa945d",
237 rx: "e8aecc370aedd953483719a116711963ce201ac3eb21d3f3257bb48668c6a72f",
238 ry: "c25caf2f0eba1ddb2f0f3f47866299ef907867b7d27e95b3873bf98397b24ee1",
239 }, {
240 name: "known good point 4",
241 k: "376a3a2cdcd12581efff13ee4ad44c4044b8a0524c42422a7e1e181e4deeccec",
242 rx: "14890e61fcd4b0bd92e5b36c81372ca6fed471ef3aa60a3e415ee4fe987daba1",
243 ry: "297b858d9f752ab42d3bca67ee0eb6dcd1c2b7b0dbe23397e66adc272263f982",
244 }, {
245 name: "known good point 5",
246 k: "1b22644a7be026548810c378d0b2994eefa6d2b9881803cb02ceff865287d1b9",
247 rx: "f73c65ead01c5126f28f442d087689bfa08e12763e0cec1d35b01751fd735ed3",
248 ry: "f449a8376906482a84ed01479bd18882b919c140d638307f0c0934ba12590bde",
249 }}
250
251 curve := S256()
252 for _, test := range tests {
253
254 k := fromHex(test.k)
255 xWant, yWant := fromHex(test.rx), fromHex(test.ry)
256
257
258
259 if !isValidAffinePoint(xWant, yWant) {
260 t.Errorf("%s: expected point is not on curve", test.name)
261 continue
262 }
263
264 rx, ry := curve.ScalarBaseMult(k.Bytes())
265 if rx.Cmp(xWant) != 0 || ry.Cmp(yWant) != 0 {
266 t.Errorf("%s: wrong result:\ngot (%x, %x)\nwant (%x, %x)",
267 test.name, rx, ry, xWant, yWant)
268 }
269 }
270 }
271
272
273
274
275 func TestScalarBaseMultAdaptorRandom(t *testing.T) {
276
277 seed := time.Now().Unix()
278 rng := rand.New(rand.NewSource(seed))
279 defer func(t *testing.T, seed int64) {
280 if t.Failed() {
281 t.Logf("random seed: %d", seed)
282 }
283 }(t, seed)
284
285 s256 := S256()
286 const maxBytes = 40
287 const iterations = 10
288 for numBytes := uint8(1); numBytes < maxBytes; numBytes++ {
289 for i := 0; i < iterations; i++ {
290
291 k := randBytes(t, rng, numBytes)
292
293
294
295 x, y := s256.ScalarBaseMult(k)
296 xWant, yWant := s256.ScalarMult(s256.Gx, s256.Gy, k)
297 if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 {
298 t.Errorf("bad output for %x: got (%x, %x), want (%x, %x)", k,
299 x, y, xWant, yWant)
300 continue
301 }
302 }
303 }
304 }
305
306
307
308
309 func TestScalarMultAdaptor(t *testing.T) {
310 tests := []struct {
311 name string
312 k string
313 x, y string
314 rx, ry string
315 }{{
316 name: "0*P = ∞ (point at infinity)",
317 k: "0",
318 x: "7e660beda020e9cc20391cef85374576853b0f22b8925d5d81c5845bb834c21e",
319 y: "2d114a5edb320cc9806527d1daf1bbb96a8fedc6f9e8ead421eaef2c7208e409",
320 rx: "0",
321 ry: "0",
322 }, {
323 name: "1*P = P",
324 k: "1",
325 x: "c00be8830995d1e44f1420dd3b90d3441fb66f6861c84a35f959c495a3be5440",
326 y: "ecf9665e6eba45720de652a340600c7356efe24d228bfe6ea2043e7791c51bb7",
327 rx: "c00be8830995d1e44f1420dd3b90d3441fb66f6861c84a35f959c495a3be5440",
328 ry: "ecf9665e6eba45720de652a340600c7356efe24d228bfe6ea2043e7791c51bb7",
329 }, {
330 name: "(group order - 1)*P = -P (aka -1*P = -P)",
331 k: "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
332 x: "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
333 y: "cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08",
334 rx: "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
335 ry: "339ea810e73639c329e6c27c9ce4415ff6c1f6976bd173cc2a8c80276f1f2127",
336 }, {
337 name: "(group order - 1)*-P = P (aka -1*-P = -P, with P from prev test)",
338 k: "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
339 x: "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
340 y: "339ea810e73639c329e6c27c9ce4415ff6c1f6976bd173cc2a8c80276f1f2127",
341 rx: "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
342 ry: "cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08",
343 }, {
344 name: "known good point from base mult tests (aka k*G)",
345 k: "aa5e28d6a97a2479a65527f7290311a3624d4cc0fa1578598ee3c2613bf99522",
346 x: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
347 y: "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
348 rx: "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
349 ry: "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
350 }, {
351 name: "known good result 1",
352 k: "7e2b897b8cebc6361663ad410835639826d590f393d90a9538881735256dfae3",
353 x: "1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5",
354 y: "b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396",
355 rx: "6951f3b50aafbc63e21707dd53623b7f42badd633a0567ef1b37f6e42a4237ad",
356 ry: "9c930796a49110122fbfdedc36418af726197ed950b783a2d29058f8c02130de",
357 }, {
358 name: "known good result 2",
359 k: "6461e6df0fe7dfd05329f41bf771b86578143d4dd1f7866fb4ca7e97c5fa945d",
360 x: "659214ac1a1790023f53c4cf55a0a63b9e20c1151efa971215b395a558aa151",
361 y: "b126363aa4243d2759320a356230569a4eea355d9dabd94ed7f4590701e5364d",
362 rx: "4ffad856833396ef753c0bd4ea40319295f107c476793df0adac2caea53b3df4",
363 ry: "586fa6b1e9a3ff7df8a2b9b3698badcf40aa06af5600fefc56dd8ae4db5451c5",
364 }, {
365 name: "known good result 3",
366 k: "376a3a2cdcd12581efff13ee4ad44c4044b8a0524c42422a7e1e181e4deeccec",
367 x: "3f0e80e574456d8f8fa64e044b2eb72ea22eb53fe1efe3a443933aca7f8cb0e3",
368 y: "cb66d7d7296cbc91e90b9c08485d01b39501253aa65b53a4cb0289e2ea5f404f",
369 rx: "35ae6480b18e48070709d9276ed97a50c6ee1fc05ac44386c85826533233d28f",
370 ry: "f88abee3efabd95e80ce8c664bbc3d4d12b24e1a0f4d2b98ba6542789c6715fd",
371 }, {
372 name: "known good result 4",
373 k: "1b22644a7be026548810c378d0b2994eefa6d2b9881803cb02ceff865287d1b9",
374 x: "d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e",
375 y: "581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58",
376 rx: "cca7f9a4b0d379c31c438050e163a8945f2f910498bd3b545be20ed862bd6cd9",
377 ry: "cfc7bbf37bef62da6e5753ed419168fa1376a3fe949c139a8dd0f5303f4ae947",
378 }, {
379 name: "known good result 5",
380 k: "7f5b2cb4b43840c75e4afad83d792e1965d8c21c1109505f45c7d46df422d73e",
381 x: "bce74de6d5f98dc027740c2bbff05b6aafe5fd8d103f827e48894a2bd3460117",
382 y: "5bea1fa17a41b115525a3e7dbf0d8d5a4f7ce5c6fc73a6f4f216512417c9f6b4",
383 rx: "3d96b9290fe6c4f2d62fe2175f4333907d0c3637fada1010b45c7d80690e16de",
384 ry: "d59c0e8192d7fbd4846172d6479630b751cd03d0d9be0dca2759c6212b70575d",
385 }, {
386
387 name: "early implementation regression point",
388 k: "a2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba219b51835b55cc30ebfe2f6599bc56f58",
389 x: "000000000000000000000000000000000000000000000000000000000000002c",
390 y: "420e7a99bba18a9d3952597510fd2b6728cfeafc21a4e73951091d4d8ddbe94e",
391 rx: "a2112dcdfbcd10ae1133a358de7b82db68e0a3eb4b492cc8268d1e7118c98788",
392 ry: "27fc7463b7bb3c5f98ecf2c84a6272bb1681ed553d92c69f2dfe25a9f9fd3836",
393 }}
394
395 curve := S256()
396 for _, test := range tests {
397
398 k := fromHex(test.k)
399 x, y := fromHex(test.x), fromHex(test.y)
400 xWant, yWant := fromHex(test.rx), fromHex(test.ry)
401
402
403
404 if !isValidAffinePoint(x, y) {
405 t.Errorf("%s: point is not on curve", test.name)
406 continue
407 }
408 if !isValidAffinePoint(xWant, yWant) {
409 t.Errorf("%s: expected point is not on curve", test.name)
410 continue
411 }
412
413
414
415 rx, ry := curve.ScalarMult(x, y, k.Bytes())
416 if rx.Cmp(xWant) != 0 || ry.Cmp(yWant) != 0 {
417 t.Errorf("%s: wrong result\ngot: (%x, %x)\nwant: (%x, %x)",
418 test.name, rx, ry, xWant, yWant)
419 }
420 }
421 }
422
View as plain text