pubkey_test.go raw
1 // Copyright (c) 2013-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package btcec
6
7 import (
8 "testing"
9
10 "next.orly.dev/pkg/nostr/utils"
11
12 "github.com/davecgh/go-spew/spew"
13 )
14
15 type pubKeyTest struct {
16 name string
17 key []byte
18 format byte
19 isValid bool
20 }
21
22 var pubKeyTests = []pubKeyTest{
23 // pubkey from bitcoin blockchain tx
24 // 0437cd7f8525ceed2324359c2d0ba26006d92d85
25 {
26 name: "uncompressed ok",
27 key: []byte{
28 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
29 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
30 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
31 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
32 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
33 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
34 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
35 0xb4, 0x12, 0xa3,
36 },
37 isValid: true,
38 format: pubkeyUncompressed,
39 },
40 {
41 name: "uncompressed x changed",
42 key: []byte{
43 0x04, 0x15, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
44 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
45 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
46 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
47 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
48 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
49 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
50 0xb4, 0x12, 0xa3,
51 },
52 isValid: false,
53 },
54 {
55 name: "uncompressed y changed",
56 key: []byte{
57 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
58 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
59 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
60 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
61 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
62 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
63 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
64 0xb4, 0x12, 0xa4,
65 },
66 isValid: false,
67 },
68 {
69 name: "uncompressed claims compressed",
70 key: []byte{
71 0x03, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
72 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
73 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
74 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
75 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
76 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
77 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
78 0xb4, 0x12, 0xa3,
79 },
80 isValid: false,
81 },
82 {
83 name: "uncompressed as hybrid ok",
84 key: []byte{
85 0x07, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
86 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
87 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
88 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
89 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
90 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
91 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
92 0xb4, 0x12, 0xa3,
93 },
94 isValid: true,
95 format: pubkeyHybrid,
96 },
97 {
98 name: "uncompressed as hybrid wrong",
99 key: []byte{
100 0x06, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
101 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
102 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
103 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
104 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
105 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
106 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
107 0xb4, 0x12, 0xa3,
108 },
109 isValid: false,
110 },
111 // from tx 0b09c51c51ff762f00fb26217269d2a18e77a4fa87d69b3c363ab4df16543f20
112 {
113 name: "compressed ok (ybit = 0)",
114 key: []byte{
115 0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
116 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
117 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
118 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
119 },
120 isValid: true,
121 format: pubkeyCompressed,
122 },
123 // from tx fdeb8e72524e8dab0da507ddbaf5f88fe4a933eb10a66bc4745bb0aa11ea393c
124 {
125 name: "compressed ok (ybit = 1)",
126 key: []byte{
127 0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33,
128 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34,
129 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4,
130 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e,
131 },
132 isValid: true,
133 format: pubkeyCompressed,
134 },
135 {
136 name: "compressed claims uncompressed (ybit = 0)",
137 key: []byte{
138 0x04, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
139 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
140 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
141 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
142 },
143 isValid: false,
144 },
145 {
146 name: "compressed claims uncompressed (ybit = 1)",
147 key: []byte{
148 0x05, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33,
149 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34,
150 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4,
151 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e,
152 },
153 isValid: false,
154 },
155 {
156 name: "wrong length)",
157 key: []byte{0x05},
158 isValid: false,
159 },
160 {
161 name: "X == P",
162 key: []byte{
163 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
164 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
165 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
166 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, 0xb2, 0xe0,
167 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
168 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
169 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
170 0xb4, 0x12, 0xa3,
171 },
172 isValid: false,
173 },
174 {
175 name: "X > P",
176 key: []byte{
177 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
178 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
179 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
180 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFD, 0x2F, 0xb2, 0xe0,
181 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
182 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
183 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
184 0xb4, 0x12, 0xa3,
185 },
186 isValid: false,
187 },
188 {
189 name: "Y == P",
190 key: []byte{
191 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
192 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
193 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
194 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xFF, 0xFF,
195 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
196 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
197 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
198 0xFF, 0xFC, 0x2F,
199 },
200 isValid: false,
201 },
202 {
203 name: "Y > P",
204 key: []byte{
205 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
206 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
207 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
208 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xFF, 0xFF,
209 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
210 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
211 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
212 0xFF, 0xFD, 0x2F,
213 },
214 isValid: false,
215 },
216 {
217 name: "hybrid",
218 key: []byte{
219 0x06, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb,
220 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
221 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59,
222 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a,
223 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb,
224 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48,
225 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb,
226 0x10, 0xd4, 0xb8,
227 },
228 format: pubkeyHybrid,
229 isValid: true,
230 },
231 }
232
233 func TestPubKeys(t *testing.T) {
234 for _, test := range pubKeyTests {
235 pk, err := ParsePubKey(test.key)
236 if err != nil {
237 if test.isValid {
238 t.Errorf(
239 "%s pubkey failed when shouldn't %v",
240 test.name, err,
241 )
242 }
243 continue
244 }
245 if !test.isValid {
246 t.Errorf(
247 "%s counted as valid when it should fail",
248 test.name,
249 )
250 continue
251 }
252 var pkStr []byte
253 switch test.format {
254 case pubkeyUncompressed:
255 pkStr = pk.SerializeUncompressed()
256 case pubkeyCompressed:
257 pkStr = pk.SerializeCompressed()
258 case pubkeyHybrid:
259 pkStr = test.key
260 }
261 if !utils.FastEqual(test.key, pkStr) {
262 t.Errorf(
263 "%s pubkey: serialized keys do not match.",
264 test.name,
265 )
266 spew.Dump(test.key)
267 spew.Dump(pkStr)
268 }
269 }
270 }
271
272 func TestPublicKeyIsEqual(t *testing.T) {
273 pubKey1, err := ParsePubKey(
274 []byte{
275 0x03, 0x26, 0x89, 0xc7, 0xc2, 0xda, 0xb1, 0x33,
276 0x09, 0xfb, 0x14, 0x3e, 0x0e, 0x8f, 0xe3, 0x96, 0x34,
277 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4,
278 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e,
279 },
280 )
281 if err != nil {
282 t.Fatalf("failed to parse raw bytes for pubKey1: %v", err)
283 }
284 pubKey2, err := ParsePubKey(
285 []byte{
286 0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
287 0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
288 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
289 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
290 },
291 )
292 if err != nil {
293 t.Fatalf("failed to parse raw bytes for pubKey2: %v", err)
294 }
295 if !pubKey1.IsEqual(pubKey1) {
296 t.Fatalf(
297 "value of IsEqual is incorrect, %v is "+
298 "equal to %v", pubKey1, pubKey1,
299 )
300 }
301 if pubKey1.IsEqual(pubKey2) {
302 t.Fatalf(
303 "value of IsEqual is incorrect, %v is not "+
304 "equal to %v", pubKey1, pubKey2,
305 )
306 }
307 }
308
309 func TestIsCompressed(t *testing.T) {
310 for _, test := range pubKeyTests {
311 isCompressed := IsCompressedPubKey(test.key)
312 wantCompressed := (test.format == pubkeyCompressed)
313 if isCompressed != wantCompressed {
314 t.Fatalf(
315 "%s (%x) pubkey: unexpected compressed result, "+
316 "got %v, want %v", test.name, test.key,
317 isCompressed, wantCompressed,
318 )
319 }
320 }
321 }
322