secp_test.go raw
1 package secp
2
3 import (
4 "crypto/rand"
5 "crypto/sha256"
6 "testing"
7 )
8
9 func TestContextCreation(t *testing.T) {
10 ctx, err := NewContext(ContextSign | ContextVerify)
11 if err != nil {
12 t.Fatalf("Failed to create context: %v", err)
13 }
14 defer ctx.Destroy()
15
16 if ctx.ctx == 0 {
17 t.Fatal("Context handle is null")
18 }
19 }
20
21 func TestPublicKeyGeneration(t *testing.T) {
22 ctx, err := NewContext(ContextSign)
23 if err != nil {
24 t.Fatalf("Failed to create context: %v", err)
25 }
26 defer ctx.Destroy()
27
28 privKey := make([]byte, 32)
29 if _, err := rand.Read(privKey); err != nil {
30 t.Fatalf("Failed to generate random key: %v", err)
31 }
32
33 pubKey, err := ctx.CreatePublicKey(privKey)
34 if err != nil {
35 t.Fatalf("Failed to create public key: %v", err)
36 }
37
38 if len(pubKey) != PublicKeySize {
39 t.Fatalf("Public key size incorrect: got %d, want %d", len(pubKey), PublicKeySize)
40 }
41 }
42
43 func TestPublicKeySerialization(t *testing.T) {
44 ctx, err := NewContext(ContextSign)
45 if err != nil {
46 t.Fatalf("Failed to create context: %v", err)
47 }
48 defer ctx.Destroy()
49
50 privKey := make([]byte, 32)
51 if _, err := rand.Read(privKey); err != nil {
52 t.Fatalf("Failed to generate random key: %v", err)
53 }
54
55 pubKey, err := ctx.CreatePublicKey(privKey)
56 if err != nil {
57 t.Fatalf("Failed to create public key: %v", err)
58 }
59
60 // Test compressed
61 compressed, err := ctx.SerializePublicKey(pubKey, true)
62 if err != nil {
63 t.Fatalf("Failed to serialize compressed: %v", err)
64 }
65 if len(compressed) != CompressedPublicKeySize {
66 t.Fatalf("Compressed size incorrect: got %d, want %d", len(compressed), CompressedPublicKeySize)
67 }
68
69 // Test uncompressed
70 uncompressed, err := ctx.SerializePublicKey(pubKey, false)
71 if err != nil {
72 t.Fatalf("Failed to serialize uncompressed: %v", err)
73 }
74 if len(uncompressed) != UncompressedPublicKeySize {
75 t.Fatalf("Uncompressed size incorrect: got %d, want %d", len(uncompressed), UncompressedPublicKeySize)
76 }
77
78 // Parse back compressed
79 parsed, err := ctx.ParsePublicKey(compressed)
80 if err != nil {
81 t.Fatalf("Failed to parse compressed: %v", err)
82 }
83 if len(parsed) != PublicKeySize {
84 t.Fatalf("Parsed size incorrect: got %d, want %d", len(parsed), PublicKeySize)
85 }
86 }
87
88 func TestECDSASignAndVerify(t *testing.T) {
89 ctx, err := NewContext(ContextSign | ContextVerify)
90 if err != nil {
91 t.Fatalf("Failed to create context: %v", err)
92 }
93 defer ctx.Destroy()
94
95 privKey := make([]byte, 32)
96 if _, err := rand.Read(privKey); err != nil {
97 t.Fatalf("Failed to generate random key: %v", err)
98 }
99
100 pubKey, err := ctx.CreatePublicKey(privKey)
101 if err != nil {
102 t.Fatalf("Failed to create public key: %v", err)
103 }
104
105 message := []byte("Test message")
106 msgHash := sha256.Sum256(message)
107
108 sig, err := ctx.Sign(msgHash[:], privKey)
109 if err != nil {
110 t.Fatalf("Failed to sign: %v", err)
111 }
112
113 valid, err := ctx.Verify(msgHash[:], sig, pubKey)
114 if err != nil {
115 t.Fatalf("Failed to verify: %v", err)
116 }
117
118 if !valid {
119 t.Fatal("Signature should be valid")
120 }
121
122 // Test with wrong message
123 wrongMsg := []byte("Wrong message")
124 wrongHash := sha256.Sum256(wrongMsg)
125 valid2, err := ctx.Verify(wrongHash[:], sig, pubKey)
126 if err != nil {
127 t.Fatalf("Failed to verify wrong message: %v", err)
128 }
129
130 if valid2 {
131 t.Fatal("Signature should be invalid for wrong message")
132 }
133 }
134
135 func TestDERSignatureSerialization(t *testing.T) {
136 ctx, err := NewContext(ContextSign)
137 if err != nil {
138 t.Fatalf("Failed to create context: %v", err)
139 }
140 defer ctx.Destroy()
141
142 privKey := make([]byte, 32)
143 if _, err := rand.Read(privKey); err != nil {
144 t.Fatalf("Failed to generate random key: %v", err)
145 }
146
147 message := []byte("Test message")
148 msgHash := sha256.Sum256(message)
149
150 sig, err := ctx.Sign(msgHash[:], privKey)
151 if err != nil {
152 t.Fatalf("Failed to sign: %v", err)
153 }
154
155 derSig, err := ctx.SerializeSignatureDER(sig)
156 if err != nil {
157 t.Fatalf("Failed to serialize DER: %v", err)
158 }
159
160 parsed, err := ctx.ParseSignatureDER(derSig)
161 if err != nil {
162 t.Fatalf("Failed to parse DER: %v", err)
163 }
164
165 if len(parsed) != SignatureSize {
166 t.Fatalf("Parsed signature size incorrect: got %d, want %d", len(parsed), SignatureSize)
167 }
168 }
169
170 func TestCompactSignatureSerialization(t *testing.T) {
171 ctx, err := NewContext(ContextSign)
172 if err != nil {
173 t.Fatalf("Failed to create context: %v", err)
174 }
175 defer ctx.Destroy()
176
177 privKey := make([]byte, 32)
178 if _, err := rand.Read(privKey); err != nil {
179 t.Fatalf("Failed to generate random key: %v", err)
180 }
181
182 message := []byte("Test message")
183 msgHash := sha256.Sum256(message)
184
185 sig, err := ctx.Sign(msgHash[:], privKey)
186 if err != nil {
187 t.Fatalf("Failed to sign: %v", err)
188 }
189
190 compact, err := ctx.SerializeSignatureCompact(sig)
191 if err != nil {
192 t.Fatalf("Failed to serialize compact: %v", err)
193 }
194
195 if len(compact) != CompactSignatureSize {
196 t.Fatalf("Compact size incorrect: got %d, want %d", len(compact), CompactSignatureSize)
197 }
198
199 parsed, err := ctx.ParseSignatureCompact(compact)
200 if err != nil {
201 t.Fatalf("Failed to parse compact: %v", err)
202 }
203
204 if len(parsed) != SignatureSize {
205 t.Fatalf("Parsed signature size incorrect: got %d, want %d", len(parsed), SignatureSize)
206 }
207 }
208
209 func TestSignatureNormalization(t *testing.T) {
210 ctx, err := NewContext(ContextSign)
211 if err != nil {
212 t.Fatalf("Failed to create context: %v", err)
213 }
214 defer ctx.Destroy()
215
216 privKey := make([]byte, 32)
217 if _, err := rand.Read(privKey); err != nil {
218 t.Fatalf("Failed to generate random key: %v", err)
219 }
220
221 message := []byte("Test message")
222 msgHash := sha256.Sum256(message)
223
224 sig, err := ctx.Sign(msgHash[:], privKey)
225 if err != nil {
226 t.Fatalf("Failed to sign: %v", err)
227 }
228
229 normalized, wasNormalized, err := ctx.NormalizeSignature(sig)
230 if err != nil {
231 t.Fatalf("Failed to normalize: %v", err)
232 }
233
234 if len(normalized) != SignatureSize {
235 t.Fatalf("Normalized signature size incorrect: got %d, want %d", len(normalized), SignatureSize)
236 }
237
238 _ = wasNormalized // May or may not be normalized
239 }
240
241 func TestSchnorrSignAndVerify(t *testing.T) {
242 if schnorrsigSign32 == nil {
243 t.Skip("Schnorr module not available")
244 }
245
246 ctx, err := NewContext(ContextSign | ContextVerify)
247 if err != nil {
248 t.Fatalf("Failed to create context: %v", err)
249 }
250 defer ctx.Destroy()
251
252 privKey := make([]byte, 32)
253 if _, err := rand.Read(privKey); err != nil {
254 t.Fatalf("Failed to generate random key: %v", err)
255 }
256
257 keypair, err := ctx.CreateKeypair(privKey)
258 if err != nil {
259 t.Fatalf("Failed to create keypair: %v", err)
260 }
261
262 xonly, _, err := ctx.KeypairXOnlyPub(keypair)
263 if err != nil {
264 t.Fatalf("Failed to extract xonly pubkey: %v", err)
265 }
266
267 message := []byte("Test message")
268 msgHash := sha256.Sum256(message)
269
270 auxRand := make([]byte, 32)
271 if _, err := rand.Read(auxRand); err != nil {
272 t.Fatalf("Failed to generate aux_rand: %v", err)
273 }
274
275 sig, err := ctx.SchnorrSign(msgHash[:], keypair, auxRand)
276 if err != nil {
277 t.Fatalf("Failed to sign: %v", err)
278 }
279
280 if len(sig) != SchnorrSignatureSize {
281 t.Fatalf("Signature size incorrect: got %d, want %d", len(sig), SchnorrSignatureSize)
282 }
283
284 valid, err := ctx.SchnorrVerify(sig, msgHash[:], xonly[:])
285 if err != nil {
286 t.Fatalf("Failed to verify: %v", err)
287 }
288
289 if !valid {
290 t.Fatal("Schnorr signature should be valid")
291 }
292
293 // Test with wrong message
294 wrongMsg := []byte("Wrong message")
295 wrongHash := sha256.Sum256(wrongMsg)
296 valid2, err := ctx.SchnorrVerify(sig, wrongHash[:], xonly[:])
297 if err != nil {
298 t.Fatalf("Failed to verify wrong message: %v", err)
299 }
300
301 if valid2 {
302 t.Fatal("Schnorr signature should be invalid for wrong message")
303 }
304 }
305
306 func TestECDH(t *testing.T) {
307 if ecdh == nil {
308 t.Skip("ECDH module not available")
309 }
310
311 ctx, err := NewContext(ContextSign)
312 if err != nil {
313 t.Fatalf("Failed to create context: %v", err)
314 }
315 defer ctx.Destroy()
316
317 // Alice's keys
318 alicePriv := make([]byte, 32)
319 if _, err := rand.Read(alicePriv); err != nil {
320 t.Fatalf("Failed to generate Alice's key: %v", err)
321 }
322 alicePub, err := ctx.CreatePublicKey(alicePriv)
323 if err != nil {
324 t.Fatalf("Failed to create Alice's public key: %v", err)
325 }
326
327 // Bob's keys
328 bobPriv := make([]byte, 32)
329 if _, err := rand.Read(bobPriv); err != nil {
330 t.Fatalf("Failed to generate Bob's key: %v", err)
331 }
332 bobPub, err := ctx.CreatePublicKey(bobPriv)
333 if err != nil {
334 t.Fatalf("Failed to create Bob's public key: %v", err)
335 }
336
337 // Compute shared secrets
338 aliceShared, err := ctx.ECDH(bobPub, alicePriv)
339 if err != nil {
340 t.Fatalf("Failed to compute Alice's shared secret: %v", err)
341 }
342
343 bobShared, err := ctx.ECDH(alicePub, bobPriv)
344 if err != nil {
345 t.Fatalf("Failed to compute Bob's shared secret: %v", err)
346 }
347
348 if len(aliceShared) != SharedSecretSize {
349 t.Fatalf("Shared secret size incorrect: got %d, want %d", len(aliceShared), SharedSecretSize)
350 }
351
352 // Secrets should match
353 if string(aliceShared) != string(bobShared) {
354 t.Fatal("Shared secrets should match")
355 }
356 }
357
358 func TestRecovery(t *testing.T) {
359 if ecdsaSignRecoverable == nil {
360 t.Skip("Recovery module not available")
361 }
362
363 ctx, err := NewContext(ContextSign | ContextVerify)
364 if err != nil {
365 t.Fatalf("Failed to create context: %v", err)
366 }
367 defer ctx.Destroy()
368
369 privKey := make([]byte, 32)
370 if _, err := rand.Read(privKey); err != nil {
371 t.Fatalf("Failed to generate random key: %v", err)
372 }
373
374 originalPubKey, err := ctx.CreatePublicKey(privKey)
375 if err != nil {
376 t.Fatalf("Failed to create public key: %v", err)
377 }
378
379 message := []byte("Test message")
380 msgHash := sha256.Sum256(message)
381
382 recSig, err := ctx.SignRecoverable(msgHash[:], privKey)
383 if err != nil {
384 t.Fatalf("Failed to sign recoverable: %v", err)
385 }
386
387 sigBytes, recID, err := ctx.SerializeRecoverableSignatureCompact(recSig)
388 if err != nil {
389 t.Fatalf("Failed to serialize recoverable: %v", err)
390 }
391
392 if len(sigBytes) != 64 {
393 t.Fatalf("Signature size incorrect: got %d, want 64", len(sigBytes))
394 }
395
396 if recID < 0 || recID > 3 {
397 t.Fatalf("Recovery ID out of range: %d", recID)
398 }
399
400 parsedSig, err := ctx.ParseRecoverableSignatureCompact(sigBytes, recID)
401 if err != nil {
402 t.Fatalf("Failed to parse recoverable: %v", err)
403 }
404
405 recoveredPubKey, err := ctx.Recover(parsedSig, msgHash[:])
406 if err != nil {
407 t.Fatalf("Failed to recover public key: %v", err)
408 }
409
410 // Serialize both for comparison
411 origSer, err := ctx.SerializePublicKey(originalPubKey, true)
412 if err != nil {
413 t.Fatalf("Failed to serialize original: %v", err)
414 }
415
416 recSer, err := ctx.SerializePublicKey(recoveredPubKey, true)
417 if err != nil {
418 t.Fatalf("Failed to serialize recovered: %v", err)
419 }
420
421 if string(origSer) != string(recSer) {
422 t.Fatal("Recovered public key should match original")
423 }
424 }
425
426 func BenchmarkSign(b *testing.B) {
427 ctx, err := NewContext(ContextSign)
428 if err != nil {
429 b.Fatalf("Failed to create context: %v", err)
430 }
431 defer ctx.Destroy()
432
433 privKey := make([]byte, 32)
434 rand.Read(privKey)
435
436 message := []byte("Benchmark message")
437 msgHash := sha256.Sum256(message)
438
439 b.ResetTimer()
440 for i := 0; i < b.N; i++ {
441 _, err := ctx.Sign(msgHash[:], privKey)
442 if err != nil {
443 b.Fatalf("Failed to sign: %v", err)
444 }
445 }
446 }
447
448 func BenchmarkVerify(b *testing.B) {
449 ctx, err := NewContext(ContextSign | ContextVerify)
450 if err != nil {
451 b.Fatalf("Failed to create context: %v", err)
452 }
453 defer ctx.Destroy()
454
455 privKey := make([]byte, 32)
456 rand.Read(privKey)
457
458 pubKey, err := ctx.CreatePublicKey(privKey)
459 if err != nil {
460 b.Fatalf("Failed to create public key: %v", err)
461 }
462
463 message := []byte("Benchmark message")
464 msgHash := sha256.Sum256(message)
465
466 sig, err := ctx.Sign(msgHash[:], privKey)
467 if err != nil {
468 b.Fatalf("Failed to sign: %v", err)
469 }
470
471 b.ResetTimer()
472 for i := 0; i < b.N; i++ {
473 _, err := ctx.Verify(msgHash[:], sig, pubKey)
474 if err != nil {
475 b.Fatalf("Failed to verify: %v", err)
476 }
477 }
478 }
479