rbsecp256k1 6.0.1 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +24 -24
- data/README.md +134 -129
- data/Rakefile +23 -18
- data/documentation/context.md +125 -98
- data/documentation/index.md +391 -378
- data/documentation/key_pair.md +25 -25
- data/documentation/private_key.md +25 -25
- data/documentation/public_key.md +36 -36
- data/documentation/recoverable_signature.md +30 -30
- data/documentation/schnorr_signature.md +34 -30
- data/documentation/secp256k1.md +24 -24
- data/documentation/shared_secret.md +14 -14
- data/documentation/signature.md +42 -42
- data/documentation/util.md +17 -17
- data/documentation/xonly_public_key.md +29 -29
- data/ext/rbsecp256k1/extconf.rb +62 -121
- data/ext/rbsecp256k1/rbsecp256k1.c +2429 -2244
- data/ext/rbsecp256k1/secp256k1_recipe.rb +76 -0
- data/lib/rbsecp256k1/context.rb +40 -36
- data/lib/rbsecp256k1/util.rb +28 -28
- data/lib/rbsecp256k1/version.rb +5 -5
- data/lib/rbsecp256k1.rb +14 -14
- metadata +16 -1
|
@@ -1,2244 +1,2429 @@
|
|
|
1
|
-
// rbsecp256k1.c - Ruby VM interfaces for library.
|
|
2
|
-
//
|
|
3
|
-
// Description:
|
|
4
|
-
// This library provides a low-level and high-performance Ruby wrapper around
|
|
5
|
-
// libsecp256k1. It includes functions for generating key pairs, signing data,
|
|
6
|
-
// and verifying signatures using the library.
|
|
7
|
-
//
|
|
8
|
-
// Dependencies:
|
|
9
|
-
// * libsecp256k1
|
|
10
|
-
|
|
11
|
-
// Sanity check that we have the basic header file.
|
|
12
|
-
#ifndef HAVE_SECP256K1_H
|
|
13
|
-
#error missing secp256k1.h during build
|
|
14
|
-
#endif // HAVE_SECP256K1_H
|
|
15
|
-
|
|
16
|
-
// Sanity check we have extrakeys module as we need it for keypair which is
|
|
17
|
-
// used by schnorrsig.
|
|
18
|
-
#ifndef HAVE_SECP256K1_EXTRAKEYS_H
|
|
19
|
-
#error missing secp256k1_extrakeys.h during build
|
|
20
|
-
#endif // HAVE_SECP256K1_EXTRAKEYS_H
|
|
21
|
-
|
|
22
|
-
#include <ruby.h>
|
|
23
|
-
#include <
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
// |--
|
|
52
|
-
// |--
|
|
53
|
-
// |--
|
|
54
|
-
// |--
|
|
55
|
-
// |--
|
|
56
|
-
// |--
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
static VALUE
|
|
97
|
-
static VALUE
|
|
98
|
-
static VALUE
|
|
99
|
-
static VALUE
|
|
100
|
-
static VALUE
|
|
101
|
-
static VALUE
|
|
102
|
-
static VALUE
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
static VALUE
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
0,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
//
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
*
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
*
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
*
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
//
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
*
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
*
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
*
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
*
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
{
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
{
|
|
514
|
-
return
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
return
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
*
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
static VALUE
|
|
665
|
-
|
|
666
|
-
{
|
|
667
|
-
PublicKey *
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
*
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
*
|
|
790
|
-
*
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
*
|
|
878
|
-
*
|
|
879
|
-
*
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
*
|
|
901
|
-
*
|
|
902
|
-
* keys are
|
|
903
|
-
*
|
|
904
|
-
* @param other [Secp256k1::
|
|
905
|
-
* @return [Boolean] true if
|
|
906
|
-
*/
|
|
907
|
-
static VALUE
|
|
908
|
-
|
|
909
|
-
{
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
if (memcmp(
|
|
917
|
-
{
|
|
918
|
-
return Qtrue;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
return Qfalse;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
//
|
|
925
|
-
// Secp256k1::
|
|
926
|
-
//
|
|
927
|
-
|
|
928
|
-
static VALUE
|
|
929
|
-
|
|
930
|
-
{
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
*
|
|
943
|
-
|
|
944
|
-
*
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
*
|
|
1075
|
-
|
|
1076
|
-
*
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
);
|
|
1232
|
-
|
|
1233
|
-
result
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
if (memcmp(lhs->sig,
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
//
|
|
1450
|
-
|
|
1451
|
-
//
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
*
|
|
1663
|
-
*
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
unsigned char
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
);
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
*
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
*
|
|
1831
|
-
*
|
|
1832
|
-
*
|
|
1833
|
-
*
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
{
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
#
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
*
|
|
1946
|
-
*
|
|
1947
|
-
*
|
|
1948
|
-
*
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
);
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
"
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
rb_define_method(
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
1
|
+
// rbsecp256k1.c - Ruby VM interfaces for library.
|
|
2
|
+
//
|
|
3
|
+
// Description:
|
|
4
|
+
// This library provides a low-level and high-performance Ruby wrapper around
|
|
5
|
+
// libsecp256k1. It includes functions for generating key pairs, signing data,
|
|
6
|
+
// and verifying signatures using the library.
|
|
7
|
+
//
|
|
8
|
+
// Dependencies:
|
|
9
|
+
// * libsecp256k1
|
|
10
|
+
|
|
11
|
+
// Sanity check that we have the basic header file.
|
|
12
|
+
#ifndef HAVE_SECP256K1_H
|
|
13
|
+
#error missing secp256k1.h during build
|
|
14
|
+
#endif // HAVE_SECP256K1_H
|
|
15
|
+
|
|
16
|
+
// Sanity check we have extrakeys module as we need it for keypair which is
|
|
17
|
+
// used by schnorrsig.
|
|
18
|
+
#ifndef HAVE_SECP256K1_EXTRAKEYS_H
|
|
19
|
+
#error missing secp256k1_extrakeys.h during build
|
|
20
|
+
#endif // HAVE_SECP256K1_EXTRAKEYS_H
|
|
21
|
+
|
|
22
|
+
#include <ruby.h>
|
|
23
|
+
#include <ruby/missing.h>
|
|
24
|
+
#include <string.h>
|
|
25
|
+
#include <secp256k1.h>
|
|
26
|
+
#include <secp256k1_preallocated.h>
|
|
27
|
+
|
|
28
|
+
// Check for optional sub-modules. As a rule any secp256k1 submodule is
|
|
29
|
+
// optional and so should be blocked off using these ifdefs.
|
|
30
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
31
|
+
#include <secp256k1_recovery.h>
|
|
32
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
33
|
+
|
|
34
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
35
|
+
#include <secp256k1_ecdh.h>
|
|
36
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
37
|
+
|
|
38
|
+
#ifdef HAVE_SECP256K1_EXTRAKEYS_H
|
|
39
|
+
#include <secp256k1_extrakeys.h>
|
|
40
|
+
#endif // HAVE_SECP256K1_EXTRAKEYS_H
|
|
41
|
+
|
|
42
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
43
|
+
#include <secp256k1_schnorrsig.h>
|
|
44
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
45
|
+
|
|
46
|
+
// High-level design:
|
|
47
|
+
//
|
|
48
|
+
// The Ruby wrapper is divided into the following hierarchical organization:
|
|
49
|
+
//
|
|
50
|
+
// +- Secp256k1 (Top-level module)
|
|
51
|
+
// |-- Context
|
|
52
|
+
// |-- KeyPair
|
|
53
|
+
// |-- PublicKey
|
|
54
|
+
// |-- XOnlyPublicKey
|
|
55
|
+
// |-- PrivateKey
|
|
56
|
+
// |-- RecoverableSignature (recovery module)
|
|
57
|
+
// |-- SharedSecret (ecdh module)
|
|
58
|
+
// |-- Signature
|
|
59
|
+
// |-- SchnorrSignature
|
|
60
|
+
//
|
|
61
|
+
// The Context class contains most of the methods that invoke libsecp256k1.
|
|
62
|
+
// The KeyPair, PublicKey, PrivateKey, RecoverableSignature, SharedSecret, and
|
|
63
|
+
// Signature objects act as data objects and are passed to various
|
|
64
|
+
// methods. Contexts are thread safe and can be used across
|
|
65
|
+
// applications. Context initialization is expensive so it is recommended that
|
|
66
|
+
// a single context be initialized and used throughout an application when
|
|
67
|
+
// possible.
|
|
68
|
+
//
|
|
69
|
+
// Exception Hierarchy:
|
|
70
|
+
//
|
|
71
|
+
// The following hierarchy is used for exceptions raised from the library:
|
|
72
|
+
//
|
|
73
|
+
// +- Error (Descends from StandardError)
|
|
74
|
+
// |-- SerializationError
|
|
75
|
+
// |-- DeserializationError
|
|
76
|
+
|
|
77
|
+
//
|
|
78
|
+
// The section below contains purely internal methods used exclusively by the
|
|
79
|
+
// C internals of the library.
|
|
80
|
+
//
|
|
81
|
+
|
|
82
|
+
// Size of an uncompressed public key
|
|
83
|
+
const size_t UNCOMPRESSED_PUBKEY_SIZE_BYTES = 65;
|
|
84
|
+
// Size of a compressed public key
|
|
85
|
+
const size_t COMPRESSED_PUBKEY_SIZE_BYTES = 33;
|
|
86
|
+
// Size of a serialized x-only public key
|
|
87
|
+
const size_t SERIALIZED_XONLY_PUBKEY_SIZE_BYTES = 32;
|
|
88
|
+
// Size of a compact signature in bytes
|
|
89
|
+
const size_t COMPACT_SIG_SIZE_BYTES = 64;
|
|
90
|
+
// Size of a schnorr signature in bytes
|
|
91
|
+
const size_t SCHNORR_SIG_SIZE_BYTES = 64;
|
|
92
|
+
|
|
93
|
+
// Globally define our module and its associated classes so we can instantiate
|
|
94
|
+
// objects from anywhere. The use of global variables seems to be inline with
|
|
95
|
+
// how the Ruby project builds its own extension gems.
|
|
96
|
+
static VALUE Secp256k1_module;
|
|
97
|
+
static VALUE Secp256k1_Error_class;
|
|
98
|
+
static VALUE Secp256k1_SerializationError_class;
|
|
99
|
+
static VALUE Secp256k1_DeserializationError_class;
|
|
100
|
+
static VALUE Secp256k1_Context_class;
|
|
101
|
+
static VALUE Secp256k1_KeyPair_class;
|
|
102
|
+
static VALUE Secp256k1_PublicKey_class;
|
|
103
|
+
static VALUE Secp256k1_PrivateKey_class;
|
|
104
|
+
static VALUE Secp256k1_Signature_class;
|
|
105
|
+
static VALUE Secp256k1_XOnlyPublicKey_class;
|
|
106
|
+
|
|
107
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
108
|
+
static VALUE Secp256k1_RecoverableSignature_class;
|
|
109
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
110
|
+
|
|
111
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
112
|
+
static VALUE Secp256k1_SharedSecret_class;
|
|
113
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
114
|
+
|
|
115
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
116
|
+
static VALUE Secp256k1_SchnorrSignature_class;
|
|
117
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
118
|
+
|
|
119
|
+
/* Ruby allocates an empty shell before initialize_copy. It must never be
|
|
120
|
+
* usable as a cryptographic value if a subclass skips the copy hook. */
|
|
121
|
+
static void *
|
|
122
|
+
CheckedTypedData_get(VALUE object, const rb_data_type_t *type)
|
|
123
|
+
{
|
|
124
|
+
void *data = rb_check_typeddata(object, type);
|
|
125
|
+
if (data == NULL)
|
|
126
|
+
{
|
|
127
|
+
rb_raise(Secp256k1_Error_class, "native object is not initialized");
|
|
128
|
+
}
|
|
129
|
+
return data;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#define CheckedTypedData_Get_Struct(object, type, descriptor, result) \
|
|
133
|
+
((result) = (type *)CheckedTypedData_get((object), (descriptor)))
|
|
134
|
+
|
|
135
|
+
/* Failed factories remain discoverable through ObjectSpace until GC. Detach
|
|
136
|
+
* their invalid payload before raising, using the normal secret-wiping free
|
|
137
|
+
* callback. Subsequent access and copying then reject the empty shell. */
|
|
138
|
+
static void
|
|
139
|
+
NativeValue_invalidate(VALUE object)
|
|
140
|
+
{
|
|
141
|
+
void *data = RTYPEDDATA_DATA(object);
|
|
142
|
+
const rb_data_type_t *type = RTYPEDDATA_TYPE(object);
|
|
143
|
+
RTYPEDDATA_DATA(object) = NULL;
|
|
144
|
+
if (data != NULL) { type->function.dfree(data); }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Binary inputs are checked as T_STRING before RSTRING_PTR is used. Borrow
|
|
148
|
+
* their bytes only after Ruby allocations; native calls need no NUL terminator.
|
|
149
|
+
* Native payloads do not move, but their Ruby owners must remain live across
|
|
150
|
+
* allocations. Keep RB_GC_GUARD after the last dependent pointer use. */
|
|
151
|
+
|
|
152
|
+
// Forward definitions for all structures
|
|
153
|
+
typedef struct Context_dummy {
|
|
154
|
+
secp256k1_context *ctx; // Context used by libsecp256k1 library
|
|
155
|
+
} Context;
|
|
156
|
+
|
|
157
|
+
typedef struct KeyPair_dummy {
|
|
158
|
+
secp256k1_keypair keypair;
|
|
159
|
+
} KeyPair;
|
|
160
|
+
|
|
161
|
+
typedef struct PublicKey_dummy {
|
|
162
|
+
secp256k1_pubkey pubkey; // Opaque object containing public key data
|
|
163
|
+
} PublicKey;
|
|
164
|
+
|
|
165
|
+
typedef struct PrivateKey_dummy {
|
|
166
|
+
unsigned char data[32]; // Bytes comprising the private key data
|
|
167
|
+
} PrivateKey;
|
|
168
|
+
|
|
169
|
+
typedef struct XOnlyPublicKey_dummy {
|
|
170
|
+
secp256k1_xonly_pubkey pubkey; // Opaque object representing an x-only pubkey.
|
|
171
|
+
} XOnlyPublicKey;
|
|
172
|
+
|
|
173
|
+
typedef struct Signature_dummy {
|
|
174
|
+
secp256k1_ecdsa_signature sig; // Signature object, contains 64-byte signature
|
|
175
|
+
} Signature;
|
|
176
|
+
|
|
177
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
178
|
+
typedef struct RecoverableSignature_dummy {
|
|
179
|
+
secp256k1_ecdsa_recoverable_signature sig; // Recoverable signature object
|
|
180
|
+
secp256k1_context *ctx;
|
|
181
|
+
} RecoverableSignature;
|
|
182
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
183
|
+
|
|
184
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
185
|
+
typedef struct SharedSecret_dummy {
|
|
186
|
+
unsigned char data[32]; // Shared secret data
|
|
187
|
+
} SharedSecret;
|
|
188
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
189
|
+
|
|
190
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
191
|
+
typedef struct SchnorrSignature_dummy {
|
|
192
|
+
unsigned char sig[64]; // Serialized schnorr signature data
|
|
193
|
+
} SchnorrSignature;
|
|
194
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
195
|
+
//
|
|
196
|
+
// Typed data definitions
|
|
197
|
+
// dsize reports owned native storage only; Ruby adds the object itself.
|
|
198
|
+
// This is ObjectSpace reporting, not another charge against Ruby's allocator.
|
|
199
|
+
// Context clone-size queries include the upstream allocation without allocator
|
|
200
|
+
// overhead. No Ruby allocations or exceptions are permitted in these callbacks.
|
|
201
|
+
//
|
|
202
|
+
|
|
203
|
+
// Context
|
|
204
|
+
static void
|
|
205
|
+
Context_free(void* in_context)
|
|
206
|
+
{
|
|
207
|
+
if (in_context == NULL) { return; }
|
|
208
|
+
Context *context;
|
|
209
|
+
context = (Context*)in_context;
|
|
210
|
+
if (context->ctx != NULL) { secp256k1_context_destroy(context->ctx); }
|
|
211
|
+
xfree(context);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static size_t
|
|
215
|
+
Context_memsize(const void *data)
|
|
216
|
+
{
|
|
217
|
+
if (data == NULL) { return 0; }
|
|
218
|
+
const Context *object = (const Context *)data;
|
|
219
|
+
return sizeof(*object) + (object->ctx == NULL ? 0 :
|
|
220
|
+
secp256k1_context_preallocated_clone_size(object->ctx));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
static const rb_data_type_t Context_DataType = {
|
|
224
|
+
"Context",
|
|
225
|
+
{ 0, Context_free, Context_memsize },
|
|
226
|
+
0, 0,
|
|
227
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/* Context.allocate and subclasses can bypass initialize. Never pass their
|
|
231
|
+
* NULL context pointers into libsecp256k1. */
|
|
232
|
+
static Context *
|
|
233
|
+
Context_get(VALUE self)
|
|
234
|
+
{
|
|
235
|
+
Context *context;
|
|
236
|
+
CheckedTypedData_Get_Struct(self, Context, &Context_DataType, context);
|
|
237
|
+
if (context->ctx == NULL)
|
|
238
|
+
{
|
|
239
|
+
rb_raise(Secp256k1_Error_class, "context is not initialized");
|
|
240
|
+
}
|
|
241
|
+
return context;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static VALUE
|
|
245
|
+
Context_initialize_copy(VALUE self, VALUE other)
|
|
246
|
+
{
|
|
247
|
+
Context *context;
|
|
248
|
+
Context *source;
|
|
249
|
+
|
|
250
|
+
if (self == other)
|
|
251
|
+
{
|
|
252
|
+
return self;
|
|
253
|
+
}
|
|
254
|
+
rb_obj_init_copy(self, other);
|
|
255
|
+
source = Context_get(other);
|
|
256
|
+
CheckedTypedData_Get_Struct(self, Context, &Context_DataType, context);
|
|
257
|
+
if (context->ctx != NULL)
|
|
258
|
+
{
|
|
259
|
+
rb_raise(Secp256k1_Error_class, "context is already initialized");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// The copy must own a distinct native allocation so either Ruby object can
|
|
263
|
+
// be collected without invalidating the other or double-freeing its context.
|
|
264
|
+
context->ctx = secp256k1_context_clone(source->ctx);
|
|
265
|
+
return self;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// PublicKey
|
|
269
|
+
static void
|
|
270
|
+
PublicKey_free(void *in_public_key)
|
|
271
|
+
{
|
|
272
|
+
PublicKey *public_key;
|
|
273
|
+
public_key = (PublicKey*)in_public_key;
|
|
274
|
+
xfree(public_key);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
static size_t
|
|
278
|
+
PublicKey_memsize(const void *data)
|
|
279
|
+
{
|
|
280
|
+
return data == NULL ? 0 : sizeof(PublicKey);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
static const rb_data_type_t PublicKey_DataType = {
|
|
284
|
+
"PublicKey",
|
|
285
|
+
{ 0, PublicKey_free, PublicKey_memsize },
|
|
286
|
+
0, 0,
|
|
287
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// XOnlyPublicKey
|
|
291
|
+
static void
|
|
292
|
+
XOnlyPublicKey_free(void* in_xonly_pubkey)
|
|
293
|
+
{
|
|
294
|
+
XOnlyPublicKey *xonly_pubkey;
|
|
295
|
+
xonly_pubkey = (XOnlyPublicKey*)in_xonly_pubkey;
|
|
296
|
+
xfree(xonly_pubkey);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
static size_t
|
|
300
|
+
XOnlyPublicKey_memsize(const void *data)
|
|
301
|
+
{
|
|
302
|
+
return data == NULL ? 0 : sizeof(XOnlyPublicKey);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
static const rb_data_type_t XOnlyPublicKey_DataType = {
|
|
306
|
+
"XOnlyPublicKey",
|
|
307
|
+
{ 0, XOnlyPublicKey_free, XOnlyPublicKey_memsize },
|
|
308
|
+
0, 0,
|
|
309
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
// PrivateKey
|
|
313
|
+
static void
|
|
314
|
+
PrivateKey_free(void *in_private_key)
|
|
315
|
+
{
|
|
316
|
+
if (in_private_key == NULL) { return; }
|
|
317
|
+
PrivateKey *private_key;
|
|
318
|
+
private_key = (PrivateKey*)in_private_key;
|
|
319
|
+
|
|
320
|
+
// Ruby supplies a portable wipe that must not be optimized away. This does
|
|
321
|
+
// not erase Ruby strings or other copies previously returned to callers.
|
|
322
|
+
explicit_bzero(private_key->data, sizeof(private_key->data));
|
|
323
|
+
|
|
324
|
+
xfree(private_key);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
static size_t
|
|
328
|
+
PrivateKey_memsize(const void *data)
|
|
329
|
+
{
|
|
330
|
+
return data == NULL ? 0 : sizeof(PrivateKey);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
static const rb_data_type_t PrivateKey_DataType = {
|
|
334
|
+
"PrivateKey",
|
|
335
|
+
{ 0, PrivateKey_free, PrivateKey_memsize },
|
|
336
|
+
0, 0,
|
|
337
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// KeyPair
|
|
341
|
+
static void
|
|
342
|
+
KeyPair_free(void *in_keypair)
|
|
343
|
+
{
|
|
344
|
+
if (in_keypair == NULL) { return; }
|
|
345
|
+
KeyPair *keypair;
|
|
346
|
+
keypair = (KeyPair*)in_keypair;
|
|
347
|
+
explicit_bzero(keypair, sizeof(*keypair));
|
|
348
|
+
xfree(keypair);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
static size_t
|
|
352
|
+
KeyPair_memsize(const void *data)
|
|
353
|
+
{
|
|
354
|
+
return data == NULL ? 0 : sizeof(KeyPair);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
static const rb_data_type_t KeyPair_DataType = {
|
|
358
|
+
"KeyPair",
|
|
359
|
+
{ 0, KeyPair_free, KeyPair_memsize },
|
|
360
|
+
0, 0,
|
|
361
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// Signature
|
|
365
|
+
static void
|
|
366
|
+
Signature_free(void *in_signature)
|
|
367
|
+
{
|
|
368
|
+
Signature *signature = (Signature*)in_signature;
|
|
369
|
+
xfree(signature);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
static size_t
|
|
373
|
+
Signature_memsize(const void *data)
|
|
374
|
+
{
|
|
375
|
+
return data == NULL ? 0 : sizeof(Signature);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
static const rb_data_type_t Signature_DataType = {
|
|
379
|
+
"Signature",
|
|
380
|
+
{ 0, Signature_free, Signature_memsize },
|
|
381
|
+
0, 0,
|
|
382
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// RecoverableSignature
|
|
386
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
387
|
+
static void
|
|
388
|
+
RecoverableSignature_free(void *in_recoverable_signature)
|
|
389
|
+
{
|
|
390
|
+
if (in_recoverable_signature == NULL) { return; }
|
|
391
|
+
RecoverableSignature *recoverable_signature = (
|
|
392
|
+
(RecoverableSignature*)in_recoverable_signature
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
if (recoverable_signature->ctx != NULL) {
|
|
396
|
+
secp256k1_context_destroy(recoverable_signature->ctx);
|
|
397
|
+
}
|
|
398
|
+
xfree(recoverable_signature);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static size_t
|
|
402
|
+
RecoverableSignature_memsize(const void *data)
|
|
403
|
+
{
|
|
404
|
+
if (data == NULL) { return 0; }
|
|
405
|
+
const RecoverableSignature *object = (const RecoverableSignature *)data;
|
|
406
|
+
return sizeof(*object) + (object->ctx == NULL ? 0 :
|
|
407
|
+
secp256k1_context_preallocated_clone_size(object->ctx));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
static const rb_data_type_t RecoverableSignature_DataType = {
|
|
411
|
+
"RecoverableSignature",
|
|
412
|
+
{ 0, RecoverableSignature_free, RecoverableSignature_memsize },
|
|
413
|
+
0, 0,
|
|
414
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
415
|
+
};
|
|
416
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
417
|
+
|
|
418
|
+
// SharedSecret
|
|
419
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
420
|
+
static void
|
|
421
|
+
SharedSecret_free(void *in_shared_secret)
|
|
422
|
+
{
|
|
423
|
+
if (in_shared_secret == NULL) { return; }
|
|
424
|
+
SharedSecret *shared_secret;
|
|
425
|
+
|
|
426
|
+
shared_secret = (SharedSecret*)in_shared_secret;
|
|
427
|
+
explicit_bzero(shared_secret->data, sizeof(shared_secret->data));
|
|
428
|
+
xfree(shared_secret);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static size_t
|
|
432
|
+
SharedSecret_memsize(const void *data)
|
|
433
|
+
{
|
|
434
|
+
return data == NULL ? 0 : sizeof(SharedSecret);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
static const rb_data_type_t SharedSecret_DataType = {
|
|
438
|
+
"SharedSecret",
|
|
439
|
+
{ 0, SharedSecret_free, SharedSecret_memsize },
|
|
440
|
+
0, 0,
|
|
441
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
442
|
+
};
|
|
443
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
444
|
+
|
|
445
|
+
// SchnorrSignature
|
|
446
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
447
|
+
static void
|
|
448
|
+
SchnorrSignature_free(void *in_schnorr_sig)
|
|
449
|
+
{
|
|
450
|
+
SchnorrSignature *schnorr_sig;
|
|
451
|
+
|
|
452
|
+
schnorr_sig = (SchnorrSignature*)in_schnorr_sig;
|
|
453
|
+
xfree(schnorr_sig);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
static size_t
|
|
457
|
+
SchnorrSignature_memsize(const void *data)
|
|
458
|
+
{
|
|
459
|
+
return data == NULL ? 0 : sizeof(SchnorrSignature);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
static const rb_data_type_t SchnorrSignature_DataType = {
|
|
463
|
+
"SchnorrSignature",
|
|
464
|
+
{ 0, SchnorrSignature_free, SchnorrSignature_memsize },
|
|
465
|
+
0, 0,
|
|
466
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
467
|
+
};
|
|
468
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Macro: SUCCESS
|
|
472
|
+
*
|
|
473
|
+
* Determines whether or not the given function result was a success.
|
|
474
|
+
*/
|
|
475
|
+
#define SUCCESS(x) ((x) == RESULT_SUCCESS)
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Macro: FAILURE
|
|
479
|
+
*
|
|
480
|
+
* Indicates whether or not the given function result is a failure.
|
|
481
|
+
*/
|
|
482
|
+
#define FAILURE(x) !SUCCESS(x)
|
|
483
|
+
|
|
484
|
+
/* Result type for internally defined functions */
|
|
485
|
+
typedef enum ResultT_dummy {
|
|
486
|
+
RESULT_SUCCESS,
|
|
487
|
+
RESULT_FAILURE
|
|
488
|
+
} ResultT;
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Computes the ECDSA signature of the given 32-byte SHA-256 hash.
|
|
492
|
+
*
|
|
493
|
+
* \param in_context libsecp256k1 context
|
|
494
|
+
* \param in_hash32 32-byte SHA-256 hash
|
|
495
|
+
* \param in_private_key Private key to be used for signing
|
|
496
|
+
* \param out_signature Signature produced during the signing proccess
|
|
497
|
+
* \return RESULT_SUCCESS if the hash and signature were computed successfully,
|
|
498
|
+
* RESULT_FAILURE if signing failed or DER encoding failed.
|
|
499
|
+
*/
|
|
500
|
+
static ResultT
|
|
501
|
+
SignData(secp256k1_context *in_context,
|
|
502
|
+
unsigned char *in_hash32,
|
|
503
|
+
unsigned char *in_private_key,
|
|
504
|
+
secp256k1_ecdsa_signature *out_signature)
|
|
505
|
+
{
|
|
506
|
+
// Sign the hash of the data
|
|
507
|
+
if (secp256k1_ecdsa_sign(in_context,
|
|
508
|
+
out_signature,
|
|
509
|
+
in_hash32,
|
|
510
|
+
in_private_key,
|
|
511
|
+
NULL,
|
|
512
|
+
NULL) == 1)
|
|
513
|
+
{
|
|
514
|
+
return RESULT_SUCCESS;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return RESULT_FAILURE;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Computes the recoverable ECDSA signature of the given data.
|
|
524
|
+
*
|
|
525
|
+
* ECDSA signing involves the following steps:
|
|
526
|
+
* 1. Compute the 32-byte SHA-256 hash of the given data.
|
|
527
|
+
* 2. Sign the 32-byte hash using the private key provided.
|
|
528
|
+
*
|
|
529
|
+
* \param in_context libsecp256k1 context
|
|
530
|
+
* \param in_hash32 32-byte SHA-256 hash to sign
|
|
531
|
+
* \param in_private_key Private key to be used for signing
|
|
532
|
+
* \param out_signature Recoverable signature computed
|
|
533
|
+
* \return RESULT_SUCCESS if the hash and signature were computed successfully,
|
|
534
|
+
* RESULT_FAILURE if signing failed or DER encoding failed.
|
|
535
|
+
*/
|
|
536
|
+
static ResultT
|
|
537
|
+
RecoverableSignData(secp256k1_context *in_context,
|
|
538
|
+
unsigned char *in_hash32,
|
|
539
|
+
unsigned char *in_private_key,
|
|
540
|
+
secp256k1_ecdsa_recoverable_signature *out_signature)
|
|
541
|
+
{
|
|
542
|
+
if (secp256k1_ecdsa_sign_recoverable(in_context,
|
|
543
|
+
out_signature,
|
|
544
|
+
in_hash32,
|
|
545
|
+
in_private_key,
|
|
546
|
+
NULL,
|
|
547
|
+
NULL) == 1)
|
|
548
|
+
{
|
|
549
|
+
return RESULT_SUCCESS;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return RESULT_FAILURE;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
556
|
+
|
|
557
|
+
//
|
|
558
|
+
// Secp256k1::XOnlyPublicKey class interface
|
|
559
|
+
//
|
|
560
|
+
|
|
561
|
+
static VALUE
|
|
562
|
+
XOnlyPublicKey_alloc(VALUE klass)
|
|
563
|
+
{
|
|
564
|
+
// Allocate the Ruby owner first; a failed wrapper allocation must not leak.
|
|
565
|
+
return rb_data_typed_object_zalloc(klass, sizeof(XOnlyPublicKey), &XOnlyPublicKey_DataType);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
static VALUE
|
|
569
|
+
XOnlyPublicKey_create_from_data(VALUE in_data)
|
|
570
|
+
{
|
|
571
|
+
XOnlyPublicKey *xonly_pubkey;
|
|
572
|
+
VALUE result;
|
|
573
|
+
|
|
574
|
+
result = XOnlyPublicKey_alloc(Secp256k1_XOnlyPublicKey_class);
|
|
575
|
+
CheckedTypedData_Get_Struct(result, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
576
|
+
|
|
577
|
+
if (secp256k1_xonly_pubkey_parse(secp256k1_context_static, &xonly_pubkey->pubkey, (unsigned char*)RSTRING_PTR(in_data)) != 1)
|
|
578
|
+
{
|
|
579
|
+
NativeValue_invalidate(result);
|
|
580
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid x-only public key data");
|
|
581
|
+
return Qnil;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Loads an x-only public key from serialized data.
|
|
589
|
+
*
|
|
590
|
+
* @param in_xonly_public_key_serialized [String] binary string with serialized
|
|
591
|
+
* data.
|
|
592
|
+
* @return [Secp256k1::XOnlyPublicKey] x-only public key derived from data.
|
|
593
|
+
* @raise [Secp256k1::DeserializationError] if x-only public key data is invalid
|
|
594
|
+
*/
|
|
595
|
+
static VALUE
|
|
596
|
+
XOnlyPublicKey_from_data(VALUE klass, VALUE in_xonly_public_key_serialized)
|
|
597
|
+
{
|
|
598
|
+
Check_Type(in_xonly_public_key_serialized, T_STRING);
|
|
599
|
+
if (RSTRING_LEN(in_xonly_public_key_serialized) != 32)
|
|
600
|
+
{
|
|
601
|
+
rb_raise(Secp256k1_DeserializationError_class, "x-only public key data must be 32 bytes in length");
|
|
602
|
+
return Qnil;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return XOnlyPublicKey_create_from_data(in_xonly_public_key_serialized);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Returns the 32-byte serialized version of this x-only public key.
|
|
610
|
+
*
|
|
611
|
+
* @return [String] 32-byte binary string containing serialized x-only public
|
|
612
|
+
* key.
|
|
613
|
+
*/
|
|
614
|
+
static VALUE
|
|
615
|
+
XOnlyPublicKey_serialized(VALUE self)
|
|
616
|
+
{
|
|
617
|
+
XOnlyPublicKey* xonly_pubkey;
|
|
618
|
+
unsigned char out[SERIALIZED_XONLY_PUBKEY_SIZE_BYTES];
|
|
619
|
+
|
|
620
|
+
CheckedTypedData_Get_Struct(self, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
621
|
+
|
|
622
|
+
if (secp256k1_xonly_pubkey_serialize(secp256k1_context_static, out, &xonly_pubkey->pubkey) != 1)
|
|
623
|
+
{
|
|
624
|
+
rb_raise(Secp256k1_SerializationError_class, "failed to serialize x-only public key");
|
|
625
|
+
return Qnil;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return rb_str_new((char*)out, SERIALIZED_XONLY_PUBKEY_SIZE_BYTES);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Compare two x-only public keys.
|
|
633
|
+
*
|
|
634
|
+
* @param other [Secp256k1::XOnlyPublicKey] x-only public key to compare.
|
|
635
|
+
* @return [Boolean] true if they are equal, false otherwise.
|
|
636
|
+
*/
|
|
637
|
+
static VALUE
|
|
638
|
+
XOnlyPublicKey_equals(VALUE self, VALUE other)
|
|
639
|
+
{
|
|
640
|
+
XOnlyPublicKey *lhs;
|
|
641
|
+
XOnlyPublicKey *rhs;
|
|
642
|
+
|
|
643
|
+
CheckedTypedData_Get_Struct(self, XOnlyPublicKey, &XOnlyPublicKey_DataType, lhs);
|
|
644
|
+
CheckedTypedData_Get_Struct(other, XOnlyPublicKey, &XOnlyPublicKey_DataType, rhs);
|
|
645
|
+
|
|
646
|
+
if (secp256k1_xonly_pubkey_cmp(secp256k1_context_static, &lhs->pubkey, &rhs->pubkey) == 0)
|
|
647
|
+
{
|
|
648
|
+
return Qtrue;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
return Qfalse;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
//
|
|
655
|
+
// Secp256k1::PublicKey class interface
|
|
656
|
+
//
|
|
657
|
+
|
|
658
|
+
static VALUE
|
|
659
|
+
PublicKey_alloc(VALUE klass)
|
|
660
|
+
{
|
|
661
|
+
return rb_data_typed_object_zalloc(klass, sizeof(PublicKey), &PublicKey_DataType);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
static VALUE
|
|
665
|
+
PublicKey_create_from_data(VALUE in_data)
|
|
666
|
+
{
|
|
667
|
+
PublicKey *public_key;
|
|
668
|
+
VALUE result;
|
|
669
|
+
|
|
670
|
+
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
|
671
|
+
CheckedTypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
|
672
|
+
|
|
673
|
+
if (secp256k1_ec_pubkey_parse(secp256k1_context_static,
|
|
674
|
+
&(public_key->pubkey),
|
|
675
|
+
(unsigned char*)RSTRING_PTR(in_data),
|
|
676
|
+
(size_t)RSTRING_LEN(in_data)) != 1)
|
|
677
|
+
{
|
|
678
|
+
NativeValue_invalidate(result);
|
|
679
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid public key data");
|
|
680
|
+
return Qnil;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return result;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Loads a public key from compressed or uncompressed binary data.
|
|
688
|
+
*
|
|
689
|
+
* @param in_public_key_data [String] binary string with compressed or
|
|
690
|
+
* uncompressed public key data.
|
|
691
|
+
* @return [Secp256k1::PublicKey] public key derived from data.
|
|
692
|
+
* @raise [Secp256k1::DeserializationError] if public key data is invalid.
|
|
693
|
+
*/
|
|
694
|
+
static VALUE
|
|
695
|
+
PublicKey_from_data(VALUE klass, VALUE in_public_key_data)
|
|
696
|
+
{
|
|
697
|
+
Check_Type(in_public_key_data, T_STRING);
|
|
698
|
+
return PublicKey_create_from_data(in_public_key_data);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* @return [String] binary string containing the uncompressed representation
|
|
703
|
+
* of this public key.
|
|
704
|
+
*/
|
|
705
|
+
static VALUE
|
|
706
|
+
PublicKey_uncompressed(VALUE self)
|
|
707
|
+
{
|
|
708
|
+
// TODO: Cache value after first computation
|
|
709
|
+
PublicKey *public_key;
|
|
710
|
+
size_t serialized_pubkey_len = UNCOMPRESSED_PUBKEY_SIZE_BYTES;
|
|
711
|
+
unsigned char serialized_pubkey[UNCOMPRESSED_PUBKEY_SIZE_BYTES];
|
|
712
|
+
|
|
713
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
|
714
|
+
|
|
715
|
+
secp256k1_ec_pubkey_serialize(secp256k1_context_static,
|
|
716
|
+
serialized_pubkey,
|
|
717
|
+
&serialized_pubkey_len,
|
|
718
|
+
&(public_key->pubkey),
|
|
719
|
+
SECP256K1_EC_UNCOMPRESSED);
|
|
720
|
+
|
|
721
|
+
return rb_str_new((char*)serialized_pubkey, serialized_pubkey_len);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* @return [String] binary string containing the compressed representation of
|
|
726
|
+
* this public key.
|
|
727
|
+
*/
|
|
728
|
+
static VALUE
|
|
729
|
+
PublicKey_compressed(VALUE self)
|
|
730
|
+
{
|
|
731
|
+
// TODO: Cache value after first computation
|
|
732
|
+
PublicKey *public_key;
|
|
733
|
+
size_t serialized_pubkey_len = COMPRESSED_PUBKEY_SIZE_BYTES;
|
|
734
|
+
unsigned char serialized_pubkey[COMPRESSED_PUBKEY_SIZE_BYTES];
|
|
735
|
+
|
|
736
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
|
737
|
+
|
|
738
|
+
secp256k1_ec_pubkey_serialize(secp256k1_context_static,
|
|
739
|
+
serialized_pubkey,
|
|
740
|
+
&serialized_pubkey_len,
|
|
741
|
+
&(public_key->pubkey),
|
|
742
|
+
SECP256K1_EC_COMPRESSED);
|
|
743
|
+
|
|
744
|
+
return rb_str_new((char*)serialized_pubkey, serialized_pubkey_len);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Returns the x-only public key equivalent of this public key.
|
|
749
|
+
*
|
|
750
|
+
* @return [Secp256k1::XOnlyPublicKey] x-only public key
|
|
751
|
+
*/
|
|
752
|
+
static VALUE
|
|
753
|
+
PublicKey_to_xonly(VALUE self)
|
|
754
|
+
{
|
|
755
|
+
PublicKey *public_key;
|
|
756
|
+
XOnlyPublicKey *xonly_pubkey;
|
|
757
|
+
VALUE result;
|
|
758
|
+
|
|
759
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
|
760
|
+
|
|
761
|
+
result = XOnlyPublicKey_alloc(Secp256k1_XOnlyPublicKey_class);
|
|
762
|
+
CheckedTypedData_Get_Struct(result, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
763
|
+
|
|
764
|
+
if (secp256k1_xonly_pubkey_from_pubkey(secp256k1_context_static,
|
|
765
|
+
&xonly_pubkey->pubkey,
|
|
766
|
+
NULL,
|
|
767
|
+
&public_key->pubkey) != 1)
|
|
768
|
+
{
|
|
769
|
+
NativeValue_invalidate(result);
|
|
770
|
+
rb_raise(Secp256k1_Error_class, "failed to convert pubkey to x-only pubkey");
|
|
771
|
+
return Qnil;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
RB_GC_GUARD(self);
|
|
775
|
+
return result;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Compares two public keys.
|
|
780
|
+
*
|
|
781
|
+
* Public keys are considered equal if their compressed representations match.
|
|
782
|
+
*
|
|
783
|
+
* @param other [Secp256k1::PublicKey] public key to compare.
|
|
784
|
+
* @return [Boolean] true if the public keys are identical, false otherwise.
|
|
785
|
+
*/
|
|
786
|
+
static VALUE
|
|
787
|
+
PublicKey_equals(VALUE self, VALUE other)
|
|
788
|
+
{
|
|
789
|
+
PublicKey *lhs;
|
|
790
|
+
PublicKey *rhs;
|
|
791
|
+
unsigned char lhs_compressed[33];
|
|
792
|
+
unsigned char rhs_compressed[33];
|
|
793
|
+
size_t lhs_len;
|
|
794
|
+
size_t rhs_len;
|
|
795
|
+
|
|
796
|
+
lhs_len = 33;
|
|
797
|
+
rhs_len = 33;
|
|
798
|
+
|
|
799
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, lhs);
|
|
800
|
+
CheckedTypedData_Get_Struct(other, PublicKey, &PublicKey_DataType, rhs);
|
|
801
|
+
|
|
802
|
+
secp256k1_ec_pubkey_serialize(
|
|
803
|
+
secp256k1_context_static,
|
|
804
|
+
lhs_compressed,
|
|
805
|
+
&lhs_len,
|
|
806
|
+
&(lhs->pubkey),
|
|
807
|
+
SECP256K1_EC_COMPRESSED
|
|
808
|
+
);
|
|
809
|
+
secp256k1_ec_pubkey_serialize(
|
|
810
|
+
secp256k1_context_static,
|
|
811
|
+
rhs_compressed,
|
|
812
|
+
&rhs_len,
|
|
813
|
+
&(rhs->pubkey),
|
|
814
|
+
SECP256K1_EC_COMPRESSED
|
|
815
|
+
);
|
|
816
|
+
|
|
817
|
+
if (lhs_len == rhs_len &&
|
|
818
|
+
memcmp(lhs_compressed, rhs_compressed, lhs_len) == 0)
|
|
819
|
+
{
|
|
820
|
+
return Qtrue;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
return Qfalse;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
//
|
|
827
|
+
// Secp256k1::PrivateKey class interface
|
|
828
|
+
//
|
|
829
|
+
|
|
830
|
+
static VALUE
|
|
831
|
+
PrivateKey_alloc(VALUE klass)
|
|
832
|
+
{
|
|
833
|
+
return rb_data_typed_object_zalloc(klass, sizeof(PrivateKey), &PrivateKey_DataType);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/* Internal-only method for creating a private key from secret data */
|
|
837
|
+
static VALUE
|
|
838
|
+
PrivateKey_create(VALUE in_private_key_data)
|
|
839
|
+
{
|
|
840
|
+
PrivateKey *private_key;
|
|
841
|
+
VALUE result;
|
|
842
|
+
|
|
843
|
+
if (secp256k1_ec_seckey_verify(secp256k1_context_static,
|
|
844
|
+
(unsigned char*)RSTRING_PTR(in_private_key_data)) != 1)
|
|
845
|
+
{
|
|
846
|
+
rb_raise(Secp256k1_Error_class, "invalid private key data");
|
|
847
|
+
return Qnil;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
result = PrivateKey_alloc(Secp256k1_PrivateKey_class);
|
|
851
|
+
CheckedTypedData_Get_Struct(result, PrivateKey, &PrivateKey_DataType, private_key);
|
|
852
|
+
MEMCPY(private_key->data, RSTRING_PTR(in_private_key_data), char, 32);
|
|
853
|
+
|
|
854
|
+
return result;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Returns binary string of private key data.
|
|
859
|
+
*
|
|
860
|
+
* @return [String] 32 byte binary string of private key data.
|
|
861
|
+
*/
|
|
862
|
+
static VALUE
|
|
863
|
+
PrivateKey_data(VALUE self)
|
|
864
|
+
{
|
|
865
|
+
PrivateKey *private_key;
|
|
866
|
+
VALUE result;
|
|
867
|
+
|
|
868
|
+
CheckedTypedData_Get_Struct(self, PrivateKey, &PrivateKey_DataType, private_key);
|
|
869
|
+
|
|
870
|
+
result = rb_str_new((char*)private_key->data, 32);
|
|
871
|
+
RB_GC_GUARD(self);
|
|
872
|
+
return result;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Load a private key from binary data.
|
|
877
|
+
*
|
|
878
|
+
* @param in_private_key_data [String] 32 byte binary string of private key
|
|
879
|
+
* data.
|
|
880
|
+
* @return [Secp256k1::PrivateKey] private key loaded from the given data.
|
|
881
|
+
* @raise [Secp256k1::Error] if private key data is not 32 bytes or is invalid.
|
|
882
|
+
*/
|
|
883
|
+
static VALUE
|
|
884
|
+
PrivateKey_from_data(VALUE klass, VALUE in_private_key_data)
|
|
885
|
+
{
|
|
886
|
+
Check_Type(in_private_key_data, T_STRING);
|
|
887
|
+
if (RSTRING_LEN(in_private_key_data) != 32)
|
|
888
|
+
{
|
|
889
|
+
rb_raise(
|
|
890
|
+
Secp256k1_Error_class,
|
|
891
|
+
"private key data must be 32 bytes in length"
|
|
892
|
+
);
|
|
893
|
+
return Qnil;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
return PrivateKey_create(in_private_key_data);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Compare two private keys.
|
|
901
|
+
*
|
|
902
|
+
* Private keys are considered equal if their data fields are identical.
|
|
903
|
+
*
|
|
904
|
+
* @param other [Secp256k1::PrivateKey] private key to compare.
|
|
905
|
+
* @return [Boolean] true if they are equal, false otherwise.
|
|
906
|
+
*/
|
|
907
|
+
static VALUE
|
|
908
|
+
PrivateKey_equals(VALUE self, VALUE other)
|
|
909
|
+
{
|
|
910
|
+
PrivateKey *lhs;
|
|
911
|
+
PrivateKey *rhs;
|
|
912
|
+
|
|
913
|
+
CheckedTypedData_Get_Struct(self, PrivateKey, &PrivateKey_DataType, lhs);
|
|
914
|
+
CheckedTypedData_Get_Struct(other, PrivateKey, &PrivateKey_DataType, rhs);
|
|
915
|
+
|
|
916
|
+
if (memcmp(lhs->data, rhs->data, 32) == 0)
|
|
917
|
+
{
|
|
918
|
+
return Qtrue;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
return Qfalse;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
//
|
|
925
|
+
// Secp256k1::KeyPair class interface
|
|
926
|
+
//
|
|
927
|
+
|
|
928
|
+
static VALUE
|
|
929
|
+
KeyPair_alloc(VALUE klass)
|
|
930
|
+
{
|
|
931
|
+
return rb_data_typed_object_zalloc(klass, sizeof(KeyPair), &KeyPair_DataType);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Retrieve the public key for the given key pair.
|
|
936
|
+
*
|
|
937
|
+
* @return [Secp256k1::PublicKey] public key corresponding to private key.
|
|
938
|
+
*/
|
|
939
|
+
static VALUE
|
|
940
|
+
KeyPair_public_key(VALUE self)
|
|
941
|
+
{
|
|
942
|
+
KeyPair *key_pair;
|
|
943
|
+
VALUE result;
|
|
944
|
+
PublicKey *public_key;
|
|
945
|
+
|
|
946
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, key_pair);
|
|
947
|
+
|
|
948
|
+
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
|
949
|
+
CheckedTypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
|
950
|
+
|
|
951
|
+
if (secp256k1_keypair_pub(secp256k1_context_static, &public_key->pubkey, &key_pair->keypair) == 0)
|
|
952
|
+
{
|
|
953
|
+
NativeValue_invalidate(result);
|
|
954
|
+
rb_raise(Secp256k1_Error_class, "failed to derive public key from keypair");
|
|
955
|
+
return Qnil;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
RB_GC_GUARD(self);
|
|
959
|
+
return result;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Retrieve the x-only public key for the given key pair.
|
|
964
|
+
*
|
|
965
|
+
* @return [Secp256k1::XOnlyPublicKey] x-only public key corresponding to
|
|
966
|
+
* private key.
|
|
967
|
+
*/
|
|
968
|
+
static VALUE
|
|
969
|
+
KeyPair_xonly_public_key(VALUE self)
|
|
970
|
+
{
|
|
971
|
+
KeyPair *key_pair;
|
|
972
|
+
VALUE result;
|
|
973
|
+
XOnlyPublicKey *xonly_pubkey;
|
|
974
|
+
|
|
975
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, key_pair);
|
|
976
|
+
|
|
977
|
+
result = XOnlyPublicKey_alloc(Secp256k1_XOnlyPublicKey_class);
|
|
978
|
+
CheckedTypedData_Get_Struct(result, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
979
|
+
|
|
980
|
+
if (secp256k1_keypair_xonly_pub(secp256k1_context_static, &xonly_pubkey->pubkey, NULL, &key_pair->keypair) == 0)
|
|
981
|
+
{
|
|
982
|
+
NativeValue_invalidate(result);
|
|
983
|
+
rb_raise(Secp256k1_Error_class, "failed to derive x-only public key from keypair");
|
|
984
|
+
return Qnil;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
RB_GC_GUARD(self);
|
|
988
|
+
return result;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Retrieve the private key for the given key pair.
|
|
993
|
+
*
|
|
994
|
+
* @return [Secp256k1::PrivateKey] public key corresponding to private key.
|
|
995
|
+
*/
|
|
996
|
+
static VALUE
|
|
997
|
+
KeyPair_private_key(VALUE self)
|
|
998
|
+
{
|
|
999
|
+
KeyPair *key_pair;
|
|
1000
|
+
PrivateKey *private_key;
|
|
1001
|
+
VALUE result;
|
|
1002
|
+
|
|
1003
|
+
// Validate the source before publishing an output object. Keep its owner
|
|
1004
|
+
// live across allocation while extracting directly into owned secret storage.
|
|
1005
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, key_pair);
|
|
1006
|
+
result = PrivateKey_alloc(Secp256k1_PrivateKey_class);
|
|
1007
|
+
CheckedTypedData_Get_Struct(result, PrivateKey, &PrivateKey_DataType, private_key);
|
|
1008
|
+
|
|
1009
|
+
if (secp256k1_keypair_sec(secp256k1_context_static, private_key->data, &key_pair->keypair) == 0)
|
|
1010
|
+
{
|
|
1011
|
+
NativeValue_invalidate(result);
|
|
1012
|
+
rb_raise(Secp256k1_Error_class, "failed to derive private key from keypair");
|
|
1013
|
+
return Qnil;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
if (secp256k1_ec_seckey_verify(secp256k1_context_static, private_key->data) != 1)
|
|
1017
|
+
{
|
|
1018
|
+
NativeValue_invalidate(result);
|
|
1019
|
+
rb_raise(Secp256k1_Error_class, "invalid private key data");
|
|
1020
|
+
return Qnil;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
RB_GC_GUARD(self);
|
|
1024
|
+
return result;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Compare two key pairs.
|
|
1029
|
+
*
|
|
1030
|
+
* Two key pairs are equal if they have the same public and private key. The
|
|
1031
|
+
* keys are compared using their own comparison operators.
|
|
1032
|
+
*
|
|
1033
|
+
* @param other [Secp256k1::KeyPair] key pair to compare to.
|
|
1034
|
+
* @return [Boolean] true if the keys match, false otherwise.
|
|
1035
|
+
*/
|
|
1036
|
+
static VALUE
|
|
1037
|
+
KeyPair_equals(VALUE self, VALUE other)
|
|
1038
|
+
{
|
|
1039
|
+
KeyPair *lhs;
|
|
1040
|
+
KeyPair *rhs;
|
|
1041
|
+
|
|
1042
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, lhs);
|
|
1043
|
+
CheckedTypedData_Get_Struct(other, KeyPair, &KeyPair_DataType, rhs);
|
|
1044
|
+
|
|
1045
|
+
if (memcmp(&lhs->keypair, &rhs->keypair, sizeof(secp256k1_keypair)) == 0)
|
|
1046
|
+
{
|
|
1047
|
+
return Qtrue;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
return Qfalse;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
//
|
|
1054
|
+
// Secp256k1::Signature class interface
|
|
1055
|
+
//
|
|
1056
|
+
|
|
1057
|
+
static VALUE
|
|
1058
|
+
Signature_alloc(VALUE klass)
|
|
1059
|
+
{
|
|
1060
|
+
return rb_data_typed_object_zalloc(klass, sizeof(Signature), &Signature_DataType);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Deserializes a Signature from 64-byte compact signature data.
|
|
1065
|
+
*
|
|
1066
|
+
* @param in_compact_signature [String] compact signature as 64-byte binary
|
|
1067
|
+
* string.
|
|
1068
|
+
* @return [Secp256k1::Signature] object deserialized from compact signature.
|
|
1069
|
+
* @raise [Secp256k1::DeserializationError] if signature data is invalid.
|
|
1070
|
+
*/
|
|
1071
|
+
static VALUE
|
|
1072
|
+
Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
|
1073
|
+
{
|
|
1074
|
+
Signature *signature;
|
|
1075
|
+
VALUE signature_result;
|
|
1076
|
+
unsigned char *signature_data;
|
|
1077
|
+
|
|
1078
|
+
Check_Type(in_compact_signature, T_STRING);
|
|
1079
|
+
|
|
1080
|
+
if (RSTRING_LEN(in_compact_signature) != 64)
|
|
1081
|
+
{
|
|
1082
|
+
rb_raise(Secp256k1_Error_class, "compact signature must be 64 bytes");
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
|
1086
|
+
CheckedTypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
|
1087
|
+
signature_data = (unsigned char*)RSTRING_PTR(in_compact_signature);
|
|
1088
|
+
|
|
1089
|
+
if (secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static,
|
|
1090
|
+
&(signature->sig),
|
|
1091
|
+
signature_data) != 1)
|
|
1092
|
+
{
|
|
1093
|
+
NativeValue_invalidate(signature_result);
|
|
1094
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid compact signature");
|
|
1095
|
+
return Qnil;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
return signature_result;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Converts a DER encoded binary signature into a signature object.
|
|
1103
|
+
*
|
|
1104
|
+
* @param in_der_encoded_signature [String] DER encoded signature as binary
|
|
1105
|
+
* string.
|
|
1106
|
+
* @return [Secp256k1::Signature] signature object initialized using signature
|
|
1107
|
+
* data.
|
|
1108
|
+
* @raise [Secp256k1::DeserializationError] if signature data is invalid.
|
|
1109
|
+
*/
|
|
1110
|
+
static VALUE
|
|
1111
|
+
Signature_from_der_encoded(VALUE klass, VALUE in_der_encoded_signature)
|
|
1112
|
+
{
|
|
1113
|
+
Signature *signature;
|
|
1114
|
+
VALUE signature_result;
|
|
1115
|
+
unsigned char *signature_data;
|
|
1116
|
+
|
|
1117
|
+
Check_Type(in_der_encoded_signature, T_STRING);
|
|
1118
|
+
|
|
1119
|
+
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
|
1120
|
+
CheckedTypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
|
1121
|
+
signature_data = (unsigned char*)RSTRING_PTR(in_der_encoded_signature);
|
|
1122
|
+
|
|
1123
|
+
if (secp256k1_ecdsa_signature_parse_der(secp256k1_context_static,
|
|
1124
|
+
&(signature->sig),
|
|
1125
|
+
signature_data,
|
|
1126
|
+
RSTRING_LEN(in_der_encoded_signature)) != 1)
|
|
1127
|
+
{
|
|
1128
|
+
NativeValue_invalidate(signature_result);
|
|
1129
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid DER encoded signature");
|
|
1130
|
+
return Qnil;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
return signature_result;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* Return Distinguished Encoding Rules (DER) encoded signature data.
|
|
1138
|
+
*
|
|
1139
|
+
* @return [String] binary string containing DER-encoded signature data.
|
|
1140
|
+
*/
|
|
1141
|
+
static VALUE
|
|
1142
|
+
Signature_der_encoded(VALUE self)
|
|
1143
|
+
{
|
|
1144
|
+
// TODO: Cache value after first computation
|
|
1145
|
+
Signature *signature;
|
|
1146
|
+
unsigned char der_signature[72];
|
|
1147
|
+
size_t der_signature_len = sizeof(der_signature);
|
|
1148
|
+
|
|
1149
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
|
1150
|
+
|
|
1151
|
+
if (secp256k1_ecdsa_signature_serialize_der(secp256k1_context_static,
|
|
1152
|
+
der_signature,
|
|
1153
|
+
&der_signature_len,
|
|
1154
|
+
&(signature->sig)) != 1)
|
|
1155
|
+
{
|
|
1156
|
+
rb_raise(
|
|
1157
|
+
Secp256k1_SerializationError_class,
|
|
1158
|
+
"could not compute DER encoded signature"
|
|
1159
|
+
);
|
|
1160
|
+
return Qnil;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
// The serializer's output length is bounded by the 72-byte stack buffer.
|
|
1164
|
+
return rb_str_new((char*)der_signature, (long)der_signature_len);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Returns the 64 byte compact representation of this signature.
|
|
1169
|
+
*
|
|
1170
|
+
* @return [String] 64 byte binary string containing signature data.
|
|
1171
|
+
*/
|
|
1172
|
+
static VALUE
|
|
1173
|
+
Signature_compact(VALUE self)
|
|
1174
|
+
{
|
|
1175
|
+
// TODO: Cache value after first computation
|
|
1176
|
+
Signature *signature;
|
|
1177
|
+
unsigned char compact_signature[COMPACT_SIG_SIZE_BYTES];
|
|
1178
|
+
|
|
1179
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
|
1180
|
+
|
|
1181
|
+
if (secp256k1_ecdsa_signature_serialize_compact(secp256k1_context_static,
|
|
1182
|
+
compact_signature,
|
|
1183
|
+
&(signature->sig)) != 1)
|
|
1184
|
+
{
|
|
1185
|
+
rb_raise(
|
|
1186
|
+
Secp256k1_SerializationError_class,
|
|
1187
|
+
"unable to compute compact signature"
|
|
1188
|
+
);
|
|
1189
|
+
return Qnil;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
return rb_str_new((char*)compact_signature, COMPACT_SIG_SIZE_BYTES);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* Returns the normalized lower-S form of this signature.
|
|
1197
|
+
*
|
|
1198
|
+
* This can be useful when importing signatures generated by other applications
|
|
1199
|
+
* that may not be normalized. Non-normalized signatures are potentially
|
|
1200
|
+
* forgeable.
|
|
1201
|
+
*
|
|
1202
|
+
* @return [Array] first element is a boolean that is `true` if the signature
|
|
1203
|
+
* was normalized, false otherwise. The second element is a `Signature`
|
|
1204
|
+
* object corresponding to the normalized signature.
|
|
1205
|
+
*/
|
|
1206
|
+
static VALUE
|
|
1207
|
+
Signature_normalized(VALUE self)
|
|
1208
|
+
{
|
|
1209
|
+
VALUE result_sig;
|
|
1210
|
+
VALUE was_normalized;
|
|
1211
|
+
VALUE result;
|
|
1212
|
+
Signature *signature;
|
|
1213
|
+
Signature *normalized_signature;
|
|
1214
|
+
|
|
1215
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
|
1216
|
+
result_sig = Signature_alloc(Secp256k1_Signature_class);
|
|
1217
|
+
CheckedTypedData_Get_Struct(
|
|
1218
|
+
result_sig, Signature, &Signature_DataType, normalized_signature
|
|
1219
|
+
);
|
|
1220
|
+
|
|
1221
|
+
was_normalized = Qfalse;
|
|
1222
|
+
if (secp256k1_ecdsa_signature_normalize(
|
|
1223
|
+
secp256k1_context_static,
|
|
1224
|
+
&(normalized_signature->sig),
|
|
1225
|
+
&(signature->sig)) == 1)
|
|
1226
|
+
{
|
|
1227
|
+
was_normalized = Qtrue;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
RB_GC_GUARD(self);
|
|
1231
|
+
result = rb_ary_new2(2);
|
|
1232
|
+
rb_ary_push(result, was_normalized);
|
|
1233
|
+
rb_ary_push(result, result_sig);
|
|
1234
|
+
|
|
1235
|
+
return result;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* Compares two signatures.
|
|
1240
|
+
*
|
|
1241
|
+
* Two signatures are equal if their compact encodings are identical.
|
|
1242
|
+
*
|
|
1243
|
+
* @param other [Secp256k1::Signature] signature to compare
|
|
1244
|
+
* @return [Boolean] true if signatures match, false otherwise.
|
|
1245
|
+
*/
|
|
1246
|
+
static VALUE
|
|
1247
|
+
Signature_equals(VALUE self, VALUE other)
|
|
1248
|
+
{
|
|
1249
|
+
Signature *lhs;
|
|
1250
|
+
Signature *rhs;
|
|
1251
|
+
unsigned char lhs_compact[64];
|
|
1252
|
+
unsigned char rhs_compact[64];
|
|
1253
|
+
|
|
1254
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, lhs);
|
|
1255
|
+
CheckedTypedData_Get_Struct(other, Signature, &Signature_DataType, rhs);
|
|
1256
|
+
|
|
1257
|
+
secp256k1_ecdsa_signature_serialize_compact(
|
|
1258
|
+
secp256k1_context_static, lhs_compact, &(lhs->sig)
|
|
1259
|
+
);
|
|
1260
|
+
secp256k1_ecdsa_signature_serialize_compact(
|
|
1261
|
+
secp256k1_context_static, rhs_compact, &(rhs->sig)
|
|
1262
|
+
);
|
|
1263
|
+
|
|
1264
|
+
if (memcmp(lhs_compact, rhs_compact, 64) == 0)
|
|
1265
|
+
{
|
|
1266
|
+
return Qtrue;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
return Qfalse;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
//
|
|
1273
|
+
// Secp256k1::RecoverableSignature class interface
|
|
1274
|
+
//
|
|
1275
|
+
|
|
1276
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
1277
|
+
|
|
1278
|
+
static VALUE
|
|
1279
|
+
RecoverableSignature_alloc(VALUE klass)
|
|
1280
|
+
{
|
|
1281
|
+
return rb_data_typed_object_zalloc(klass, sizeof(RecoverableSignature), &RecoverableSignature_DataType);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
* Returns the compact encoding of recoverable signature.
|
|
1286
|
+
*
|
|
1287
|
+
* @return [Array] first element is the 64 byte compact encoding of signature,
|
|
1288
|
+
* the second element is the integer recovery ID.
|
|
1289
|
+
* @raise [Secp256k1::SerializationError] if signature serialization fails.
|
|
1290
|
+
*/
|
|
1291
|
+
static VALUE
|
|
1292
|
+
RecoverableSignature_compact(VALUE self)
|
|
1293
|
+
{
|
|
1294
|
+
RecoverableSignature *recoverable_signature;
|
|
1295
|
+
unsigned char compact_sig[64];
|
|
1296
|
+
int recovery_id;
|
|
1297
|
+
VALUE result;
|
|
1298
|
+
|
|
1299
|
+
CheckedTypedData_Get_Struct(
|
|
1300
|
+
self,
|
|
1301
|
+
RecoverableSignature,
|
|
1302
|
+
&RecoverableSignature_DataType,
|
|
1303
|
+
recoverable_signature
|
|
1304
|
+
);
|
|
1305
|
+
|
|
1306
|
+
if (secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
|
1307
|
+
recoverable_signature->ctx,
|
|
1308
|
+
compact_sig,
|
|
1309
|
+
&recovery_id,
|
|
1310
|
+
&(recoverable_signature->sig)) != 1)
|
|
1311
|
+
{
|
|
1312
|
+
rb_raise(
|
|
1313
|
+
Secp256k1_SerializationError_class,
|
|
1314
|
+
"unable to serialize recoverable signature"
|
|
1315
|
+
);
|
|
1316
|
+
return Qnil;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
// Create a new array with room for 2 elements and push data onto it
|
|
1320
|
+
result = rb_ary_new2(2);
|
|
1321
|
+
rb_ary_push(result, rb_str_new((char*)compact_sig, 64));
|
|
1322
|
+
rb_ary_push(result, rb_int_new(recovery_id));
|
|
1323
|
+
|
|
1324
|
+
return result;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* Convert a recoverable signature to a non-recoverable signature.
|
|
1329
|
+
*
|
|
1330
|
+
* @return [Secp256k1::Signature] non-recoverable signature derived from this
|
|
1331
|
+
* recoverable signature.
|
|
1332
|
+
*/
|
|
1333
|
+
static VALUE
|
|
1334
|
+
RecoverableSignature_to_signature(VALUE self)
|
|
1335
|
+
{
|
|
1336
|
+
RecoverableSignature *recoverable_signature;
|
|
1337
|
+
Signature *signature;
|
|
1338
|
+
VALUE result;
|
|
1339
|
+
|
|
1340
|
+
CheckedTypedData_Get_Struct(
|
|
1341
|
+
self,
|
|
1342
|
+
RecoverableSignature,
|
|
1343
|
+
&RecoverableSignature_DataType,
|
|
1344
|
+
recoverable_signature
|
|
1345
|
+
);
|
|
1346
|
+
|
|
1347
|
+
result = Signature_alloc(Secp256k1_Signature_class);
|
|
1348
|
+
CheckedTypedData_Get_Struct(
|
|
1349
|
+
result,
|
|
1350
|
+
Signature,
|
|
1351
|
+
&Signature_DataType,
|
|
1352
|
+
signature
|
|
1353
|
+
);
|
|
1354
|
+
|
|
1355
|
+
// NOTE: This method cannot fail
|
|
1356
|
+
secp256k1_ecdsa_recoverable_signature_convert(
|
|
1357
|
+
recoverable_signature->ctx,
|
|
1358
|
+
&(signature->sig),
|
|
1359
|
+
&(recoverable_signature->sig));
|
|
1360
|
+
|
|
1361
|
+
RB_GC_GUARD(self);
|
|
1362
|
+
return result;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* Attempts to recover the public key associated with this signature.
|
|
1367
|
+
*
|
|
1368
|
+
* @param in_hash32 [String] 32-byte SHA-256 hash of data.
|
|
1369
|
+
* @return [Secp256k1::PublicKey] recovered public key.
|
|
1370
|
+
* @raise [Secp256k1::Error] if hash given is not 32 bytes.
|
|
1371
|
+
* @raise [Secp256k1::DeserializationError] if public key could not be
|
|
1372
|
+
* recovered.
|
|
1373
|
+
*/
|
|
1374
|
+
static VALUE
|
|
1375
|
+
RecoverableSignature_recover_public_key(VALUE self, VALUE in_hash32)
|
|
1376
|
+
{
|
|
1377
|
+
RecoverableSignature *recoverable_signature;
|
|
1378
|
+
PublicKey *public_key;
|
|
1379
|
+
VALUE result;
|
|
1380
|
+
unsigned char *hash32;
|
|
1381
|
+
|
|
1382
|
+
Check_Type(in_hash32, T_STRING);
|
|
1383
|
+
if (RSTRING_LEN(in_hash32) != 32)
|
|
1384
|
+
{
|
|
1385
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
|
|
1386
|
+
return Qnil;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
CheckedTypedData_Get_Struct(
|
|
1390
|
+
self,
|
|
1391
|
+
RecoverableSignature,
|
|
1392
|
+
&RecoverableSignature_DataType,
|
|
1393
|
+
recoverable_signature
|
|
1394
|
+
);
|
|
1395
|
+
|
|
1396
|
+
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
|
1397
|
+
CheckedTypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
|
1398
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1399
|
+
|
|
1400
|
+
if (secp256k1_ecdsa_recover(recoverable_signature->ctx,
|
|
1401
|
+
&(public_key->pubkey),
|
|
1402
|
+
&(recoverable_signature->sig),
|
|
1403
|
+
hash32) == 1)
|
|
1404
|
+
{
|
|
1405
|
+
RB_GC_GUARD(self);
|
|
1406
|
+
return result;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
NativeValue_invalidate(result);
|
|
1410
|
+
rb_raise(Secp256k1_DeserializationError_class, "unable to recover public key");
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* Compares two recoverable signatures.
|
|
1415
|
+
*
|
|
1416
|
+
* Two recoverable signatures their secp256k1_ecdsa_recoverable_signature data
|
|
1417
|
+
* is identical.
|
|
1418
|
+
*
|
|
1419
|
+
* @param other [Secp256k1::RecoverableSignature] recoverable signature to
|
|
1420
|
+
* compare.
|
|
1421
|
+
* @return [Boolean] true if the recoverable signatures are identical, false
|
|
1422
|
+
* otherwise.
|
|
1423
|
+
*/
|
|
1424
|
+
static VALUE
|
|
1425
|
+
RecoverableSignature_equals(VALUE self, VALUE other)
|
|
1426
|
+
{
|
|
1427
|
+
RecoverableSignature *lhs;
|
|
1428
|
+
RecoverableSignature *rhs;
|
|
1429
|
+
|
|
1430
|
+
CheckedTypedData_Get_Struct(
|
|
1431
|
+
self, RecoverableSignature, &RecoverableSignature_DataType, lhs
|
|
1432
|
+
);
|
|
1433
|
+
CheckedTypedData_Get_Struct(
|
|
1434
|
+
other, RecoverableSignature, &RecoverableSignature_DataType, rhs
|
|
1435
|
+
);
|
|
1436
|
+
|
|
1437
|
+
// NOTE: It is safe to directly compare these data structures rather than
|
|
1438
|
+
// first serializing and then comparing.
|
|
1439
|
+
if (memcmp(&(lhs->sig),
|
|
1440
|
+
&(rhs->sig),
|
|
1441
|
+
sizeof(secp256k1_ecdsa_recoverable_signature)) == 0)
|
|
1442
|
+
{
|
|
1443
|
+
return Qtrue;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
return Qfalse;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
1450
|
+
|
|
1451
|
+
//
|
|
1452
|
+
// Secp256k1::SharedSecret class interface
|
|
1453
|
+
//
|
|
1454
|
+
|
|
1455
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
1456
|
+
|
|
1457
|
+
static VALUE
|
|
1458
|
+
SharedSecret_alloc(VALUE klass)
|
|
1459
|
+
{
|
|
1460
|
+
return rb_data_typed_object_zalloc(klass, sizeof(SharedSecret), &SharedSecret_DataType);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
1464
|
+
|
|
1465
|
+
//
|
|
1466
|
+
// Secp256k1::SchnorrSignature class interface
|
|
1467
|
+
//
|
|
1468
|
+
|
|
1469
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
1470
|
+
|
|
1471
|
+
static VALUE
|
|
1472
|
+
SchnorrSignature_alloc(VALUE klass)
|
|
1473
|
+
{
|
|
1474
|
+
return rb_data_typed_object_zalloc(klass, sizeof(SchnorrSignature), &SchnorrSignature_DataType);
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
static VALUE
|
|
1478
|
+
SchnorrSignature_from_data(VALUE klass, VALUE in_data)
|
|
1479
|
+
{
|
|
1480
|
+
SchnorrSignature* sig;
|
|
1481
|
+
VALUE result;
|
|
1482
|
+
unsigned char* schnorr_data;
|
|
1483
|
+
|
|
1484
|
+
Check_Type(in_data, T_STRING);
|
|
1485
|
+
if (RSTRING_LEN(in_data) != SCHNORR_SIG_SIZE_BYTES)
|
|
1486
|
+
{
|
|
1487
|
+
rb_raise(Secp256k1_DeserializationError_class, "schnorr signature data must be 64 bytes in length");
|
|
1488
|
+
return Qnil;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
result = SchnorrSignature_alloc(Secp256k1_SchnorrSignature_class);
|
|
1492
|
+
CheckedTypedData_Get_Struct(result, SchnorrSignature, &SchnorrSignature_DataType, sig);
|
|
1493
|
+
schnorr_data = (unsigned char*)RSTRING_PTR(in_data);
|
|
1494
|
+
|
|
1495
|
+
memcpy(sig->sig, schnorr_data, SCHNORR_SIG_SIZE_BYTES);
|
|
1496
|
+
|
|
1497
|
+
return result;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
static VALUE
|
|
1501
|
+
SchnorrSignature_serialized(VALUE self)
|
|
1502
|
+
{
|
|
1503
|
+
SchnorrSignature *schnorr_sig;
|
|
1504
|
+
VALUE result;
|
|
1505
|
+
|
|
1506
|
+
CheckedTypedData_Get_Struct(self, SchnorrSignature, &SchnorrSignature_DataType, schnorr_sig);
|
|
1507
|
+
|
|
1508
|
+
result = rb_str_new((char*)schnorr_sig->sig, SCHNORR_SIG_SIZE_BYTES);
|
|
1509
|
+
RB_GC_GUARD(self);
|
|
1510
|
+
return result;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
static VALUE
|
|
1514
|
+
SchnorrSignature_verify(VALUE self, VALUE in_message, VALUE in_xonly_pubkey)
|
|
1515
|
+
{
|
|
1516
|
+
XOnlyPublicKey *xonly_pubkey;
|
|
1517
|
+
SchnorrSignature *schnorr_sig;
|
|
1518
|
+
unsigned char* msg;
|
|
1519
|
+
|
|
1520
|
+
CheckedTypedData_Get_Struct(self, SchnorrSignature, &SchnorrSignature_DataType, schnorr_sig);
|
|
1521
|
+
CheckedTypedData_Get_Struct(in_xonly_pubkey, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
1522
|
+
Check_Type(in_message, T_STRING);
|
|
1523
|
+
|
|
1524
|
+
msg = (unsigned char*)RSTRING_PTR(in_message);
|
|
1525
|
+
if (secp256k1_schnorrsig_verify(secp256k1_context_static, schnorr_sig->sig, msg, RSTRING_LEN(in_message), &xonly_pubkey->pubkey) != 1)
|
|
1526
|
+
{
|
|
1527
|
+
return Qfalse;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
return Qtrue;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
static VALUE
|
|
1534
|
+
SchnorrSignature_equals(VALUE self, VALUE other)
|
|
1535
|
+
{
|
|
1536
|
+
SchnorrSignature *lhs;
|
|
1537
|
+
SchnorrSignature *rhs;
|
|
1538
|
+
|
|
1539
|
+
CheckedTypedData_Get_Struct(self, SchnorrSignature, &SchnorrSignature_DataType, lhs);
|
|
1540
|
+
CheckedTypedData_Get_Struct(other, SchnorrSignature, &SchnorrSignature_DataType, rhs);
|
|
1541
|
+
|
|
1542
|
+
if (memcmp(lhs->sig, rhs->sig, SCHNORR_SIG_SIZE_BYTES) == 0)
|
|
1543
|
+
{
|
|
1544
|
+
return Qtrue;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
return Qfalse;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
1551
|
+
|
|
1552
|
+
//
|
|
1553
|
+
// Secp256k1::Context class interface
|
|
1554
|
+
//
|
|
1555
|
+
|
|
1556
|
+
/* Allocate a new context object */
|
|
1557
|
+
static VALUE
|
|
1558
|
+
Context_alloc(VALUE klass)
|
|
1559
|
+
{
|
|
1560
|
+
return rb_data_typed_object_zalloc(klass, sizeof(Context), &Context_DataType);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Initialize a new context.
|
|
1565
|
+
*
|
|
1566
|
+
* Context initialization should be infrequent as it is an expensive operation.
|
|
1567
|
+
*
|
|
1568
|
+
* @param context_randomization_bytes [String,nil] (Optional) 32 bytes of
|
|
1569
|
+
* random data used to randomize the context. If omitted then the
|
|
1570
|
+
* context remains unrandomized. It is recommended that you provide this
|
|
1571
|
+
* argument.
|
|
1572
|
+
* @return [Secp256k1::Context]
|
|
1573
|
+
* @raise [Secp256k1::Error] if context randomization fails.
|
|
1574
|
+
*/
|
|
1575
|
+
static VALUE
|
|
1576
|
+
Context_initialize(int argc, const VALUE* argv, VALUE self)
|
|
1577
|
+
{
|
|
1578
|
+
Context *context;
|
|
1579
|
+
secp256k1_context *new_context;
|
|
1580
|
+
unsigned char *seed32;
|
|
1581
|
+
VALUE context_randomization_bytes;
|
|
1582
|
+
VALUE opts;
|
|
1583
|
+
static ID kwarg_ids;
|
|
1584
|
+
|
|
1585
|
+
context_randomization_bytes = Qnil;
|
|
1586
|
+
if (!kwarg_ids)
|
|
1587
|
+
{
|
|
1588
|
+
CONST_ID(kwarg_ids, "context_randomization_bytes");
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
rb_check_frozen(self);
|
|
1592
|
+
CheckedTypedData_Get_Struct(self, Context, &Context_DataType, context);
|
|
1593
|
+
if (context->ctx != NULL)
|
|
1594
|
+
{
|
|
1595
|
+
rb_raise(Secp256k1_Error_class, "context is already initialized");
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// Handle optional second argument containing random bytes to use for
|
|
1599
|
+
// randomization. We pass ":" to rb_scan_args to say that we expect keyword
|
|
1600
|
+
// arguments. We then parse the opts result of the scan in order to grab
|
|
1601
|
+
// context_randomization_bytes from the hash.
|
|
1602
|
+
rb_scan_args(argc, argv, ":", &opts);
|
|
1603
|
+
rb_get_kwargs(opts, &kwarg_ids, 0, 1, &context_randomization_bytes);
|
|
1604
|
+
|
|
1605
|
+
// We need this check because rb_get_kwargs will set the result to Qundef if
|
|
1606
|
+
// the keyword argument is not provided. This lets us use the NIL_P
|
|
1607
|
+
// predicate.
|
|
1608
|
+
if (context_randomization_bytes == Qundef)
|
|
1609
|
+
{
|
|
1610
|
+
context_randomization_bytes = Qnil;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
if (!NIL_P(context_randomization_bytes)) // Random bytes given
|
|
1614
|
+
{
|
|
1615
|
+
Check_Type(context_randomization_bytes, T_STRING);
|
|
1616
|
+
if (RSTRING_LEN(context_randomization_bytes) != 32)
|
|
1617
|
+
{
|
|
1618
|
+
rb_raise(
|
|
1619
|
+
Secp256k1_Error_class,
|
|
1620
|
+
"context_randomization_bytes must be 32 bytes in length"
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
new_context = secp256k1_context_create(
|
|
1626
|
+
SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY
|
|
1627
|
+
);
|
|
1628
|
+
|
|
1629
|
+
if (!NIL_P(context_randomization_bytes))
|
|
1630
|
+
{
|
|
1631
|
+
seed32 = (unsigned char*)RSTRING_PTR(context_randomization_bytes);
|
|
1632
|
+
|
|
1633
|
+
// Randomize the context at initialization time rather than before calls so
|
|
1634
|
+
// the same context can be used across threads safely.
|
|
1635
|
+
if (secp256k1_context_randomize(new_context, seed32) != 1)
|
|
1636
|
+
{
|
|
1637
|
+
secp256k1_context_destroy(new_context);
|
|
1638
|
+
rb_raise(
|
|
1639
|
+
Secp256k1_Error_class,
|
|
1640
|
+
"context randomization failed"
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
context->ctx = new_context;
|
|
1646
|
+
return self;
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* Converts binary private key data into a new key pair.
|
|
1651
|
+
*
|
|
1652
|
+
* @param in_private_key_data [String] binary private key data
|
|
1653
|
+
* @return [Secp256k1::KeyPair] key pair initialized from the private key data.
|
|
1654
|
+
* @raise [Secp256k1::Error] if the private key data is invalid or key derivation
|
|
1655
|
+
* fails.
|
|
1656
|
+
*/
|
|
1657
|
+
static VALUE
|
|
1658
|
+
Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
1659
|
+
{
|
|
1660
|
+
Context *context;
|
|
1661
|
+
VALUE result;
|
|
1662
|
+
KeyPair *keypair;
|
|
1663
|
+
unsigned char *private_key_data;
|
|
1664
|
+
|
|
1665
|
+
Check_Type(in_private_key_data, T_STRING);
|
|
1666
|
+
context = Context_get(self);
|
|
1667
|
+
|
|
1668
|
+
if (RSTRING_LEN(in_private_key_data) != 32)
|
|
1669
|
+
{
|
|
1670
|
+
rb_raise(Secp256k1_Error_class, "private key data must be 32 bytes in length");
|
|
1671
|
+
return Qnil;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
result = KeyPair_alloc(Secp256k1_KeyPair_class);
|
|
1675
|
+
CheckedTypedData_Get_Struct(result, KeyPair, &KeyPair_DataType, keypair);
|
|
1676
|
+
|
|
1677
|
+
private_key_data = (unsigned char*)RSTRING_PTR(in_private_key_data);
|
|
1678
|
+
|
|
1679
|
+
if (secp256k1_keypair_create(context->ctx, &keypair->keypair, private_key_data) == 0)
|
|
1680
|
+
{
|
|
1681
|
+
NativeValue_invalidate(result);
|
|
1682
|
+
rb_raise(Secp256k1_Error_class, "invalid secret when attempting to create keypair");
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
RB_GC_GUARD(self);
|
|
1686
|
+
return result;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* Computes the ECDSA signature of the data using the secp256k1 elliptic curve.
|
|
1691
|
+
*
|
|
1692
|
+
* @param in_private_key [Secp256k1::PrivateKey] private key to use for
|
|
1693
|
+
* signing.
|
|
1694
|
+
* @param in_hash32 [String] 32-byte binary string with SHA-256 hash of data.
|
|
1695
|
+
* @return [Secp256k1::Signature] signature resulting from signing data.
|
|
1696
|
+
* @raise [Secp256k1::Error] if hash is not 32-bytes in length or signature
|
|
1697
|
+
* computation fails.
|
|
1698
|
+
*/
|
|
1699
|
+
static VALUE
|
|
1700
|
+
Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1701
|
+
{
|
|
1702
|
+
unsigned char *hash32;
|
|
1703
|
+
PrivateKey *private_key;
|
|
1704
|
+
Context *context;
|
|
1705
|
+
Signature *signature;
|
|
1706
|
+
VALUE signature_result;
|
|
1707
|
+
|
|
1708
|
+
Check_Type(in_hash32, T_STRING);
|
|
1709
|
+
|
|
1710
|
+
if (RSTRING_LEN(in_hash32) != 32)
|
|
1711
|
+
{
|
|
1712
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
|
|
1713
|
+
return Qnil;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
context = Context_get(self);
|
|
1717
|
+
CheckedTypedData_Get_Struct(in_private_key, PrivateKey, &PrivateKey_DataType, private_key);
|
|
1718
|
+
|
|
1719
|
+
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
|
1720
|
+
CheckedTypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
|
1721
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1722
|
+
|
|
1723
|
+
// Attempt to sign the hash of the given data
|
|
1724
|
+
if (SUCCESS(SignData(context->ctx,
|
|
1725
|
+
hash32,
|
|
1726
|
+
private_key->data,
|
|
1727
|
+
&(signature->sig))))
|
|
1728
|
+
{
|
|
1729
|
+
RB_GC_GUARD(self);
|
|
1730
|
+
RB_GC_GUARD(in_private_key);
|
|
1731
|
+
return signature_result;
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
NativeValue_invalidate(signature_result);
|
|
1735
|
+
rb_raise(Secp256k1_Error_class, "unable to compute signature");
|
|
1736
|
+
return Qnil;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
/**
|
|
1740
|
+
* Computes the tagged hash as defined in BIP-340.
|
|
1741
|
+
*
|
|
1742
|
+
* @param in_tag [String] tag value included in the hash.
|
|
1743
|
+
* @param in_message [String] message to be hashed.
|
|
1744
|
+
* @return [String] 32-byte binary hash.
|
|
1745
|
+
*/
|
|
1746
|
+
static VALUE
|
|
1747
|
+
Context_tagged_sha256(VALUE self, VALUE in_tag, VALUE in_message)
|
|
1748
|
+
{
|
|
1749
|
+
Context *context;
|
|
1750
|
+
unsigned char* tag;
|
|
1751
|
+
unsigned char* msg;
|
|
1752
|
+
unsigned char hash32[32];
|
|
1753
|
+
|
|
1754
|
+
Check_Type(in_tag, T_STRING);
|
|
1755
|
+
Check_Type(in_message, T_STRING);
|
|
1756
|
+
|
|
1757
|
+
context = Context_get(self);
|
|
1758
|
+
|
|
1759
|
+
tag = (unsigned char*)RSTRING_PTR(in_tag);
|
|
1760
|
+
msg = (unsigned char*)RSTRING_PTR(in_message);
|
|
1761
|
+
|
|
1762
|
+
if (secp256k1_tagged_sha256(context->ctx, hash32, tag, RSTRING_LEN(in_tag), msg, RSTRING_LEN(in_message)) != 1)
|
|
1763
|
+
{
|
|
1764
|
+
rb_raise(Secp256k1_Error_class, "failed to compute tagged SHA256");
|
|
1765
|
+
return Qnil;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
return rb_str_new((char*)hash32, 32);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
/**
|
|
1772
|
+
* Verifies that signature matches public key and data.
|
|
1773
|
+
*
|
|
1774
|
+
* @param in_signature [Secp256k1::Signature] signature to be verified.
|
|
1775
|
+
* @param in_pubkey [Secp256k1::PublicKey] public key to verify signature
|
|
1776
|
+
* against.
|
|
1777
|
+
* @param in_hash32 [String] 32-byte binary string containing SHA-256 hash of
|
|
1778
|
+
* data.
|
|
1779
|
+
* @return [Boolean] True if the signature is valid, false otherwise.
|
|
1780
|
+
* @raise [Secp256k1::Error] if hash is not 32-bytes in length.
|
|
1781
|
+
*/
|
|
1782
|
+
static VALUE
|
|
1783
|
+
Context_verify(VALUE self, VALUE in_signature, VALUE in_pubkey, VALUE in_hash32)
|
|
1784
|
+
{
|
|
1785
|
+
Context *context;
|
|
1786
|
+
PublicKey *public_key;
|
|
1787
|
+
Signature *signature;
|
|
1788
|
+
unsigned char *hash32;
|
|
1789
|
+
|
|
1790
|
+
Check_Type(in_hash32, T_STRING);
|
|
1791
|
+
|
|
1792
|
+
if (RSTRING_LEN(in_hash32) != 32)
|
|
1793
|
+
{
|
|
1794
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32-bytes in length");
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
context = Context_get(self);
|
|
1798
|
+
CheckedTypedData_Get_Struct(in_pubkey, PublicKey, &PublicKey_DataType, public_key);
|
|
1799
|
+
CheckedTypedData_Get_Struct(in_signature, Signature, &Signature_DataType, signature);
|
|
1800
|
+
|
|
1801
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1802
|
+
|
|
1803
|
+
if (secp256k1_ecdsa_verify(context->ctx,
|
|
1804
|
+
&(signature->sig),
|
|
1805
|
+
hash32,
|
|
1806
|
+
&(public_key->pubkey)) == 1)
|
|
1807
|
+
{
|
|
1808
|
+
return Qtrue;
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
return Qfalse;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
// Context recoverable signature methods
|
|
1815
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
1816
|
+
|
|
1817
|
+
/**
|
|
1818
|
+
* Computes the recoverable ECDSA signature of data signed with private key.
|
|
1819
|
+
*
|
|
1820
|
+
* @param in_private_key [Secp256k1::PrivateKey] private key to sign with.
|
|
1821
|
+
* @param in_hash32 [String] 32-byte binary string with SHA-256 hash of data.
|
|
1822
|
+
* @return [Secp256k1::RecoverableSignature] recoverable signature produced by
|
|
1823
|
+
* signing the SHA-256 hash `in_hash32` with `in_private_key`.
|
|
1824
|
+
* @raise [Secp256k1::Error] if the hash is not 32 bytes or signature could not
|
|
1825
|
+
* be computed.
|
|
1826
|
+
*/
|
|
1827
|
+
static VALUE
|
|
1828
|
+
Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1829
|
+
{
|
|
1830
|
+
Context *context;
|
|
1831
|
+
PrivateKey *private_key;
|
|
1832
|
+
RecoverableSignature *recoverable_signature;
|
|
1833
|
+
unsigned char *hash32;
|
|
1834
|
+
VALUE result;
|
|
1835
|
+
|
|
1836
|
+
Check_Type(in_hash32, T_STRING);
|
|
1837
|
+
if (RSTRING_LEN(in_hash32) != 32)
|
|
1838
|
+
{
|
|
1839
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
|
|
1840
|
+
return Qnil;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
context = Context_get(self);
|
|
1844
|
+
CheckedTypedData_Get_Struct(
|
|
1845
|
+
in_private_key, PrivateKey, &PrivateKey_DataType, private_key
|
|
1846
|
+
);
|
|
1847
|
+
|
|
1848
|
+
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
|
|
1849
|
+
CheckedTypedData_Get_Struct(
|
|
1850
|
+
result,
|
|
1851
|
+
RecoverableSignature,
|
|
1852
|
+
&RecoverableSignature_DataType,
|
|
1853
|
+
recoverable_signature
|
|
1854
|
+
);
|
|
1855
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1856
|
+
|
|
1857
|
+
if (SUCCESS(RecoverableSignData(context->ctx,
|
|
1858
|
+
hash32,
|
|
1859
|
+
private_key->data,
|
|
1860
|
+
&(recoverable_signature->sig))))
|
|
1861
|
+
{
|
|
1862
|
+
recoverable_signature->ctx = secp256k1_context_clone(context->ctx);
|
|
1863
|
+
RB_GC_GUARD(self);
|
|
1864
|
+
RB_GC_GUARD(in_private_key);
|
|
1865
|
+
return result;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
NativeValue_invalidate(result);
|
|
1869
|
+
rb_raise(Secp256k1_Error_class, "unable to compute recoverable signature");
|
|
1870
|
+
return Qnil;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
/**
|
|
1874
|
+
* Loads recoverable signature from compact representation and recovery ID.
|
|
1875
|
+
*
|
|
1876
|
+
* @param in_compact_sig [String] binary string containing compact signature
|
|
1877
|
+
* data.
|
|
1878
|
+
* @param in_recovery_id [Integer] recovery ID (range [0, 3])
|
|
1879
|
+
* @return [Secp256k1::RecoverableSignature] signature parsed from data.
|
|
1880
|
+
* @raise [Secp256k1::DeserializationError] if signature data or recovery ID is
|
|
1881
|
+
* invalid.
|
|
1882
|
+
* @raise [Secp256k1::Error] if compact signature is not 64 bytes or recovery ID
|
|
1883
|
+
* is not in range [0, 3].
|
|
1884
|
+
*/
|
|
1885
|
+
static VALUE
|
|
1886
|
+
Context_recoverable_signature_from_compact(
|
|
1887
|
+
VALUE self, VALUE in_compact_sig, VALUE in_recovery_id)
|
|
1888
|
+
{
|
|
1889
|
+
Context *context;
|
|
1890
|
+
RecoverableSignature *recoverable_signature;
|
|
1891
|
+
unsigned char *compact_sig;
|
|
1892
|
+
int recovery_id;
|
|
1893
|
+
VALUE result;
|
|
1894
|
+
|
|
1895
|
+
Check_Type(in_compact_sig, T_STRING);
|
|
1896
|
+
Check_Type(in_recovery_id, T_FIXNUM);
|
|
1897
|
+
context = Context_get(self);
|
|
1898
|
+
|
|
1899
|
+
recovery_id = FIX2INT(in_recovery_id);
|
|
1900
|
+
|
|
1901
|
+
if (RSTRING_LEN(in_compact_sig) != 64)
|
|
1902
|
+
{
|
|
1903
|
+
rb_raise(Secp256k1_Error_class, "compact signature is not 64 bytes");
|
|
1904
|
+
return Qnil;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
if (recovery_id < 0 || recovery_id > 3)
|
|
1908
|
+
{
|
|
1909
|
+
rb_raise(Secp256k1_Error_class, "invalid recovery ID, must be in range [0, 3]");
|
|
1910
|
+
return Qnil;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
|
|
1914
|
+
CheckedTypedData_Get_Struct(
|
|
1915
|
+
result,
|
|
1916
|
+
RecoverableSignature,
|
|
1917
|
+
&RecoverableSignature_DataType,
|
|
1918
|
+
recoverable_signature
|
|
1919
|
+
);
|
|
1920
|
+
compact_sig = (unsigned char*)RSTRING_PTR(in_compact_sig);
|
|
1921
|
+
|
|
1922
|
+
if (secp256k1_ecdsa_recoverable_signature_parse_compact(
|
|
1923
|
+
context->ctx,
|
|
1924
|
+
&(recoverable_signature->sig),
|
|
1925
|
+
compact_sig,
|
|
1926
|
+
recovery_id) == 1)
|
|
1927
|
+
{
|
|
1928
|
+
recoverable_signature->ctx = secp256k1_context_clone(context->ctx);
|
|
1929
|
+
RB_GC_GUARD(self);
|
|
1930
|
+
return result;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
NativeValue_invalidate(result);
|
|
1934
|
+
rb_raise(Secp256k1_DeserializationError_class, "unable to parse recoverable signature");
|
|
1935
|
+
return Qnil;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
1939
|
+
|
|
1940
|
+
// Context EC Diffie-Hellman methods
|
|
1941
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
1942
|
+
|
|
1943
|
+
/**
|
|
1944
|
+
* Compute EC Diffie-Hellman secret in constant time.
|
|
1945
|
+
*
|
|
1946
|
+
* Creates a new shared secret from public_key and private_key.
|
|
1947
|
+
*
|
|
1948
|
+
* @param point [Secp256k1::PublicKey] public-key representing ECDH point.
|
|
1949
|
+
* @param scalar [Secp256k1::PrivateKey] private-key representing ECDH scalar.
|
|
1950
|
+
* @return [Secp256k1::SharedSecret] shared secret
|
|
1951
|
+
* @raise [Secp256k1::Error] If scalar was invalid (zero or caused overflow).
|
|
1952
|
+
*/
|
|
1953
|
+
static VALUE
|
|
1954
|
+
Context_ecdh(VALUE self, VALUE point, VALUE scalar)
|
|
1955
|
+
{
|
|
1956
|
+
Context *context;
|
|
1957
|
+
PublicKey *public_key;
|
|
1958
|
+
PrivateKey *private_key;
|
|
1959
|
+
SharedSecret *shared_secret;
|
|
1960
|
+
VALUE result;
|
|
1961
|
+
|
|
1962
|
+
context = Context_get(self);
|
|
1963
|
+
CheckedTypedData_Get_Struct(point, PublicKey, &PublicKey_DataType, public_key);
|
|
1964
|
+
CheckedTypedData_Get_Struct(scalar, PrivateKey, &PrivateKey_DataType, private_key);
|
|
1965
|
+
|
|
1966
|
+
result = SharedSecret_alloc(Secp256k1_SharedSecret_class);
|
|
1967
|
+
CheckedTypedData_Get_Struct(
|
|
1968
|
+
result, SharedSecret, &SharedSecret_DataType, shared_secret
|
|
1969
|
+
);
|
|
1970
|
+
|
|
1971
|
+
if (secp256k1_ecdh(context->ctx,
|
|
1972
|
+
shared_secret->data,
|
|
1973
|
+
&(public_key->pubkey),
|
|
1974
|
+
(unsigned char*)private_key->data,
|
|
1975
|
+
NULL,
|
|
1976
|
+
NULL) != 1)
|
|
1977
|
+
{
|
|
1978
|
+
NativeValue_invalidate(result);
|
|
1979
|
+
rb_raise(Secp256k1_Error_class, "invalid scalar provided to ecdh");
|
|
1980
|
+
return Qnil;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
rb_iv_set(result, "@data", rb_str_new((char*)shared_secret->data, 32));
|
|
1984
|
+
|
|
1985
|
+
RB_GC_GUARD(self);
|
|
1986
|
+
RB_GC_GUARD(point);
|
|
1987
|
+
RB_GC_GUARD(scalar);
|
|
1988
|
+
return result;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
1992
|
+
|
|
1993
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
1994
|
+
|
|
1995
|
+
static VALUE
|
|
1996
|
+
Context_sign_schnorr_custom(VALUE self, VALUE in_keypair, VALUE in_message, VALUE in_auxrand)
|
|
1997
|
+
{
|
|
1998
|
+
Context* context;
|
|
1999
|
+
KeyPair* keypair;
|
|
2000
|
+
SchnorrSignature* schnorr_sig;
|
|
2001
|
+
unsigned char* msg;
|
|
2002
|
+
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
|
|
2003
|
+
unsigned char sig[64];
|
|
2004
|
+
VALUE result;
|
|
2005
|
+
|
|
2006
|
+
context = Context_get(self);
|
|
2007
|
+
CheckedTypedData_Get_Struct(in_keypair, KeyPair, &KeyPair_DataType, keypair);
|
|
2008
|
+
|
|
2009
|
+
Check_Type(in_message, T_STRING);
|
|
2010
|
+
|
|
2011
|
+
if (!NIL_P(in_auxrand))
|
|
2012
|
+
{
|
|
2013
|
+
Check_Type(in_auxrand, T_STRING);
|
|
2014
|
+
if (RSTRING_LEN(in_auxrand) != 32)
|
|
2015
|
+
{
|
|
2016
|
+
rb_raise(Secp256k1_Error_class, "schnorr signing auxrand must be 32-bytes in length");
|
|
2017
|
+
return Qnil;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
msg = (unsigned char*)RSTRING_PTR(in_message);
|
|
2022
|
+
extraparams.ndata = NIL_P(in_auxrand) ? NULL : (void*)RSTRING_PTR(in_auxrand);
|
|
2023
|
+
|
|
2024
|
+
if (secp256k1_schnorrsig_sign_custom(context->ctx, sig, msg, (size_t)RSTRING_LEN(in_message), &keypair->keypair, &extraparams) != 1)
|
|
2025
|
+
{
|
|
2026
|
+
rb_raise(Secp256k1_Error_class, "schnorr signing failed");
|
|
2027
|
+
return Qnil;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
result = SchnorrSignature_alloc(Secp256k1_SchnorrSignature_class);
|
|
2031
|
+
CheckedTypedData_Get_Struct(result, SchnorrSignature, &SchnorrSignature_DataType, schnorr_sig);
|
|
2032
|
+
memcpy(schnorr_sig->sig, sig, SCHNORR_SIG_SIZE_BYTES);
|
|
2033
|
+
|
|
2034
|
+
return result;
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
2038
|
+
|
|
2039
|
+
//
|
|
2040
|
+
/* Keep normal Ruby dup/clone machinery (ivars, subclass hooks, singleton
|
|
2041
|
+
* methods and frozen state), while rejecting direct construction. The VM
|
|
2042
|
+
* allocator exposes no native storage until initialize_copy succeeds. */
|
|
2043
|
+
static VALUE
|
|
2044
|
+
NativeValue_reject_construction(int argc, VALUE *argv, VALUE self)
|
|
2045
|
+
{
|
|
2046
|
+
rb_raise(rb_eTypeError, "use a factory to create native objects");
|
|
2047
|
+
return Qnil;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/* Upstream guarantees its key/signature value structs can be safely copied.
|
|
2051
|
+
* These wrappers contain inline values only; owned pointers need a deep copy. */
|
|
2052
|
+
#define DEFINE_VALUE_COPY(Type) \
|
|
2053
|
+
static VALUE Type##_copy_alloc(VALUE klass) \
|
|
2054
|
+
{ \
|
|
2055
|
+
return TypedData_Wrap_Struct(klass, &Type##_DataType, NULL); \
|
|
2056
|
+
} \
|
|
2057
|
+
static VALUE Type##_initialize_copy(VALUE self, VALUE other) \
|
|
2058
|
+
{ \
|
|
2059
|
+
Type *source; \
|
|
2060
|
+
Type *copy; \
|
|
2061
|
+
if (self == other) { return self; } \
|
|
2062
|
+
rb_obj_init_copy(self, other); \
|
|
2063
|
+
CheckedTypedData_Get_Struct(other, Type, &Type##_DataType, source); \
|
|
2064
|
+
if (rb_check_typeddata(self, &Type##_DataType) != NULL) \
|
|
2065
|
+
{ \
|
|
2066
|
+
rb_raise(Secp256k1_Error_class, "native object is already initialized"); \
|
|
2067
|
+
} \
|
|
2068
|
+
copy = ALLOC(Type); \
|
|
2069
|
+
*copy = *source; \
|
|
2070
|
+
RB_GC_GUARD(other); \
|
|
2071
|
+
RTYPEDDATA_DATA(self) = copy; \
|
|
2072
|
+
return self; \
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
DEFINE_VALUE_COPY(PublicKey)
|
|
2076
|
+
DEFINE_VALUE_COPY(XOnlyPublicKey)
|
|
2077
|
+
DEFINE_VALUE_COPY(PrivateKey)
|
|
2078
|
+
DEFINE_VALUE_COPY(KeyPair)
|
|
2079
|
+
DEFINE_VALUE_COPY(Signature)
|
|
2080
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
2081
|
+
DEFINE_VALUE_COPY(SchnorrSignature)
|
|
2082
|
+
#endif
|
|
2083
|
+
|
|
2084
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
2085
|
+
static VALUE
|
|
2086
|
+
RecoverableSignature_copy_alloc(VALUE klass)
|
|
2087
|
+
{
|
|
2088
|
+
return TypedData_Wrap_Struct(klass, &RecoverableSignature_DataType, NULL);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
static VALUE
|
|
2092
|
+
RecoverableSignature_initialize_copy(VALUE self, VALUE other)
|
|
2093
|
+
{
|
|
2094
|
+
RecoverableSignature *source;
|
|
2095
|
+
RecoverableSignature *copy;
|
|
2096
|
+
if (self == other) { return self; }
|
|
2097
|
+
rb_obj_init_copy(self, other);
|
|
2098
|
+
CheckedTypedData_Get_Struct(other, RecoverableSignature, &RecoverableSignature_DataType, source);
|
|
2099
|
+
if (rb_check_typeddata(self, &RecoverableSignature_DataType) != NULL)
|
|
2100
|
+
{
|
|
2101
|
+
rb_raise(Secp256k1_Error_class, "native object is already initialized");
|
|
2102
|
+
}
|
|
2103
|
+
copy = ALLOC(RecoverableSignature);
|
|
2104
|
+
copy->sig = source->sig;
|
|
2105
|
+
copy->ctx = secp256k1_context_clone(source->ctx);
|
|
2106
|
+
RB_GC_GUARD(other);
|
|
2107
|
+
RTYPEDDATA_DATA(self) = copy;
|
|
2108
|
+
return self;
|
|
2109
|
+
}
|
|
2110
|
+
#endif
|
|
2111
|
+
|
|
2112
|
+
#define ENABLE_VALUE_COPY(Type) \
|
|
2113
|
+
rb_define_alloc_func(Secp256k1_##Type##_class, Type##_copy_alloc); \
|
|
2114
|
+
rb_define_singleton_method(Secp256k1_##Type##_class, "allocate", NativeValue_reject_construction, -1); \
|
|
2115
|
+
rb_define_method(Secp256k1_##Type##_class, "initialize", NativeValue_reject_construction, -1); \
|
|
2116
|
+
rb_define_method(Secp256k1_##Type##_class, "initialize_copy", Type##_initialize_copy, 1)
|
|
2117
|
+
|
|
2118
|
+
// Secp256k1 module methods
|
|
2119
|
+
//
|
|
2120
|
+
|
|
2121
|
+
/**
|
|
2122
|
+
* Indicates whether or not the libsecp256k1 recovery module is installed.
|
|
2123
|
+
*
|
|
2124
|
+
* @return [Boolean] true if libsecp256k1 was built with the recovery module,
|
|
2125
|
+
* false otherwise.
|
|
2126
|
+
*/
|
|
2127
|
+
static VALUE
|
|
2128
|
+
Secp256k1_have_recovery(VALUE module)
|
|
2129
|
+
{
|
|
2130
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
2131
|
+
return Qtrue;
|
|
2132
|
+
#else // HAVE_SECP256K1_RECOVERY_H
|
|
2133
|
+
return Qfalse;
|
|
2134
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
/**
|
|
2138
|
+
* Indicates whether or not libsecp256k1 EC Diffie-Hellman module is installed.
|
|
2139
|
+
*
|
|
2140
|
+
* @return [Boolean] true if libsecp256k1 was build with the ECDH module, false
|
|
2141
|
+
* otherwise.
|
|
2142
|
+
*/
|
|
2143
|
+
static VALUE
|
|
2144
|
+
Secp256k1_have_ecdh(VALUE module)
|
|
2145
|
+
{
|
|
2146
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
2147
|
+
return Qtrue;
|
|
2148
|
+
#else // HAVE_SECP256K1_ECDH_H
|
|
2149
|
+
return Qfalse;
|
|
2150
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
/**
|
|
2154
|
+
* Indicates whether or not libsecp256k1 Schnorr signature module is installed.
|
|
2155
|
+
*
|
|
2156
|
+
* @return [Boolean]
|
|
2157
|
+
*/
|
|
2158
|
+
static VALUE
|
|
2159
|
+
Secp256k1_have_schnorr(VALUE module)
|
|
2160
|
+
{
|
|
2161
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
2162
|
+
return Qtrue;
|
|
2163
|
+
#else
|
|
2164
|
+
return Qfalse;
|
|
2165
|
+
#endif
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
//
|
|
2169
|
+
// Library initialization
|
|
2170
|
+
//
|
|
2171
|
+
|
|
2172
|
+
void Init_rbsecp256k1(void)
|
|
2173
|
+
{
|
|
2174
|
+
// Perform selftest to ensure secp256k1_context_static is valid. This will
|
|
2175
|
+
// cause the program to abort if the selftest fails.
|
|
2176
|
+
secp256k1_selftest();
|
|
2177
|
+
|
|
2178
|
+
// Secp256k1
|
|
2179
|
+
Secp256k1_module = rb_define_module("Secp256k1");
|
|
2180
|
+
rb_define_singleton_method(
|
|
2181
|
+
Secp256k1_module,
|
|
2182
|
+
"have_recovery?",
|
|
2183
|
+
Secp256k1_have_recovery,
|
|
2184
|
+
0
|
|
2185
|
+
);
|
|
2186
|
+
rb_define_singleton_method(
|
|
2187
|
+
Secp256k1_module,
|
|
2188
|
+
"have_ecdh?",
|
|
2189
|
+
Secp256k1_have_ecdh,
|
|
2190
|
+
0
|
|
2191
|
+
);
|
|
2192
|
+
rb_define_singleton_method(
|
|
2193
|
+
Secp256k1_module,
|
|
2194
|
+
"have_schnorr?",
|
|
2195
|
+
Secp256k1_have_schnorr,
|
|
2196
|
+
0
|
|
2197
|
+
);
|
|
2198
|
+
|
|
2199
|
+
// Secp256k1 exception hierarchy
|
|
2200
|
+
Secp256k1_Error_class = rb_define_class_under(
|
|
2201
|
+
Secp256k1_module, "Error", rb_eStandardError
|
|
2202
|
+
);
|
|
2203
|
+
Secp256k1_SerializationError_class = rb_define_class_under(
|
|
2204
|
+
Secp256k1_module, "SerializationError", Secp256k1_Error_class
|
|
2205
|
+
);
|
|
2206
|
+
Secp256k1_DeserializationError_class = rb_define_class_under(
|
|
2207
|
+
Secp256k1_module, "DeserializationError", Secp256k1_Error_class
|
|
2208
|
+
);
|
|
2209
|
+
|
|
2210
|
+
// Secp256k1::Context
|
|
2211
|
+
Secp256k1_Context_class = rb_define_class_under(
|
|
2212
|
+
Secp256k1_module, "Context", rb_cObject
|
|
2213
|
+
);
|
|
2214
|
+
rb_undef_alloc_func(Secp256k1_Context_class);
|
|
2215
|
+
rb_define_alloc_func(Secp256k1_Context_class, Context_alloc);
|
|
2216
|
+
rb_define_method(Secp256k1_Context_class, "initialize_copy", Context_initialize_copy, 1);
|
|
2217
|
+
rb_define_method(Secp256k1_Context_class,
|
|
2218
|
+
"initialize",
|
|
2219
|
+
Context_initialize,
|
|
2220
|
+
-1);
|
|
2221
|
+
rb_define_method(Secp256k1_Context_class,
|
|
2222
|
+
"key_pair_from_private_key",
|
|
2223
|
+
Context_key_pair_from_private_key,
|
|
2224
|
+
1);
|
|
2225
|
+
rb_define_method(Secp256k1_Context_class,
|
|
2226
|
+
"sign",
|
|
2227
|
+
Context_sign,
|
|
2228
|
+
2);
|
|
2229
|
+
rb_define_method(Secp256k1_Context_class,
|
|
2230
|
+
"tagged_sha256",
|
|
2231
|
+
Context_tagged_sha256,
|
|
2232
|
+
2);
|
|
2233
|
+
rb_define_method(Secp256k1_Context_class,
|
|
2234
|
+
"verify",
|
|
2235
|
+
Context_verify,
|
|
2236
|
+
3);
|
|
2237
|
+
|
|
2238
|
+
// Factories wrap initialized storage directly. Copy allocators create empty,
|
|
2239
|
+
// checked shells for Ruby dup/clone; direct construction is rejected.
|
|
2240
|
+
// Secp256k1::KeyPair
|
|
2241
|
+
Secp256k1_KeyPair_class = rb_define_class_under(Secp256k1_module,
|
|
2242
|
+
"KeyPair",
|
|
2243
|
+
rb_cObject);
|
|
2244
|
+
ENABLE_VALUE_COPY(KeyPair);
|
|
2245
|
+
rb_define_method(Secp256k1_KeyPair_class, "public_key", KeyPair_public_key, 0);
|
|
2246
|
+
rb_define_method(Secp256k1_KeyPair_class, "private_key", KeyPair_private_key, 0);
|
|
2247
|
+
rb_define_method(Secp256k1_KeyPair_class, "xonly_public_key", KeyPair_xonly_public_key, 0);
|
|
2248
|
+
rb_define_method(Secp256k1_KeyPair_class, "==", KeyPair_equals, 1);
|
|
2249
|
+
|
|
2250
|
+
// Secp256k1::PublicKey
|
|
2251
|
+
Secp256k1_PublicKey_class = rb_define_class_under(Secp256k1_module,
|
|
2252
|
+
"PublicKey",
|
|
2253
|
+
rb_cObject);
|
|
2254
|
+
ENABLE_VALUE_COPY(PublicKey);
|
|
2255
|
+
rb_define_method(Secp256k1_PublicKey_class,
|
|
2256
|
+
"compressed",
|
|
2257
|
+
PublicKey_compressed,
|
|
2258
|
+
0);
|
|
2259
|
+
rb_define_method(Secp256k1_PublicKey_class,
|
|
2260
|
+
"uncompressed",
|
|
2261
|
+
PublicKey_uncompressed,
|
|
2262
|
+
0);
|
|
2263
|
+
rb_define_method(Secp256k1_PublicKey_class,
|
|
2264
|
+
"to_xonly",
|
|
2265
|
+
PublicKey_to_xonly,
|
|
2266
|
+
0);
|
|
2267
|
+
rb_define_singleton_method(
|
|
2268
|
+
Secp256k1_PublicKey_class,
|
|
2269
|
+
"from_data",
|
|
2270
|
+
PublicKey_from_data,
|
|
2271
|
+
1
|
|
2272
|
+
);
|
|
2273
|
+
rb_define_method(Secp256k1_PublicKey_class, "==", PublicKey_equals, 1);
|
|
2274
|
+
|
|
2275
|
+
// Secp256k1::XOnlyPublicKey
|
|
2276
|
+
Secp256k1_XOnlyPublicKey_class = rb_define_class_under(Secp256k1_module,
|
|
2277
|
+
"XOnlyPublicKey",
|
|
2278
|
+
rb_cObject);
|
|
2279
|
+
|
|
2280
|
+
ENABLE_VALUE_COPY(XOnlyPublicKey);
|
|
2281
|
+
rb_define_method(Secp256k1_XOnlyPublicKey_class,
|
|
2282
|
+
"serialized",
|
|
2283
|
+
XOnlyPublicKey_serialized,
|
|
2284
|
+
0);
|
|
2285
|
+
rb_define_singleton_method(
|
|
2286
|
+
Secp256k1_XOnlyPublicKey_class,
|
|
2287
|
+
"from_data",
|
|
2288
|
+
XOnlyPublicKey_from_data,
|
|
2289
|
+
1);
|
|
2290
|
+
rb_define_method(Secp256k1_XOnlyPublicKey_class, "==", XOnlyPublicKey_equals, 1);
|
|
2291
|
+
|
|
2292
|
+
// Secp256k1::PrivateKey
|
|
2293
|
+
Secp256k1_PrivateKey_class = rb_define_class_under(
|
|
2294
|
+
Secp256k1_module, "PrivateKey", rb_cObject
|
|
2295
|
+
);
|
|
2296
|
+
ENABLE_VALUE_COPY(PrivateKey);
|
|
2297
|
+
rb_define_method(Secp256k1_PrivateKey_class, "data", PrivateKey_data, 0);
|
|
2298
|
+
rb_define_method(Secp256k1_PrivateKey_class, "==", PrivateKey_equals, 1);
|
|
2299
|
+
rb_define_singleton_method(
|
|
2300
|
+
Secp256k1_PrivateKey_class,
|
|
2301
|
+
"from_data",
|
|
2302
|
+
PrivateKey_from_data,
|
|
2303
|
+
1
|
|
2304
|
+
);
|
|
2305
|
+
|
|
2306
|
+
// Secp256k1::Signature
|
|
2307
|
+
Secp256k1_Signature_class = rb_define_class_under(Secp256k1_module,
|
|
2308
|
+
"Signature",
|
|
2309
|
+
rb_cObject);
|
|
2310
|
+
ENABLE_VALUE_COPY(Signature);
|
|
2311
|
+
rb_define_method(Secp256k1_Signature_class,
|
|
2312
|
+
"der_encoded",
|
|
2313
|
+
Signature_der_encoded,
|
|
2314
|
+
0);
|
|
2315
|
+
rb_define_method(Secp256k1_Signature_class,
|
|
2316
|
+
"compact",
|
|
2317
|
+
Signature_compact,
|
|
2318
|
+
0);
|
|
2319
|
+
rb_define_method(Secp256k1_Signature_class,
|
|
2320
|
+
"normalized",
|
|
2321
|
+
Signature_normalized,
|
|
2322
|
+
0);
|
|
2323
|
+
rb_define_method(Secp256k1_Signature_class,
|
|
2324
|
+
"==",
|
|
2325
|
+
Signature_equals,
|
|
2326
|
+
1);
|
|
2327
|
+
rb_define_singleton_method(
|
|
2328
|
+
Secp256k1_Signature_class,
|
|
2329
|
+
"from_compact",
|
|
2330
|
+
Signature_from_compact,
|
|
2331
|
+
1
|
|
2332
|
+
);
|
|
2333
|
+
rb_define_singleton_method(
|
|
2334
|
+
Secp256k1_Signature_class,
|
|
2335
|
+
"from_der_encoded",
|
|
2336
|
+
Signature_from_der_encoded,
|
|
2337
|
+
1
|
|
2338
|
+
);
|
|
2339
|
+
|
|
2340
|
+
#ifdef HAVE_SECP256K1_RECOVERY_H
|
|
2341
|
+
// Secp256k1::RecoverableSignature
|
|
2342
|
+
Secp256k1_RecoverableSignature_class = rb_define_class_under(
|
|
2343
|
+
Secp256k1_module,
|
|
2344
|
+
"RecoverableSignature",
|
|
2345
|
+
rb_cObject
|
|
2346
|
+
);
|
|
2347
|
+
ENABLE_VALUE_COPY(RecoverableSignature);
|
|
2348
|
+
rb_define_method(
|
|
2349
|
+
Secp256k1_RecoverableSignature_class,
|
|
2350
|
+
"compact",
|
|
2351
|
+
RecoverableSignature_compact,
|
|
2352
|
+
0
|
|
2353
|
+
);
|
|
2354
|
+
rb_define_method(
|
|
2355
|
+
Secp256k1_RecoverableSignature_class,
|
|
2356
|
+
"to_signature",
|
|
2357
|
+
RecoverableSignature_to_signature,
|
|
2358
|
+
0
|
|
2359
|
+
);
|
|
2360
|
+
rb_define_method(
|
|
2361
|
+
Secp256k1_RecoverableSignature_class,
|
|
2362
|
+
"recover_public_key",
|
|
2363
|
+
RecoverableSignature_recover_public_key,
|
|
2364
|
+
1
|
|
2365
|
+
);
|
|
2366
|
+
rb_define_method(
|
|
2367
|
+
Secp256k1_RecoverableSignature_class,
|
|
2368
|
+
"==",
|
|
2369
|
+
RecoverableSignature_equals,
|
|
2370
|
+
1
|
|
2371
|
+
);
|
|
2372
|
+
|
|
2373
|
+
// Context recoverable signature methods
|
|
2374
|
+
rb_define_method(
|
|
2375
|
+
Secp256k1_Context_class,
|
|
2376
|
+
"sign_recoverable",
|
|
2377
|
+
Context_sign_recoverable,
|
|
2378
|
+
2
|
|
2379
|
+
);
|
|
2380
|
+
rb_define_method(
|
|
2381
|
+
Secp256k1_Context_class,
|
|
2382
|
+
"recoverable_signature_from_compact",
|
|
2383
|
+
Context_recoverable_signature_from_compact,
|
|
2384
|
+
2
|
|
2385
|
+
);
|
|
2386
|
+
#endif // HAVE_SECP256K1_RECOVERY_H
|
|
2387
|
+
|
|
2388
|
+
#ifdef HAVE_SECP256K1_ECDH_H
|
|
2389
|
+
Secp256k1_SharedSecret_class = rb_define_class_under(
|
|
2390
|
+
Secp256k1_module,
|
|
2391
|
+
"SharedSecret",
|
|
2392
|
+
rb_cObject
|
|
2393
|
+
);
|
|
2394
|
+
rb_undef_alloc_func(Secp256k1_SharedSecret_class);
|
|
2395
|
+
rb_define_attr(Secp256k1_SharedSecret_class, "data", 1, 0);
|
|
2396
|
+
|
|
2397
|
+
// Context EC Diffie-Hellman methods
|
|
2398
|
+
rb_define_method(
|
|
2399
|
+
Secp256k1_Context_class,
|
|
2400
|
+
"ecdh",
|
|
2401
|
+
Context_ecdh,
|
|
2402
|
+
2
|
|
2403
|
+
);
|
|
2404
|
+
#endif // HAVE_SECP256K1_ECDH_H
|
|
2405
|
+
|
|
2406
|
+
#ifdef HAVE_SECP256K1_SCHNORRSIG_H
|
|
2407
|
+
Secp256k1_SchnorrSignature_class = rb_define_class_under(
|
|
2408
|
+
Secp256k1_module,
|
|
2409
|
+
"SchnorrSignature",
|
|
2410
|
+
rb_cObject);
|
|
2411
|
+
ENABLE_VALUE_COPY(SchnorrSignature);
|
|
2412
|
+
rb_define_method(Secp256k1_SchnorrSignature_class, "serialized", SchnorrSignature_serialized, 0);
|
|
2413
|
+
rb_define_method(Secp256k1_SchnorrSignature_class, "verify", SchnorrSignature_verify, 2);
|
|
2414
|
+
rb_define_method(Secp256k1_SchnorrSignature_class, "==", SchnorrSignature_equals, 1);
|
|
2415
|
+
|
|
2416
|
+
rb_define_singleton_method(
|
|
2417
|
+
Secp256k1_SchnorrSignature_class,
|
|
2418
|
+
"from_data",
|
|
2419
|
+
SchnorrSignature_from_data,
|
|
2420
|
+
1
|
|
2421
|
+
);
|
|
2422
|
+
|
|
2423
|
+
rb_define_method(
|
|
2424
|
+
Secp256k1_Context_class,
|
|
2425
|
+
"sign_schnorr_custom",
|
|
2426
|
+
Context_sign_schnorr_custom,
|
|
2427
|
+
3);
|
|
2428
|
+
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
2429
|
+
}
|