pubkey_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 "errors"
10 "testing"
11
12 "next.orly.dev/pkg/nostr/utils"
13 )
14
15 // TestParsePubKey ensures that public keys are properly parsed according
16 // to the spec including both the positive and negative cases.
17 func TestParsePubKey(t *testing.T) {
18 tests := []struct {
19 name string // test description
20 key string // hex encoded public key
21 err error // expected error
22 wantX string // expected x coordinate
23 wantY string // expected y coordinate
24 }{
25 {
26 name: "uncompressed ok",
27 key: "04" +
28 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
29 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
30 err: nil,
31 wantX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
32 wantY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
33 }, {
34 name: "uncompressed x changed (not on curve)",
35 key: "04" +
36 "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
37 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
38 err: ErrPubKeyNotOnCurve,
39 }, {
40 name: "uncompressed y changed (not on curve)",
41 key: "04" +
42 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
43 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a4",
44 err: ErrPubKeyNotOnCurve,
45 }, {
46 name: "uncompressed claims compressed",
47 key: "03" +
48 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
49 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
50 err: ErrPubKeyInvalidFormat,
51 }, {
52 name: "uncompressed as hybrid ok (ybit = 0)",
53 key: "06" +
54 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
55 "4d1f1522047b33068bbb9b07d1e9f40564749b062b3fc0666479bc08a94be98c",
56 err: nil,
57 wantX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
58 wantY: "4d1f1522047b33068bbb9b07d1e9f40564749b062b3fc0666479bc08a94be98c",
59 }, {
60 name: "uncompressed as hybrid ok (ybit = 1)",
61 key: "07" +
62 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
63 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
64 err: nil,
65 wantX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
66 wantY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
67 }, {
68 name: "uncompressed as hybrid wrong oddness",
69 key: "06" +
70 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
71 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
72 err: ErrPubKeyMismatchedOddness,
73 }, {
74 name: "compressed ok (ybit = 0)",
75 key: "02" +
76 "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d",
77 err: nil,
78 wantX: "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d",
79 wantY: "0890ff84d7999d878a57bee170e19ef4b4803b4bdede64503a6ac352b03c8032",
80 }, {
81 name: "compressed ok (ybit = 1)",
82 key: "03" +
83 "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e",
84 err: nil,
85 wantX: "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e",
86 wantY: "499dd7852849a38aa23ed9f306f07794063fe7904e0f347bc209fdddaf37691f",
87 }, {
88 name: "compressed claims uncompressed (ybit = 0)",
89 key: "04" +
90 "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d",
91 err: ErrPubKeyInvalidFormat,
92 }, {
93 name: "compressed claims uncompressed (ybit = 1)",
94 key: "04" +
95 "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e",
96 err: ErrPubKeyInvalidFormat,
97 }, {
98 name: "compressed claims hybrid (ybit = 0)",
99 key: "06" +
100 "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d",
101 err: ErrPubKeyInvalidFormat,
102 }, {
103 name: "compressed claims hybrid (ybit = 1)",
104 key: "07" +
105 "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e",
106 err: ErrPubKeyInvalidFormat,
107 }, {
108 name: "compressed with invalid x coord (ybit = 0)",
109 key: "03" +
110 "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4c",
111 err: ErrPubKeyNotOnCurve,
112 }, {
113 name: "compressed with invalid x coord (ybit = 1)",
114 key: "03" +
115 "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448d",
116 err: ErrPubKeyNotOnCurve,
117 }, {
118 name: "empty",
119 key: "",
120 err: ErrPubKeyInvalidLen,
121 }, {
122 name: "wrong length",
123 key: "05",
124 err: ErrPubKeyInvalidLen,
125 }, {
126 name: "uncompressed x == p",
127 key: "04" +
128 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" +
129 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
130 err: ErrPubKeyXTooBig,
131 }, {
132 // The y coordinate produces a valid point for x == 1 (mod p), but it
133 // should fail to parse instead of wrapping around.
134 name: "uncompressed x > p (p + 1 -- aka 1)",
135 key: "04" +
136 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30" +
137 "bde70df51939b94c9c24979fa7dd04ebd9b3572da7802290438af2a681895441",
138 err: ErrPubKeyXTooBig,
139 }, {
140 name: "uncompressed y == p",
141 key: "04" +
142 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
143 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
144 err: ErrPubKeyYTooBig,
145 }, {
146 // The x coordinate produces a valid point for y == 1 (mod p), but it
147 // should fail to parse instead of wrapping around.
148 name: "uncompressed y > p (p + 1 -- aka 1)",
149 key: "04" +
150 "1fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff507" +
151 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
152 err: ErrPubKeyYTooBig,
153 }, {
154 name: "compressed x == p (ybit = 0)",
155 key: "02" +
156 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
157 err: ErrPubKeyXTooBig,
158 }, {
159 name: "compressed x == p (ybit = 1)",
160 key: "03" +
161 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
162 err: ErrPubKeyXTooBig,
163 }, {
164 // This would be valid for x == 2 (mod p), but it should fail to parse
165 // instead of wrapping around.
166 name: "compressed x > p (p + 2 -- aka 2) (ybit = 0)",
167 key: "02" +
168 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc31",
169 err: ErrPubKeyXTooBig,
170 }, {
171 // This would be valid for x == 1 (mod p), but it should fail to parse
172 // instead of wrapping around.
173 name: "compressed x > p (p + 1 -- aka 1) (ybit = 1)",
174 key: "03" +
175 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
176 err: ErrPubKeyXTooBig,
177 }, {
178 name: "hybrid x == p (ybit = 1)",
179 key: "07" +
180 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" +
181 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
182 err: ErrPubKeyXTooBig,
183 }, {
184 // The y coordinate produces a valid point for x == 1 (mod p), but it
185 // should fail to parse instead of wrapping around.
186 name: "hybrid x > p (p + 1 -- aka 1) (ybit = 0)",
187 key: "06" +
188 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30" +
189 "bde70df51939b94c9c24979fa7dd04ebd9b3572da7802290438af2a681895441",
190 err: ErrPubKeyXTooBig,
191 }, {
192 name: "hybrid y == p (ybit = 0 when mod p)",
193 key: "06" +
194 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
195 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
196 err: ErrPubKeyYTooBig,
197 }, {
198 // The x coordinate produces a valid point for y == 1 (mod p), but it
199 // should fail to parse instead of wrapping around.
200 name: "hybrid y > p (p + 1 -- aka 1) (ybit = 1 when mod p)",
201 key: "07" +
202 "1fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff507" +
203 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
204 err: ErrPubKeyYTooBig,
205 },
206 }
207 for _, test := range tests {
208 pubKeyBytes := hexToBytes(test.key)
209 pubKey, err := ParsePubKey(pubKeyBytes)
210 if !errors.Is(err, test.err) {
211 t.Errorf(
212 "%s mismatched e -- got %v, want %v", test.name, err,
213 test.err,
214 )
215 continue
216 }
217 if err != nil {
218 continue
219 }
220 // Ensure the x and y coordinates match the expected values upon
221 // successful parse.
222 wantX, wantY := hexToFieldVal(test.wantX), hexToFieldVal(test.wantY)
223 if !pubKey.x.Equals(wantX) {
224 t.Errorf(
225 "%s: mismatched x coordinate -- got %v, want %v",
226 test.name, pubKey.x, wantX,
227 )
228 continue
229 }
230 if !pubKey.y.Equals(wantY) {
231 t.Errorf(
232 "%s: mismatched y coordinate -- got %v, want %v",
233 test.name, pubKey.y, wantY,
234 )
235 continue
236 }
237 }
238 }
239
240 // TestPubKeySerialize ensures that serializing public keys works as expected
241 // for both the compressed and uncompressed cases.
242 func TestPubKeySerialize(t *testing.T) {
243 tests := []struct {
244 name string // test description
245 pubX string // hex encoded x coordinate for pubkey to serialize
246 pubY string // hex encoded y coordinate for pubkey to serialize
247 compress bool // whether to serialize compressed or uncompressed
248 expected string // hex encoded expected pubkey serialization
249 }{
250 {
251 name: "uncompressed (ybit = 0)",
252 pubX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
253 pubY: "4d1f1522047b33068bbb9b07d1e9f40564749b062b3fc0666479bc08a94be98c",
254 compress: false,
255 expected: "04" +
256 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
257 "4d1f1522047b33068bbb9b07d1e9f40564749b062b3fc0666479bc08a94be98c",
258 }, {
259 name: "uncompressed (ybit = 1)",
260 pubX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
261 pubY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
262 compress: false,
263 expected: "04" +
264 "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
265 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
266 }, {
267 // It's invalid to parse pubkeys that are not on the curve, however it
268 // is possible to manually create them and they should serialize
269 // correctly.
270 name: "uncompressed not on the curve due to x coord",
271 pubX: "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
272 pubY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
273 compress: false,
274 expected: "04" +
275 "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
276 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
277 }, {
278 // It's invalid to parse pubkeys that are not on the curve, however it
279 // is possible to manually create them and they should serialize
280 // correctly.
281 name: "uncompressed not on the curve due to y coord",
282 pubX: "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
283 pubY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a4",
284 compress: false,
285 expected: "04" +
286 "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" +
287 "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a4",
288 }, {
289 name: "compressed (ybit = 0)",
290 pubX: "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d",
291 pubY: "0890ff84d7999d878a57bee170e19ef4b4803b4bdede64503a6ac352b03c8032",
292 compress: true,
293 expected: "02" +
294 "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d",
295 }, {
296 name: "compressed (ybit = 1)",
297 pubX: "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e",
298 pubY: "499dd7852849a38aa23ed9f306f07794063fe7904e0f347bc209fdddaf37691f",
299 compress: true,
300 expected: "03" +
301 "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e",
302 }, {
303 // It's invalid to parse pubkeys that are not on the curve, however it
304 // is possible to manually create them and they should serialize
305 // correctly.
306 name: "compressed not on curve (ybit = 0)",
307 pubX: "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4c",
308 pubY: "0890ff84d7999d878a57bee170e19ef4b4803b4bdede64503a6ac352b03c8032",
309 compress: true,
310 expected: "02" +
311 "ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4c",
312 }, {
313 // It's invalid to parse pubkeys that are not on the curve, however it
314 // is possible to manually create them and they should serialize
315 // correctly.
316 name: "compressed not on curve (ybit = 1)",
317 pubX: "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448d",
318 pubY: "499dd7852849a38aa23ed9f306f07794063fe7904e0f347bc209fdddaf37691f",
319 compress: true,
320 expected: "03" +
321 "2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448d",
322 },
323 }
324 for _, test := range tests {
325 // Parse the test data.
326 x, y := hexToFieldVal(test.pubX), hexToFieldVal(test.pubY)
327 pubKey := NewPublicKey(x, y)
328 // Serialize with the correct method and ensure the result matches the
329 // expected value.
330 var serialized []byte
331 if test.compress {
332 serialized = pubKey.SerializeCompressed()
333 } else {
334 serialized = pubKey.SerializeUncompressed()
335 }
336 expected := hexToBytes(test.expected)
337 if !utils.FastEqual(serialized, expected) {
338 t.Errorf(
339 "%s: mismatched serialized public key -- got %x, want %x",
340 test.name, serialized, expected,
341 )
342 continue
343 }
344 }
345 }
346
347 // TestPublicKeyIsEqual ensures that equality testing between two public keys
348 // works as expected.
349 func TestPublicKeyIsEqual(t *testing.T) {
350 pubKey1 := &PublicKey{
351 x: *hexToFieldVal("2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e"),
352 y: *hexToFieldVal("499dd7852849a38aa23ed9f306f07794063fe7904e0f347bc209fdddaf37691f"),
353 }
354 pubKey1Copy := &PublicKey{
355 x: *hexToFieldVal("2689c7c2dab13309fb143e0e8fe396342521887e976690b6b47f5b2a4b7d448e"),
356 y: *hexToFieldVal("499dd7852849a38aa23ed9f306f07794063fe7904e0f347bc209fdddaf37691f"),
357 }
358 pubKey2 := &PublicKey{
359 x: *hexToFieldVal("ce0b14fb842b1ba549fdd675c98075f12e9c510f8ef52bd021a9a1f4809d3b4d"),
360 y: *hexToFieldVal("0890ff84d7999d878a57bee170e19ef4b4803b4bdede64503a6ac352b03c8032"),
361 }
362
363 if !pubKey1.IsEqual(pubKey1) {
364 t.Fatalf(
365 "bad self public key equality check: (%v, %v)", pubKey1.x,
366 pubKey1.y,
367 )
368 }
369 if !pubKey1.IsEqual(pubKey1Copy) {
370 t.Fatalf(
371 "bad public key equality check: (%v, %v) == (%v, %v)",
372 pubKey1.x, pubKey1.y, pubKey1Copy.x, pubKey1Copy.y,
373 )
374 }
375
376 if pubKey1.IsEqual(pubKey2) {
377 t.Fatalf(
378 "bad public key equality check: (%v, %v) != (%v, %v)",
379 pubKey1.x, pubKey1.y, pubKey2.x, pubKey2.y,
380 )
381 }
382 }
383
384 // TestPublicKeyAsJacobian ensures converting a public key to a jacobian point
385 // with a Z coordinate of 1 works as expected.
386 func TestPublicKeyAsJacobian(t *testing.T) {
387 tests := []struct {
388 name string // test description
389 pubKey string // hex encoded serialized compressed pubkey
390 wantX string // hex encoded expected X coordinate
391 wantY string // hex encoded expected Y coordinate
392 }{
393 {
394 name: "public key for secret key 0x01",
395 pubKey: "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
396 wantX: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
397 wantY: "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
398 }, {
399 name: "public for secret key 0x03",
400 pubKey: "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
401 wantX: "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
402 wantY: "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672",
403 }, {
404 name: "public for secret key 0x06",
405 pubKey: "03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556",
406 wantX: "fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556",
407 wantY: "ae12777aacfbb620f3be96017f45c560de80f0f6518fe4a03c870c36b075f297",
408 },
409 }
410 for _, test := range tests {
411 // Parse the test data.
412 pubKeyBytes := hexToBytes(test.pubKey)
413 wantX := hexToFieldVal(test.wantX)
414 wantY := hexToFieldVal(test.wantY)
415 pubKey, err := ParsePubKey(pubKeyBytes)
416 if err != nil {
417 t.Errorf("%s: failed to parse public key: %v", test.name, err)
418 continue
419 }
420 // Convert the public key to a jacobian point and ensure the coordinates
421 // match the expected values.
422 var point JacobianPoint
423 pubKey.AsJacobian(&point)
424 if !point.Z.IsOne() {
425 t.Errorf(
426 "%s: invalid Z coordinate -- got %v, want 1", test.name,
427 point.Z,
428 )
429 continue
430 }
431 if !point.X.Equals(wantX) {
432 t.Errorf(
433 "%s: invalid X coordinate - got %v, want %v", test.name,
434 point.X, wantX,
435 )
436 continue
437 }
438 if !point.Y.Equals(wantY) {
439 t.Errorf(
440 "%s: invalid Y coordinate - got %v, want %v", test.name,
441 point.Y, wantY,
442 )
443 continue
444 }
445 }
446 }
447
448 // TestPublicKeyIsOnCurve ensures testing if a public key is on the curve works
449 // as expected.
450 func TestPublicKeyIsOnCurve(t *testing.T) {
451 tests := []struct {
452 name string // test description
453 pubX string // hex encoded x coordinate for pubkey to serialize
454 pubY string // hex encoded y coordinate for pubkey to serialize
455 want bool // expected result
456 }{
457 {
458 name: "valid with even y",
459 pubX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
460 pubY: "4d1f1522047b33068bbb9b07d1e9f40564749b062b3fc0666479bc08a94be98c",
461 want: true,
462 }, {
463 name: "valid with odd y",
464 pubX: "11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
465 pubY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
466 want: true,
467 }, {
468 name: "invalid due to x coord",
469 pubX: "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
470 pubY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3",
471 want: false,
472 }, {
473 name: "invalid due to y coord",
474 pubX: "15db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c",
475 pubY: "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a4",
476 want: false,
477 },
478 }
479 for _, test := range tests {
480 // Parse the test data.
481 x, y := hexToFieldVal(test.pubX), hexToFieldVal(test.pubY)
482 pubKey := NewPublicKey(x, y)
483
484 result := pubKey.IsOnCurve()
485 if result != test.want {
486 t.Errorf(
487 "%s: mismatched is on curve result -- got %v, want %v",
488 test.name, result, test.want,
489 )
490 continue
491 }
492 }
493 }
494