pubkey_test.go raw
1 package p256k1
2
3 import (
4 "crypto/rand"
5 "testing"
6 )
7
8 func TestECPubkeyCreate(t *testing.T) {
9 // Generate a random private key
10 seckey := make([]byte, 32)
11 if _, err := rand.Read(seckey); err != nil {
12 t.Fatal(err)
13 }
14
15 // Ensure it's a valid private key (not zero, not >= order)
16 var scalar Scalar
17 for !scalar.setB32Seckey(seckey) {
18 if _, err := rand.Read(seckey); err != nil {
19 t.Fatal(err)
20 }
21 }
22
23 // Create public key
24 var pubkey PublicKey
25 err := ECPubkeyCreate(&pubkey, seckey)
26 if err != nil {
27 t.Errorf("ECPubkeyCreate failed: %v", err)
28 }
29
30 // Verify the public key is valid by parsing it
31 var parsed PublicKey
32 var serialized [65]byte
33 length := ECPubkeySerialize(serialized[:], &pubkey, ECUncompressed)
34 if length != 65 {
35 t.Error("uncompressed serialization should be 65 bytes")
36 }
37
38 err = ECPubkeyParse(&parsed, serialized[:length])
39 if err != nil {
40 t.Errorf("failed to parse created public key: %v", err)
41 }
42
43 // Compare original and parsed
44 if ECPubkeyCmp(&pubkey, &parsed) != 0 {
45 t.Error("parsed public key should equal original")
46 }
47 }
48
49 func TestECPubkeyParse(t *testing.T) {
50 // Test with generator point (known valid point)
51 // Generator X: 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
52 // Generator Y: 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
53
54 // Uncompressed format
55 uncompressed := []byte{
56 0x04,
57 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
58 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
59 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8,
60 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8,
61 }
62
63 var pubkey PublicKey
64 err := ECPubkeyParse(&pubkey, uncompressed)
65 if err != nil {
66 t.Errorf("failed to parse uncompressed generator: %v", err)
67 }
68
69 // Compressed format (even Y)
70 compressed := []byte{
71 0x02,
72 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
73 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
74 }
75
76 var pubkey2 PublicKey
77 err = ECPubkeyParse(&pubkey2, compressed)
78 if err != nil {
79 t.Errorf("failed to parse compressed generator: %v", err)
80 }
81
82 // Both should be equal
83 if ECPubkeyCmp(&pubkey, &pubkey2) != 0 {
84 t.Error("compressed and uncompressed generator should be equal")
85 }
86
87 // Test invalid inputs
88 invalidInputs := [][]byte{
89 {}, // empty
90 {0x05}, // invalid prefix
91 {0x04, 0x00}, // too short
92 make([]byte, 66), // too long
93 {0x02}, // compressed too short
94 make([]byte, 34), // compressed too long
95 }
96
97 for i, invalid := range invalidInputs {
98 var dummy PublicKey
99 err := ECPubkeyParse(&dummy, invalid)
100 if err == nil {
101 t.Errorf("invalid input %d should have failed", i)
102 }
103 }
104 }
105
106 func TestECPubkeySerialize(t *testing.T) {
107 // Create a public key from a known private key
108 seckey := []byte{
109 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
110 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
111 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
112 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
113 }
114
115 var pubkey PublicKey
116 err := ECPubkeyCreate(&pubkey, seckey)
117 if err != nil {
118 t.Fatalf("failed to create public key: %v", err)
119 }
120
121 // Test compressed serialization
122 var compressed [33]byte
123 compressedLength := ECPubkeySerialize(compressed[:], &pubkey, ECCompressed)
124 if compressedLength != 33 {
125 t.Errorf("compressed serialization should return 33 bytes, got %d", compressedLength)
126 }
127 if compressed[0] != 0x02 && compressed[0] != 0x03 {
128 t.Errorf("compressed format should start with 0x02 or 0x03, got 0x%02x", compressed[0])
129 }
130
131 // Test uncompressed serialization
132 var uncompressed [65]byte
133 uncompressedLength := ECPubkeySerialize(uncompressed[:], &pubkey, ECUncompressed)
134 if uncompressedLength != 65 {
135 t.Errorf("uncompressed serialization should return 65 bytes, got %d", uncompressedLength)
136 }
137 if uncompressed[0] != 0x04 {
138 t.Errorf("uncompressed format should start with 0x04, got 0x%02x", uncompressed[0])
139 }
140
141 // Test round-trip
142 var parsed1, parsed2 PublicKey
143 err = ECPubkeyParse(&parsed1, compressed[:compressedLength])
144 if err != nil {
145 t.Errorf("failed to parse compressed: %v", err)
146 }
147
148 err = ECPubkeyParse(&parsed2, uncompressed[:uncompressedLength])
149 if err != nil {
150 t.Errorf("failed to parse uncompressed: %v", err)
151 }
152
153 if ECPubkeyCmp(&parsed1, &parsed2) != 0 {
154 t.Error("round-trip should preserve public key")
155 }
156
157 // Test buffer too small
158 var small [32]byte
159 smallLength := ECPubkeySerialize(small[:], &pubkey, ECCompressed)
160 if smallLength != 0 {
161 t.Error("serialization with small buffer should return 0")
162 }
163
164 // Test invalid flags
165 invalidLength := ECPubkeySerialize(compressed[:], &pubkey, 0xFF)
166 if invalidLength != 0 {
167 t.Error("serialization with invalid flags should return 0")
168 }
169 }
170
171 func TestECPubkeyCmp(t *testing.T) {
172 // Create two different public keys
173 seckey1 := []byte{
174 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
175 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
176 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
177 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
178 }
179 seckey2 := []byte{
180 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
181 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
182 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
183 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
184 }
185
186 var pubkey1, pubkey2, pubkey3 PublicKey
187
188 err := ECPubkeyCreate(&pubkey1, seckey1)
189 if err != nil {
190 t.Fatalf("failed to create pubkey1: %v", err)
191 }
192
193 err = ECPubkeyCreate(&pubkey2, seckey2)
194 if err != nil {
195 t.Fatalf("failed to create pubkey2: %v", err)
196 }
197
198 err = ECPubkeyCreate(&pubkey3, seckey1) // Same as pubkey1
199 if err != nil {
200 t.Fatalf("failed to create pubkey3: %v", err)
201 }
202
203 // Test equality
204 if ECPubkeyCmp(&pubkey1, &pubkey3) != 0 {
205 t.Error("identical public keys should compare equal")
206 }
207
208 // Test inequality
209 cmp := ECPubkeyCmp(&pubkey1, &pubkey2)
210 if cmp == 0 {
211 t.Error("different public keys should not compare equal")
212 }
213
214 // Test symmetry
215 cmp2 := ECPubkeyCmp(&pubkey2, &pubkey1)
216 if (cmp > 0 && cmp2 >= 0) || (cmp < 0 && cmp2 <= 0) {
217 t.Error("comparison should be antisymmetric")
218 }
219 }
220
221 func BenchmarkECPubkeyCreate(b *testing.B) {
222 seckey := []byte{
223 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
224 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
225 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
226 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
227 }
228
229 b.ResetTimer()
230 for i := 0; i < b.N; i++ {
231 var pubkey PublicKey
232 ECPubkeyCreate(&pubkey, seckey)
233 }
234 }
235
236 func BenchmarkECPubkeySerializeCompressed(b *testing.B) {
237 seckey := []byte{
238 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
239 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
240 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
241 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
242 }
243
244 var pubkey PublicKey
245 ECPubkeyCreate(&pubkey, seckey)
246 var output [33]byte
247
248 b.ResetTimer()
249 for i := 0; i < b.N; i++ {
250 ECPubkeySerialize(output[:], &pubkey, ECCompressed)
251 }
252 }
253
254 func BenchmarkECPubkeyParse(b *testing.B) {
255 // Use generator point in compressed format
256 compressed := []byte{
257 0x02,
258 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07,
259 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,
260 }
261
262 b.ResetTimer()
263 for i := 0; i < b.N; i++ {
264 var pubkey PublicKey
265 ECPubkeyParse(&pubkey, compressed)
266 }
267 }
268