rbsecp256k1 6.0.0 → 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 -0
- data/README.md +5 -0
- data/Rakefile +6 -1
- data/documentation/context.md +31 -4
- data/documentation/index.md +14 -1
- data/documentation/key_pair.md +0 -0
- data/documentation/private_key.md +0 -0
- data/documentation/public_key.md +0 -0
- data/documentation/recoverable_signature.md +0 -0
- data/documentation/schnorr_signature.md +5 -1
- data/documentation/secp256k1.md +0 -0
- data/documentation/shared_secret.md +0 -0
- data/documentation/signature.md +0 -0
- data/documentation/util.md +0 -0
- data/documentation/xonly_public_key.md +0 -0
- data/ext/rbsecp256k1/extconf.rb +7 -66
- data/ext/rbsecp256k1/rbsecp256k1.c +424 -239
- data/ext/rbsecp256k1/secp256k1_recipe.rb +76 -0
- data/lib/rbsecp256k1/context.rb +5 -1
- data/lib/rbsecp256k1/util.rb +0 -0
- data/lib/rbsecp256k1/version.rb +1 -1
- data/lib/rbsecp256k1.rb +0 -0
- metadata +72 -13
|
@@ -20,7 +20,10 @@
|
|
|
20
20
|
#endif // HAVE_SECP256K1_EXTRAKEYS_H
|
|
21
21
|
|
|
22
22
|
#include <ruby.h>
|
|
23
|
+
#include <ruby/missing.h>
|
|
24
|
+
#include <string.h>
|
|
23
25
|
#include <secp256k1.h>
|
|
26
|
+
#include <secp256k1_preallocated.h>
|
|
24
27
|
|
|
25
28
|
// Check for optional sub-modules. As a rule any secp256k1 submodule is
|
|
26
29
|
// optional and so should be blocked off using these ifdefs.
|
|
@@ -113,6 +116,39 @@ static VALUE Secp256k1_SharedSecret_class;
|
|
|
113
116
|
static VALUE Secp256k1_SchnorrSignature_class;
|
|
114
117
|
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
115
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
|
+
|
|
116
152
|
// Forward definitions for all structures
|
|
117
153
|
typedef struct Context_dummy {
|
|
118
154
|
secp256k1_context *ctx; // Context used by libsecp256k1 library
|
|
@@ -158,25 +194,77 @@ typedef struct SchnorrSignature_dummy {
|
|
|
158
194
|
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
159
195
|
//
|
|
160
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.
|
|
161
201
|
//
|
|
162
202
|
|
|
163
203
|
// Context
|
|
164
204
|
static void
|
|
165
205
|
Context_free(void* in_context)
|
|
166
206
|
{
|
|
207
|
+
if (in_context == NULL) { return; }
|
|
167
208
|
Context *context;
|
|
168
209
|
context = (Context*)in_context;
|
|
169
|
-
secp256k1_context_destroy(context->ctx);
|
|
210
|
+
if (context->ctx != NULL) { secp256k1_context_destroy(context->ctx); }
|
|
170
211
|
xfree(context);
|
|
171
212
|
}
|
|
172
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
|
+
|
|
173
223
|
static const rb_data_type_t Context_DataType = {
|
|
174
224
|
"Context",
|
|
175
|
-
{ 0, Context_free,
|
|
225
|
+
{ 0, Context_free, Context_memsize },
|
|
176
226
|
0, 0,
|
|
177
227
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
178
228
|
};
|
|
179
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
|
+
|
|
180
268
|
// PublicKey
|
|
181
269
|
static void
|
|
182
270
|
PublicKey_free(void *in_public_key)
|
|
@@ -186,9 +274,15 @@ PublicKey_free(void *in_public_key)
|
|
|
186
274
|
xfree(public_key);
|
|
187
275
|
}
|
|
188
276
|
|
|
277
|
+
static size_t
|
|
278
|
+
PublicKey_memsize(const void *data)
|
|
279
|
+
{
|
|
280
|
+
return data == NULL ? 0 : sizeof(PublicKey);
|
|
281
|
+
}
|
|
282
|
+
|
|
189
283
|
static const rb_data_type_t PublicKey_DataType = {
|
|
190
284
|
"PublicKey",
|
|
191
|
-
{ 0, PublicKey_free,
|
|
285
|
+
{ 0, PublicKey_free, PublicKey_memsize },
|
|
192
286
|
0, 0,
|
|
193
287
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
194
288
|
};
|
|
@@ -202,9 +296,15 @@ XOnlyPublicKey_free(void* in_xonly_pubkey)
|
|
|
202
296
|
xfree(xonly_pubkey);
|
|
203
297
|
}
|
|
204
298
|
|
|
299
|
+
static size_t
|
|
300
|
+
XOnlyPublicKey_memsize(const void *data)
|
|
301
|
+
{
|
|
302
|
+
return data == NULL ? 0 : sizeof(XOnlyPublicKey);
|
|
303
|
+
}
|
|
304
|
+
|
|
205
305
|
static const rb_data_type_t XOnlyPublicKey_DataType = {
|
|
206
306
|
"XOnlyPublicKey",
|
|
207
|
-
{ 0, XOnlyPublicKey_free,
|
|
307
|
+
{ 0, XOnlyPublicKey_free, XOnlyPublicKey_memsize },
|
|
208
308
|
0, 0,
|
|
209
309
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
210
310
|
};
|
|
@@ -213,24 +313,26 @@ static const rb_data_type_t XOnlyPublicKey_DataType = {
|
|
|
213
313
|
static void
|
|
214
314
|
PrivateKey_free(void *in_private_key)
|
|
215
315
|
{
|
|
316
|
+
if (in_private_key == NULL) { return; }
|
|
216
317
|
PrivateKey *private_key;
|
|
217
318
|
private_key = (PrivateKey*)in_private_key;
|
|
218
319
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
*
|
|
223
|
-
* That being said its not clear how much control we actually have over Ruby
|
|
224
|
-
* potentially copying the string version of this private key data.
|
|
225
|
-
*/
|
|
226
|
-
memset(private_key->data, 0, 32);
|
|
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));
|
|
227
323
|
|
|
228
324
|
xfree(private_key);
|
|
229
325
|
}
|
|
230
326
|
|
|
327
|
+
static size_t
|
|
328
|
+
PrivateKey_memsize(const void *data)
|
|
329
|
+
{
|
|
330
|
+
return data == NULL ? 0 : sizeof(PrivateKey);
|
|
331
|
+
}
|
|
332
|
+
|
|
231
333
|
static const rb_data_type_t PrivateKey_DataType = {
|
|
232
334
|
"PrivateKey",
|
|
233
|
-
{ 0, PrivateKey_free,
|
|
335
|
+
{ 0, PrivateKey_free, PrivateKey_memsize },
|
|
234
336
|
0, 0,
|
|
235
337
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
236
338
|
};
|
|
@@ -239,14 +341,22 @@ static const rb_data_type_t PrivateKey_DataType = {
|
|
|
239
341
|
static void
|
|
240
342
|
KeyPair_free(void *in_keypair)
|
|
241
343
|
{
|
|
344
|
+
if (in_keypair == NULL) { return; }
|
|
242
345
|
KeyPair *keypair;
|
|
243
346
|
keypair = (KeyPair*)in_keypair;
|
|
347
|
+
explicit_bzero(keypair, sizeof(*keypair));
|
|
244
348
|
xfree(keypair);
|
|
245
349
|
}
|
|
246
350
|
|
|
351
|
+
static size_t
|
|
352
|
+
KeyPair_memsize(const void *data)
|
|
353
|
+
{
|
|
354
|
+
return data == NULL ? 0 : sizeof(KeyPair);
|
|
355
|
+
}
|
|
356
|
+
|
|
247
357
|
static const rb_data_type_t KeyPair_DataType = {
|
|
248
358
|
"KeyPair",
|
|
249
|
-
{ 0, KeyPair_free,
|
|
359
|
+
{ 0, KeyPair_free, KeyPair_memsize },
|
|
250
360
|
0, 0,
|
|
251
361
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
252
362
|
};
|
|
@@ -259,9 +369,15 @@ Signature_free(void *in_signature)
|
|
|
259
369
|
xfree(signature);
|
|
260
370
|
}
|
|
261
371
|
|
|
372
|
+
static size_t
|
|
373
|
+
Signature_memsize(const void *data)
|
|
374
|
+
{
|
|
375
|
+
return data == NULL ? 0 : sizeof(Signature);
|
|
376
|
+
}
|
|
377
|
+
|
|
262
378
|
static const rb_data_type_t Signature_DataType = {
|
|
263
379
|
"Signature",
|
|
264
|
-
{ 0, Signature_free,
|
|
380
|
+
{ 0, Signature_free, Signature_memsize },
|
|
265
381
|
0, 0,
|
|
266
382
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
267
383
|
};
|
|
@@ -271,17 +387,29 @@ static const rb_data_type_t Signature_DataType = {
|
|
|
271
387
|
static void
|
|
272
388
|
RecoverableSignature_free(void *in_recoverable_signature)
|
|
273
389
|
{
|
|
390
|
+
if (in_recoverable_signature == NULL) { return; }
|
|
274
391
|
RecoverableSignature *recoverable_signature = (
|
|
275
392
|
(RecoverableSignature*)in_recoverable_signature
|
|
276
393
|
);
|
|
277
394
|
|
|
278
|
-
|
|
395
|
+
if (recoverable_signature->ctx != NULL) {
|
|
396
|
+
secp256k1_context_destroy(recoverable_signature->ctx);
|
|
397
|
+
}
|
|
279
398
|
xfree(recoverable_signature);
|
|
280
399
|
}
|
|
281
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
|
+
|
|
282
410
|
static const rb_data_type_t RecoverableSignature_DataType = {
|
|
283
411
|
"RecoverableSignature",
|
|
284
|
-
{ 0, RecoverableSignature_free,
|
|
412
|
+
{ 0, RecoverableSignature_free, RecoverableSignature_memsize },
|
|
285
413
|
0, 0,
|
|
286
414
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
287
415
|
};
|
|
@@ -292,15 +420,23 @@ static const rb_data_type_t RecoverableSignature_DataType = {
|
|
|
292
420
|
static void
|
|
293
421
|
SharedSecret_free(void *in_shared_secret)
|
|
294
422
|
{
|
|
423
|
+
if (in_shared_secret == NULL) { return; }
|
|
295
424
|
SharedSecret *shared_secret;
|
|
296
425
|
|
|
297
426
|
shared_secret = (SharedSecret*)in_shared_secret;
|
|
427
|
+
explicit_bzero(shared_secret->data, sizeof(shared_secret->data));
|
|
298
428
|
xfree(shared_secret);
|
|
299
429
|
}
|
|
300
430
|
|
|
431
|
+
static size_t
|
|
432
|
+
SharedSecret_memsize(const void *data)
|
|
433
|
+
{
|
|
434
|
+
return data == NULL ? 0 : sizeof(SharedSecret);
|
|
435
|
+
}
|
|
436
|
+
|
|
301
437
|
static const rb_data_type_t SharedSecret_DataType = {
|
|
302
438
|
"SharedSecret",
|
|
303
|
-
{ 0, SharedSecret_free,
|
|
439
|
+
{ 0, SharedSecret_free, SharedSecret_memsize },
|
|
304
440
|
0, 0,
|
|
305
441
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
306
442
|
};
|
|
@@ -317,9 +453,15 @@ SchnorrSignature_free(void *in_schnorr_sig)
|
|
|
317
453
|
xfree(schnorr_sig);
|
|
318
454
|
}
|
|
319
455
|
|
|
456
|
+
static size_t
|
|
457
|
+
SchnorrSignature_memsize(const void *data)
|
|
458
|
+
{
|
|
459
|
+
return data == NULL ? 0 : sizeof(SchnorrSignature);
|
|
460
|
+
}
|
|
461
|
+
|
|
320
462
|
static const rb_data_type_t SchnorrSignature_DataType = {
|
|
321
463
|
"SchnorrSignature",
|
|
322
|
-
{ 0, SchnorrSignature_free,
|
|
464
|
+
{ 0, SchnorrSignature_free, SchnorrSignature_memsize },
|
|
323
465
|
0, 0,
|
|
324
466
|
RUBY_TYPED_FREE_IMMEDIATELY
|
|
325
467
|
};
|
|
@@ -419,27 +561,22 @@ RecoverableSignData(secp256k1_context *in_context,
|
|
|
419
561
|
static VALUE
|
|
420
562
|
XOnlyPublicKey_alloc(VALUE klass)
|
|
421
563
|
{
|
|
422
|
-
|
|
423
|
-
XOnlyPublicKey
|
|
424
|
-
|
|
425
|
-
xonly_pubkey = ALLOC(XOnlyPublicKey);
|
|
426
|
-
MEMZERO(xonly_pubkey, XOnlyPublicKey, 1);
|
|
427
|
-
result = TypedData_Wrap_Struct(klass, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
428
|
-
|
|
429
|
-
return result;
|
|
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);
|
|
430
566
|
}
|
|
431
567
|
|
|
432
568
|
static VALUE
|
|
433
|
-
XOnlyPublicKey_create_from_data(
|
|
569
|
+
XOnlyPublicKey_create_from_data(VALUE in_data)
|
|
434
570
|
{
|
|
435
571
|
XOnlyPublicKey *xonly_pubkey;
|
|
436
572
|
VALUE result;
|
|
437
573
|
|
|
438
574
|
result = XOnlyPublicKey_alloc(Secp256k1_XOnlyPublicKey_class);
|
|
439
|
-
|
|
575
|
+
CheckedTypedData_Get_Struct(result, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
440
576
|
|
|
441
|
-
if (secp256k1_xonly_pubkey_parse(secp256k1_context_static, &xonly_pubkey->pubkey,
|
|
577
|
+
if (secp256k1_xonly_pubkey_parse(secp256k1_context_static, &xonly_pubkey->pubkey, (unsigned char*)RSTRING_PTR(in_data)) != 1)
|
|
442
578
|
{
|
|
579
|
+
NativeValue_invalidate(result);
|
|
443
580
|
rb_raise(Secp256k1_DeserializationError_class, "invalid x-only public key data");
|
|
444
581
|
return Qnil;
|
|
445
582
|
}
|
|
@@ -458,8 +595,6 @@ XOnlyPublicKey_create_from_data(unsigned char *in_xonly_pubkey32)
|
|
|
458
595
|
static VALUE
|
|
459
596
|
XOnlyPublicKey_from_data(VALUE klass, VALUE in_xonly_public_key_serialized)
|
|
460
597
|
{
|
|
461
|
-
unsigned char *xonly_pubkey_data;
|
|
462
|
-
|
|
463
598
|
Check_Type(in_xonly_public_key_serialized, T_STRING);
|
|
464
599
|
if (RSTRING_LEN(in_xonly_public_key_serialized) != 32)
|
|
465
600
|
{
|
|
@@ -467,8 +602,7 @@ XOnlyPublicKey_from_data(VALUE klass, VALUE in_xonly_public_key_serialized)
|
|
|
467
602
|
return Qnil;
|
|
468
603
|
}
|
|
469
604
|
|
|
470
|
-
|
|
471
|
-
return XOnlyPublicKey_create_from_data(xonly_pubkey_data);
|
|
605
|
+
return XOnlyPublicKey_create_from_data(in_xonly_public_key_serialized);
|
|
472
606
|
}
|
|
473
607
|
|
|
474
608
|
/**
|
|
@@ -483,7 +617,7 @@ XOnlyPublicKey_serialized(VALUE self)
|
|
|
483
617
|
XOnlyPublicKey* xonly_pubkey;
|
|
484
618
|
unsigned char out[SERIALIZED_XONLY_PUBKEY_SIZE_BYTES];
|
|
485
619
|
|
|
486
|
-
|
|
620
|
+
CheckedTypedData_Get_Struct(self, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
487
621
|
|
|
488
622
|
if (secp256k1_xonly_pubkey_serialize(secp256k1_context_static, out, &xonly_pubkey->pubkey) != 1)
|
|
489
623
|
{
|
|
@@ -506,8 +640,8 @@ XOnlyPublicKey_equals(VALUE self, VALUE other)
|
|
|
506
640
|
XOnlyPublicKey *lhs;
|
|
507
641
|
XOnlyPublicKey *rhs;
|
|
508
642
|
|
|
509
|
-
|
|
510
|
-
|
|
643
|
+
CheckedTypedData_Get_Struct(self, XOnlyPublicKey, &XOnlyPublicKey_DataType, lhs);
|
|
644
|
+
CheckedTypedData_Get_Struct(other, XOnlyPublicKey, &XOnlyPublicKey_DataType, rhs);
|
|
511
645
|
|
|
512
646
|
if (secp256k1_xonly_pubkey_cmp(secp256k1_context_static, &lhs->pubkey, &rhs->pubkey) == 0)
|
|
513
647
|
{
|
|
@@ -524,31 +658,24 @@ XOnlyPublicKey_equals(VALUE self, VALUE other)
|
|
|
524
658
|
static VALUE
|
|
525
659
|
PublicKey_alloc(VALUE klass)
|
|
526
660
|
{
|
|
527
|
-
|
|
528
|
-
PublicKey *public_key;
|
|
529
|
-
|
|
530
|
-
public_key = ALLOC(PublicKey);
|
|
531
|
-
MEMZERO(public_key, PublicKey, 1);
|
|
532
|
-
result = TypedData_Wrap_Struct(klass, &PublicKey_DataType, public_key);
|
|
533
|
-
|
|
534
|
-
return result;
|
|
661
|
+
return rb_data_typed_object_zalloc(klass, sizeof(PublicKey), &PublicKey_DataType);
|
|
535
662
|
}
|
|
536
663
|
|
|
537
664
|
static VALUE
|
|
538
|
-
PublicKey_create_from_data(
|
|
539
|
-
unsigned int in_public_key_data_len)
|
|
665
|
+
PublicKey_create_from_data(VALUE in_data)
|
|
540
666
|
{
|
|
541
667
|
PublicKey *public_key;
|
|
542
668
|
VALUE result;
|
|
543
669
|
|
|
544
670
|
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
|
545
|
-
|
|
671
|
+
CheckedTypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
|
546
672
|
|
|
547
673
|
if (secp256k1_ec_pubkey_parse(secp256k1_context_static,
|
|
548
674
|
&(public_key->pubkey),
|
|
549
|
-
|
|
550
|
-
|
|
675
|
+
(unsigned char*)RSTRING_PTR(in_data),
|
|
676
|
+
(size_t)RSTRING_LEN(in_data)) != 1)
|
|
551
677
|
{
|
|
678
|
+
NativeValue_invalidate(result);
|
|
552
679
|
rb_raise(Secp256k1_DeserializationError_class, "invalid public key data");
|
|
553
680
|
return Qnil;
|
|
554
681
|
}
|
|
@@ -567,15 +694,8 @@ PublicKey_create_from_data(unsigned char *in_public_key_data,
|
|
|
567
694
|
static VALUE
|
|
568
695
|
PublicKey_from_data(VALUE klass, VALUE in_public_key_data)
|
|
569
696
|
{
|
|
570
|
-
unsigned char *public_key_data;
|
|
571
|
-
|
|
572
697
|
Check_Type(in_public_key_data, T_STRING);
|
|
573
|
-
|
|
574
|
-
public_key_data = (unsigned char*)StringValuePtr(in_public_key_data);
|
|
575
|
-
return PublicKey_create_from_data(
|
|
576
|
-
public_key_data,
|
|
577
|
-
(int)RSTRING_LEN(in_public_key_data)
|
|
578
|
-
);
|
|
698
|
+
return PublicKey_create_from_data(in_public_key_data);
|
|
579
699
|
}
|
|
580
700
|
|
|
581
701
|
/**
|
|
@@ -590,7 +710,7 @@ PublicKey_uncompressed(VALUE self)
|
|
|
590
710
|
size_t serialized_pubkey_len = UNCOMPRESSED_PUBKEY_SIZE_BYTES;
|
|
591
711
|
unsigned char serialized_pubkey[UNCOMPRESSED_PUBKEY_SIZE_BYTES];
|
|
592
712
|
|
|
593
|
-
|
|
713
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
|
594
714
|
|
|
595
715
|
secp256k1_ec_pubkey_serialize(secp256k1_context_static,
|
|
596
716
|
serialized_pubkey,
|
|
@@ -613,7 +733,7 @@ PublicKey_compressed(VALUE self)
|
|
|
613
733
|
size_t serialized_pubkey_len = COMPRESSED_PUBKEY_SIZE_BYTES;
|
|
614
734
|
unsigned char serialized_pubkey[COMPRESSED_PUBKEY_SIZE_BYTES];
|
|
615
735
|
|
|
616
|
-
|
|
736
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
|
617
737
|
|
|
618
738
|
secp256k1_ec_pubkey_serialize(secp256k1_context_static,
|
|
619
739
|
serialized_pubkey,
|
|
@@ -636,20 +756,22 @@ PublicKey_to_xonly(VALUE self)
|
|
|
636
756
|
XOnlyPublicKey *xonly_pubkey;
|
|
637
757
|
VALUE result;
|
|
638
758
|
|
|
639
|
-
|
|
759
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
|
640
760
|
|
|
641
761
|
result = XOnlyPublicKey_alloc(Secp256k1_XOnlyPublicKey_class);
|
|
642
|
-
|
|
762
|
+
CheckedTypedData_Get_Struct(result, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
643
763
|
|
|
644
764
|
if (secp256k1_xonly_pubkey_from_pubkey(secp256k1_context_static,
|
|
645
765
|
&xonly_pubkey->pubkey,
|
|
646
766
|
NULL,
|
|
647
767
|
&public_key->pubkey) != 1)
|
|
648
768
|
{
|
|
769
|
+
NativeValue_invalidate(result);
|
|
649
770
|
rb_raise(Secp256k1_Error_class, "failed to convert pubkey to x-only pubkey");
|
|
650
771
|
return Qnil;
|
|
651
772
|
}
|
|
652
773
|
|
|
774
|
+
RB_GC_GUARD(self);
|
|
653
775
|
return result;
|
|
654
776
|
}
|
|
655
777
|
|
|
@@ -674,8 +796,8 @@ PublicKey_equals(VALUE self, VALUE other)
|
|
|
674
796
|
lhs_len = 33;
|
|
675
797
|
rhs_len = 33;
|
|
676
798
|
|
|
677
|
-
|
|
678
|
-
|
|
799
|
+
CheckedTypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, lhs);
|
|
800
|
+
CheckedTypedData_Get_Struct(other, PublicKey, &PublicKey_DataType, rhs);
|
|
679
801
|
|
|
680
802
|
secp256k1_ec_pubkey_serialize(
|
|
681
803
|
secp256k1_context_static,
|
|
@@ -708,33 +830,26 @@ PublicKey_equals(VALUE self, VALUE other)
|
|
|
708
830
|
static VALUE
|
|
709
831
|
PrivateKey_alloc(VALUE klass)
|
|
710
832
|
{
|
|
711
|
-
|
|
712
|
-
PrivateKey *private_key;
|
|
713
|
-
|
|
714
|
-
private_key = ALLOC(PrivateKey);
|
|
715
|
-
MEMZERO(private_key, PrivateKey, 1);
|
|
716
|
-
new_instance = TypedData_Wrap_Struct(klass, &PrivateKey_DataType, private_key);
|
|
717
|
-
|
|
718
|
-
return new_instance;
|
|
833
|
+
return rb_data_typed_object_zalloc(klass, sizeof(PrivateKey), &PrivateKey_DataType);
|
|
719
834
|
}
|
|
720
835
|
|
|
721
836
|
/* Internal-only method for creating a private key from secret data */
|
|
722
837
|
static VALUE
|
|
723
|
-
PrivateKey_create(
|
|
838
|
+
PrivateKey_create(VALUE in_private_key_data)
|
|
724
839
|
{
|
|
725
840
|
PrivateKey *private_key;
|
|
726
841
|
VALUE result;
|
|
727
842
|
|
|
728
843
|
if (secp256k1_ec_seckey_verify(secp256k1_context_static,
|
|
729
|
-
in_private_key_data) != 1)
|
|
844
|
+
(unsigned char*)RSTRING_PTR(in_private_key_data)) != 1)
|
|
730
845
|
{
|
|
731
846
|
rb_raise(Secp256k1_Error_class, "invalid private key data");
|
|
732
847
|
return Qnil;
|
|
733
848
|
}
|
|
734
849
|
|
|
735
850
|
result = PrivateKey_alloc(Secp256k1_PrivateKey_class);
|
|
736
|
-
|
|
737
|
-
MEMCPY(private_key->data, in_private_key_data, char, 32);
|
|
851
|
+
CheckedTypedData_Get_Struct(result, PrivateKey, &PrivateKey_DataType, private_key);
|
|
852
|
+
MEMCPY(private_key->data, RSTRING_PTR(in_private_key_data), char, 32);
|
|
738
853
|
|
|
739
854
|
return result;
|
|
740
855
|
}
|
|
@@ -748,10 +863,13 @@ static VALUE
|
|
|
748
863
|
PrivateKey_data(VALUE self)
|
|
749
864
|
{
|
|
750
865
|
PrivateKey *private_key;
|
|
866
|
+
VALUE result;
|
|
751
867
|
|
|
752
|
-
|
|
868
|
+
CheckedTypedData_Get_Struct(self, PrivateKey, &PrivateKey_DataType, private_key);
|
|
753
869
|
|
|
754
|
-
|
|
870
|
+
result = rb_str_new((char*)private_key->data, 32);
|
|
871
|
+
RB_GC_GUARD(self);
|
|
872
|
+
return result;
|
|
755
873
|
}
|
|
756
874
|
|
|
757
875
|
/**
|
|
@@ -765,8 +883,6 @@ PrivateKey_data(VALUE self)
|
|
|
765
883
|
static VALUE
|
|
766
884
|
PrivateKey_from_data(VALUE klass, VALUE in_private_key_data)
|
|
767
885
|
{
|
|
768
|
-
unsigned char *private_key_data;
|
|
769
|
-
|
|
770
886
|
Check_Type(in_private_key_data, T_STRING);
|
|
771
887
|
if (RSTRING_LEN(in_private_key_data) != 32)
|
|
772
888
|
{
|
|
@@ -777,8 +893,7 @@ PrivateKey_from_data(VALUE klass, VALUE in_private_key_data)
|
|
|
777
893
|
return Qnil;
|
|
778
894
|
}
|
|
779
895
|
|
|
780
|
-
|
|
781
|
-
return PrivateKey_create(private_key_data);
|
|
896
|
+
return PrivateKey_create(in_private_key_data);
|
|
782
897
|
}
|
|
783
898
|
|
|
784
899
|
/**
|
|
@@ -795,8 +910,8 @@ PrivateKey_equals(VALUE self, VALUE other)
|
|
|
795
910
|
PrivateKey *lhs;
|
|
796
911
|
PrivateKey *rhs;
|
|
797
912
|
|
|
798
|
-
|
|
799
|
-
|
|
913
|
+
CheckedTypedData_Get_Struct(self, PrivateKey, &PrivateKey_DataType, lhs);
|
|
914
|
+
CheckedTypedData_Get_Struct(other, PrivateKey, &PrivateKey_DataType, rhs);
|
|
800
915
|
|
|
801
916
|
if (memcmp(lhs->data, rhs->data, 32) == 0)
|
|
802
917
|
{
|
|
@@ -813,11 +928,7 @@ PrivateKey_equals(VALUE self, VALUE other)
|
|
|
813
928
|
static VALUE
|
|
814
929
|
KeyPair_alloc(VALUE klass)
|
|
815
930
|
{
|
|
816
|
-
KeyPair
|
|
817
|
-
|
|
818
|
-
key_pair = ALLOC(KeyPair);
|
|
819
|
-
|
|
820
|
-
return TypedData_Wrap_Struct(klass, &KeyPair_DataType, key_pair);
|
|
931
|
+
return rb_data_typed_object_zalloc(klass, sizeof(KeyPair), &KeyPair_DataType);
|
|
821
932
|
}
|
|
822
933
|
|
|
823
934
|
/**
|
|
@@ -832,17 +943,19 @@ KeyPair_public_key(VALUE self)
|
|
|
832
943
|
VALUE result;
|
|
833
944
|
PublicKey *public_key;
|
|
834
945
|
|
|
835
|
-
|
|
946
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, key_pair);
|
|
836
947
|
|
|
837
948
|
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
|
838
|
-
|
|
949
|
+
CheckedTypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
|
839
950
|
|
|
840
951
|
if (secp256k1_keypair_pub(secp256k1_context_static, &public_key->pubkey, &key_pair->keypair) == 0)
|
|
841
952
|
{
|
|
953
|
+
NativeValue_invalidate(result);
|
|
842
954
|
rb_raise(Secp256k1_Error_class, "failed to derive public key from keypair");
|
|
843
955
|
return Qnil;
|
|
844
956
|
}
|
|
845
957
|
|
|
958
|
+
RB_GC_GUARD(self);
|
|
846
959
|
return result;
|
|
847
960
|
}
|
|
848
961
|
|
|
@@ -859,17 +972,19 @@ KeyPair_xonly_public_key(VALUE self)
|
|
|
859
972
|
VALUE result;
|
|
860
973
|
XOnlyPublicKey *xonly_pubkey;
|
|
861
974
|
|
|
862
|
-
|
|
975
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, key_pair);
|
|
863
976
|
|
|
864
977
|
result = XOnlyPublicKey_alloc(Secp256k1_XOnlyPublicKey_class);
|
|
865
|
-
|
|
978
|
+
CheckedTypedData_Get_Struct(result, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
866
979
|
|
|
867
980
|
if (secp256k1_keypair_xonly_pub(secp256k1_context_static, &xonly_pubkey->pubkey, NULL, &key_pair->keypair) == 0)
|
|
868
981
|
{
|
|
982
|
+
NativeValue_invalidate(result);
|
|
869
983
|
rb_raise(Secp256k1_Error_class, "failed to derive x-only public key from keypair");
|
|
870
984
|
return Qnil;
|
|
871
985
|
}
|
|
872
986
|
|
|
987
|
+
RB_GC_GUARD(self);
|
|
873
988
|
return result;
|
|
874
989
|
}
|
|
875
990
|
|
|
@@ -882,17 +997,31 @@ static VALUE
|
|
|
882
997
|
KeyPair_private_key(VALUE self)
|
|
883
998
|
{
|
|
884
999
|
KeyPair *key_pair;
|
|
885
|
-
|
|
1000
|
+
PrivateKey *private_key;
|
|
1001
|
+
VALUE result;
|
|
886
1002
|
|
|
887
|
-
|
|
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);
|
|
888
1008
|
|
|
889
|
-
if (secp256k1_keypair_sec(secp256k1_context_static,
|
|
1009
|
+
if (secp256k1_keypair_sec(secp256k1_context_static, private_key->data, &key_pair->keypair) == 0)
|
|
890
1010
|
{
|
|
1011
|
+
NativeValue_invalidate(result);
|
|
891
1012
|
rb_raise(Secp256k1_Error_class, "failed to derive private key from keypair");
|
|
892
1013
|
return Qnil;
|
|
893
1014
|
}
|
|
894
1015
|
|
|
895
|
-
|
|
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;
|
|
896
1025
|
}
|
|
897
1026
|
|
|
898
1027
|
/**
|
|
@@ -910,8 +1039,8 @@ KeyPair_equals(VALUE self, VALUE other)
|
|
|
910
1039
|
KeyPair *lhs;
|
|
911
1040
|
KeyPair *rhs;
|
|
912
1041
|
|
|
913
|
-
|
|
914
|
-
|
|
1042
|
+
CheckedTypedData_Get_Struct(self, KeyPair, &KeyPair_DataType, lhs);
|
|
1043
|
+
CheckedTypedData_Get_Struct(other, KeyPair, &KeyPair_DataType, rhs);
|
|
915
1044
|
|
|
916
1045
|
if (memcmp(&lhs->keypair, &rhs->keypair, sizeof(secp256k1_keypair)) == 0)
|
|
917
1046
|
{
|
|
@@ -928,14 +1057,7 @@ KeyPair_equals(VALUE self, VALUE other)
|
|
|
928
1057
|
static VALUE
|
|
929
1058
|
Signature_alloc(VALUE klass)
|
|
930
1059
|
{
|
|
931
|
-
|
|
932
|
-
Signature *signature;
|
|
933
|
-
|
|
934
|
-
signature = ALLOC(Signature);
|
|
935
|
-
MEMZERO(signature, Signature, 1);
|
|
936
|
-
new_instance = TypedData_Wrap_Struct(klass, &Signature_DataType, signature);
|
|
937
|
-
|
|
938
|
-
return new_instance;
|
|
1060
|
+
return rb_data_typed_object_zalloc(klass, sizeof(Signature), &Signature_DataType);
|
|
939
1061
|
}
|
|
940
1062
|
|
|
941
1063
|
/**
|
|
@@ -960,15 +1082,15 @@ Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
|
|
960
1082
|
rb_raise(Secp256k1_Error_class, "compact signature must be 64 bytes");
|
|
961
1083
|
}
|
|
962
1084
|
|
|
963
|
-
signature_data = (unsigned char*)StringValuePtr(in_compact_signature);
|
|
964
|
-
|
|
965
1085
|
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
|
966
|
-
|
|
1086
|
+
CheckedTypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
|
1087
|
+
signature_data = (unsigned char*)RSTRING_PTR(in_compact_signature);
|
|
967
1088
|
|
|
968
1089
|
if (secp256k1_ecdsa_signature_parse_compact(secp256k1_context_static,
|
|
969
1090
|
&(signature->sig),
|
|
970
1091
|
signature_data) != 1)
|
|
971
1092
|
{
|
|
1093
|
+
NativeValue_invalidate(signature_result);
|
|
972
1094
|
rb_raise(Secp256k1_DeserializationError_class, "invalid compact signature");
|
|
973
1095
|
return Qnil;
|
|
974
1096
|
}
|
|
@@ -994,16 +1116,16 @@ Signature_from_der_encoded(VALUE klass, VALUE in_der_encoded_signature)
|
|
|
994
1116
|
|
|
995
1117
|
Check_Type(in_der_encoded_signature, T_STRING);
|
|
996
1118
|
|
|
997
|
-
signature_data = (unsigned char*)StringValuePtr(in_der_encoded_signature);
|
|
998
|
-
|
|
999
1119
|
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
|
1000
|
-
|
|
1120
|
+
CheckedTypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
|
1121
|
+
signature_data = (unsigned char*)RSTRING_PTR(in_der_encoded_signature);
|
|
1001
1122
|
|
|
1002
1123
|
if (secp256k1_ecdsa_signature_parse_der(secp256k1_context_static,
|
|
1003
1124
|
&(signature->sig),
|
|
1004
1125
|
signature_data,
|
|
1005
1126
|
RSTRING_LEN(in_der_encoded_signature)) != 1)
|
|
1006
1127
|
{
|
|
1128
|
+
NativeValue_invalidate(signature_result);
|
|
1007
1129
|
rb_raise(Secp256k1_DeserializationError_class, "invalid DER encoded signature");
|
|
1008
1130
|
return Qnil;
|
|
1009
1131
|
}
|
|
@@ -1021,12 +1143,11 @@ Signature_der_encoded(VALUE self)
|
|
|
1021
1143
|
{
|
|
1022
1144
|
// TODO: Cache value after first computation
|
|
1023
1145
|
Signature *signature;
|
|
1024
|
-
unsigned long der_signature_len;
|
|
1025
1146
|
unsigned char der_signature[72];
|
|
1147
|
+
size_t der_signature_len = sizeof(der_signature);
|
|
1026
1148
|
|
|
1027
|
-
|
|
1149
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
|
1028
1150
|
|
|
1029
|
-
der_signature_len = 72;
|
|
1030
1151
|
if (secp256k1_ecdsa_signature_serialize_der(secp256k1_context_static,
|
|
1031
1152
|
der_signature,
|
|
1032
1153
|
&der_signature_len,
|
|
@@ -1039,7 +1160,8 @@ Signature_der_encoded(VALUE self)
|
|
|
1039
1160
|
return Qnil;
|
|
1040
1161
|
}
|
|
1041
1162
|
|
|
1042
|
-
|
|
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);
|
|
1043
1165
|
}
|
|
1044
1166
|
|
|
1045
1167
|
/**
|
|
@@ -1054,7 +1176,7 @@ Signature_compact(VALUE self)
|
|
|
1054
1176
|
Signature *signature;
|
|
1055
1177
|
unsigned char compact_signature[COMPACT_SIG_SIZE_BYTES];
|
|
1056
1178
|
|
|
1057
|
-
|
|
1179
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
|
1058
1180
|
|
|
1059
1181
|
if (secp256k1_ecdsa_signature_serialize_compact(secp256k1_context_static,
|
|
1060
1182
|
compact_signature,
|
|
@@ -1090,9 +1212,9 @@ Signature_normalized(VALUE self)
|
|
|
1090
1212
|
Signature *signature;
|
|
1091
1213
|
Signature *normalized_signature;
|
|
1092
1214
|
|
|
1093
|
-
|
|
1215
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
|
1094
1216
|
result_sig = Signature_alloc(Secp256k1_Signature_class);
|
|
1095
|
-
|
|
1217
|
+
CheckedTypedData_Get_Struct(
|
|
1096
1218
|
result_sig, Signature, &Signature_DataType, normalized_signature
|
|
1097
1219
|
);
|
|
1098
1220
|
|
|
@@ -1105,6 +1227,7 @@ Signature_normalized(VALUE self)
|
|
|
1105
1227
|
was_normalized = Qtrue;
|
|
1106
1228
|
}
|
|
1107
1229
|
|
|
1230
|
+
RB_GC_GUARD(self);
|
|
1108
1231
|
result = rb_ary_new2(2);
|
|
1109
1232
|
rb_ary_push(result, was_normalized);
|
|
1110
1233
|
rb_ary_push(result, result_sig);
|
|
@@ -1128,8 +1251,8 @@ Signature_equals(VALUE self, VALUE other)
|
|
|
1128
1251
|
unsigned char lhs_compact[64];
|
|
1129
1252
|
unsigned char rhs_compact[64];
|
|
1130
1253
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1254
|
+
CheckedTypedData_Get_Struct(self, Signature, &Signature_DataType, lhs);
|
|
1255
|
+
CheckedTypedData_Get_Struct(other, Signature, &Signature_DataType, rhs);
|
|
1133
1256
|
|
|
1134
1257
|
secp256k1_ecdsa_signature_serialize_compact(
|
|
1135
1258
|
secp256k1_context_static, lhs_compact, &(lhs->sig)
|
|
@@ -1155,16 +1278,7 @@ Signature_equals(VALUE self, VALUE other)
|
|
|
1155
1278
|
static VALUE
|
|
1156
1279
|
RecoverableSignature_alloc(VALUE klass)
|
|
1157
1280
|
{
|
|
1158
|
-
|
|
1159
|
-
RecoverableSignature *recoverable_signature;
|
|
1160
|
-
|
|
1161
|
-
recoverable_signature = ALLOC(RecoverableSignature);
|
|
1162
|
-
MEMZERO(recoverable_signature, RecoverableSignature, 1);
|
|
1163
|
-
new_instance = TypedData_Wrap_Struct(
|
|
1164
|
-
klass, &RecoverableSignature_DataType, recoverable_signature
|
|
1165
|
-
);
|
|
1166
|
-
|
|
1167
|
-
return new_instance;
|
|
1281
|
+
return rb_data_typed_object_zalloc(klass, sizeof(RecoverableSignature), &RecoverableSignature_DataType);
|
|
1168
1282
|
}
|
|
1169
1283
|
|
|
1170
1284
|
/**
|
|
@@ -1182,7 +1296,7 @@ RecoverableSignature_compact(VALUE self)
|
|
|
1182
1296
|
int recovery_id;
|
|
1183
1297
|
VALUE result;
|
|
1184
1298
|
|
|
1185
|
-
|
|
1299
|
+
CheckedTypedData_Get_Struct(
|
|
1186
1300
|
self,
|
|
1187
1301
|
RecoverableSignature,
|
|
1188
1302
|
&RecoverableSignature_DataType,
|
|
@@ -1223,7 +1337,7 @@ RecoverableSignature_to_signature(VALUE self)
|
|
|
1223
1337
|
Signature *signature;
|
|
1224
1338
|
VALUE result;
|
|
1225
1339
|
|
|
1226
|
-
|
|
1340
|
+
CheckedTypedData_Get_Struct(
|
|
1227
1341
|
self,
|
|
1228
1342
|
RecoverableSignature,
|
|
1229
1343
|
&RecoverableSignature_DataType,
|
|
@@ -1231,7 +1345,7 @@ RecoverableSignature_to_signature(VALUE self)
|
|
|
1231
1345
|
);
|
|
1232
1346
|
|
|
1233
1347
|
result = Signature_alloc(Secp256k1_Signature_class);
|
|
1234
|
-
|
|
1348
|
+
CheckedTypedData_Get_Struct(
|
|
1235
1349
|
result,
|
|
1236
1350
|
Signature,
|
|
1237
1351
|
&Signature_DataType,
|
|
@@ -1244,6 +1358,7 @@ RecoverableSignature_to_signature(VALUE self)
|
|
|
1244
1358
|
&(signature->sig),
|
|
1245
1359
|
&(recoverable_signature->sig));
|
|
1246
1360
|
|
|
1361
|
+
RB_GC_GUARD(self);
|
|
1247
1362
|
return result;
|
|
1248
1363
|
}
|
|
1249
1364
|
|
|
@@ -1271,25 +1386,27 @@ RecoverableSignature_recover_public_key(VALUE self, VALUE in_hash32)
|
|
|
1271
1386
|
return Qnil;
|
|
1272
1387
|
}
|
|
1273
1388
|
|
|
1274
|
-
|
|
1389
|
+
CheckedTypedData_Get_Struct(
|
|
1275
1390
|
self,
|
|
1276
1391
|
RecoverableSignature,
|
|
1277
1392
|
&RecoverableSignature_DataType,
|
|
1278
1393
|
recoverable_signature
|
|
1279
1394
|
);
|
|
1280
|
-
hash32 = (unsigned char*)StringValuePtr(in_hash32);
|
|
1281
1395
|
|
|
1282
1396
|
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
|
1283
|
-
|
|
1397
|
+
CheckedTypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
|
1398
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1284
1399
|
|
|
1285
1400
|
if (secp256k1_ecdsa_recover(recoverable_signature->ctx,
|
|
1286
1401
|
&(public_key->pubkey),
|
|
1287
1402
|
&(recoverable_signature->sig),
|
|
1288
1403
|
hash32) == 1)
|
|
1289
1404
|
{
|
|
1405
|
+
RB_GC_GUARD(self);
|
|
1290
1406
|
return result;
|
|
1291
1407
|
}
|
|
1292
1408
|
|
|
1409
|
+
NativeValue_invalidate(result);
|
|
1293
1410
|
rb_raise(Secp256k1_DeserializationError_class, "unable to recover public key");
|
|
1294
1411
|
}
|
|
1295
1412
|
|
|
@@ -1310,10 +1427,10 @@ RecoverableSignature_equals(VALUE self, VALUE other)
|
|
|
1310
1427
|
RecoverableSignature *lhs;
|
|
1311
1428
|
RecoverableSignature *rhs;
|
|
1312
1429
|
|
|
1313
|
-
|
|
1430
|
+
CheckedTypedData_Get_Struct(
|
|
1314
1431
|
self, RecoverableSignature, &RecoverableSignature_DataType, lhs
|
|
1315
1432
|
);
|
|
1316
|
-
|
|
1433
|
+
CheckedTypedData_Get_Struct(
|
|
1317
1434
|
other, RecoverableSignature, &RecoverableSignature_DataType, rhs
|
|
1318
1435
|
);
|
|
1319
1436
|
|
|
@@ -1340,16 +1457,7 @@ RecoverableSignature_equals(VALUE self, VALUE other)
|
|
|
1340
1457
|
static VALUE
|
|
1341
1458
|
SharedSecret_alloc(VALUE klass)
|
|
1342
1459
|
{
|
|
1343
|
-
|
|
1344
|
-
SharedSecret *shared_secret;
|
|
1345
|
-
|
|
1346
|
-
shared_secret = ALLOC(SharedSecret);
|
|
1347
|
-
MEMZERO(shared_secret, SharedSecret, 1);
|
|
1348
|
-
new_instance = TypedData_Wrap_Struct(
|
|
1349
|
-
klass, &SharedSecret_DataType, shared_secret
|
|
1350
|
-
);
|
|
1351
|
-
|
|
1352
|
-
return new_instance;
|
|
1460
|
+
return rb_data_typed_object_zalloc(klass, sizeof(SharedSecret), &SharedSecret_DataType);
|
|
1353
1461
|
}
|
|
1354
1462
|
|
|
1355
1463
|
#endif // HAVE_SECP256K1_ECDH_H
|
|
@@ -1363,14 +1471,7 @@ SharedSecret_alloc(VALUE klass)
|
|
|
1363
1471
|
static VALUE
|
|
1364
1472
|
SchnorrSignature_alloc(VALUE klass)
|
|
1365
1473
|
{
|
|
1366
|
-
|
|
1367
|
-
SchnorrSignature *schnorr_sig;
|
|
1368
|
-
|
|
1369
|
-
schnorr_sig = ALLOC(SchnorrSignature);
|
|
1370
|
-
MEMZERO(schnorr_sig, SchnorrSignature, 1);
|
|
1371
|
-
new_instance = TypedData_Wrap_Struct(klass, &SchnorrSignature_DataType, schnorr_sig);
|
|
1372
|
-
|
|
1373
|
-
return new_instance;
|
|
1474
|
+
return rb_data_typed_object_zalloc(klass, sizeof(SchnorrSignature), &SchnorrSignature_DataType);
|
|
1374
1475
|
}
|
|
1375
1476
|
|
|
1376
1477
|
static VALUE
|
|
@@ -1387,10 +1488,9 @@ SchnorrSignature_from_data(VALUE klass, VALUE in_data)
|
|
|
1387
1488
|
return Qnil;
|
|
1388
1489
|
}
|
|
1389
1490
|
|
|
1390
|
-
schnorr_data = (unsigned char*)StringValuePtr(in_data);
|
|
1391
|
-
|
|
1392
1491
|
result = SchnorrSignature_alloc(Secp256k1_SchnorrSignature_class);
|
|
1393
|
-
|
|
1492
|
+
CheckedTypedData_Get_Struct(result, SchnorrSignature, &SchnorrSignature_DataType, sig);
|
|
1493
|
+
schnorr_data = (unsigned char*)RSTRING_PTR(in_data);
|
|
1394
1494
|
|
|
1395
1495
|
memcpy(sig->sig, schnorr_data, SCHNORR_SIG_SIZE_BYTES);
|
|
1396
1496
|
|
|
@@ -1401,10 +1501,13 @@ static VALUE
|
|
|
1401
1501
|
SchnorrSignature_serialized(VALUE self)
|
|
1402
1502
|
{
|
|
1403
1503
|
SchnorrSignature *schnorr_sig;
|
|
1504
|
+
VALUE result;
|
|
1404
1505
|
|
|
1405
|
-
|
|
1506
|
+
CheckedTypedData_Get_Struct(self, SchnorrSignature, &SchnorrSignature_DataType, schnorr_sig);
|
|
1406
1507
|
|
|
1407
|
-
|
|
1508
|
+
result = rb_str_new((char*)schnorr_sig->sig, SCHNORR_SIG_SIZE_BYTES);
|
|
1509
|
+
RB_GC_GUARD(self);
|
|
1510
|
+
return result;
|
|
1408
1511
|
}
|
|
1409
1512
|
|
|
1410
1513
|
static VALUE
|
|
@@ -1414,11 +1517,11 @@ SchnorrSignature_verify(VALUE self, VALUE in_message, VALUE in_xonly_pubkey)
|
|
|
1414
1517
|
SchnorrSignature *schnorr_sig;
|
|
1415
1518
|
unsigned char* msg;
|
|
1416
1519
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1520
|
+
CheckedTypedData_Get_Struct(self, SchnorrSignature, &SchnorrSignature_DataType, schnorr_sig);
|
|
1521
|
+
CheckedTypedData_Get_Struct(in_xonly_pubkey, XOnlyPublicKey, &XOnlyPublicKey_DataType, xonly_pubkey);
|
|
1419
1522
|
Check_Type(in_message, T_STRING);
|
|
1420
1523
|
|
|
1421
|
-
msg = (unsigned char*)
|
|
1524
|
+
msg = (unsigned char*)RSTRING_PTR(in_message);
|
|
1422
1525
|
if (secp256k1_schnorrsig_verify(secp256k1_context_static, schnorr_sig->sig, msg, RSTRING_LEN(in_message), &xonly_pubkey->pubkey) != 1)
|
|
1423
1526
|
{
|
|
1424
1527
|
return Qfalse;
|
|
@@ -1433,8 +1536,8 @@ SchnorrSignature_equals(VALUE self, VALUE other)
|
|
|
1433
1536
|
SchnorrSignature *lhs;
|
|
1434
1537
|
SchnorrSignature *rhs;
|
|
1435
1538
|
|
|
1436
|
-
|
|
1437
|
-
|
|
1539
|
+
CheckedTypedData_Get_Struct(self, SchnorrSignature, &SchnorrSignature_DataType, lhs);
|
|
1540
|
+
CheckedTypedData_Get_Struct(other, SchnorrSignature, &SchnorrSignature_DataType, rhs);
|
|
1438
1541
|
|
|
1439
1542
|
if (memcmp(lhs->sig, rhs->sig, SCHNORR_SIG_SIZE_BYTES) == 0)
|
|
1440
1543
|
{
|
|
@@ -1454,15 +1557,7 @@ SchnorrSignature_equals(VALUE self, VALUE other)
|
|
|
1454
1557
|
static VALUE
|
|
1455
1558
|
Context_alloc(VALUE klass)
|
|
1456
1559
|
{
|
|
1457
|
-
|
|
1458
|
-
Context *context;
|
|
1459
|
-
|
|
1460
|
-
context = ALLOC(Context);
|
|
1461
|
-
MEMZERO(context, Context, 1);
|
|
1462
|
-
|
|
1463
|
-
new_instance = TypedData_Wrap_Struct(klass, &Context_DataType, context);
|
|
1464
|
-
|
|
1465
|
-
return new_instance;
|
|
1560
|
+
return rb_data_typed_object_zalloc(klass, sizeof(Context), &Context_DataType);
|
|
1466
1561
|
}
|
|
1467
1562
|
|
|
1468
1563
|
/**
|
|
@@ -1481,6 +1576,7 @@ static VALUE
|
|
|
1481
1576
|
Context_initialize(int argc, const VALUE* argv, VALUE self)
|
|
1482
1577
|
{
|
|
1483
1578
|
Context *context;
|
|
1579
|
+
secp256k1_context *new_context;
|
|
1484
1580
|
unsigned char *seed32;
|
|
1485
1581
|
VALUE context_randomization_bytes;
|
|
1486
1582
|
VALUE opts;
|
|
@@ -1492,11 +1588,12 @@ Context_initialize(int argc, const VALUE* argv, VALUE self)
|
|
|
1492
1588
|
CONST_ID(kwarg_ids, "context_randomization_bytes");
|
|
1493
1589
|
}
|
|
1494
1590
|
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
context->ctx
|
|
1498
|
-
|
|
1499
|
-
|
|
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
|
+
}
|
|
1500
1597
|
|
|
1501
1598
|
// Handle optional second argument containing random bytes to use for
|
|
1502
1599
|
// randomization. We pass ":" to rb_scan_args to say that we expect keyword
|
|
@@ -1523,13 +1620,21 @@ Context_initialize(int argc, const VALUE* argv, VALUE self)
|
|
|
1523
1620
|
"context_randomization_bytes must be 32 bytes in length"
|
|
1524
1621
|
);
|
|
1525
1622
|
}
|
|
1623
|
+
}
|
|
1526
1624
|
|
|
1527
|
-
|
|
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);
|
|
1528
1632
|
|
|
1529
1633
|
// Randomize the context at initialization time rather than before calls so
|
|
1530
1634
|
// the same context can be used across threads safely.
|
|
1531
|
-
if (secp256k1_context_randomize(
|
|
1635
|
+
if (secp256k1_context_randomize(new_context, seed32) != 1)
|
|
1532
1636
|
{
|
|
1637
|
+
secp256k1_context_destroy(new_context);
|
|
1533
1638
|
rb_raise(
|
|
1534
1639
|
Secp256k1_Error_class,
|
|
1535
1640
|
"context randomization failed"
|
|
@@ -1537,6 +1642,7 @@ Context_initialize(int argc, const VALUE* argv, VALUE self)
|
|
|
1537
1642
|
}
|
|
1538
1643
|
}
|
|
1539
1644
|
|
|
1645
|
+
context->ctx = new_context;
|
|
1540
1646
|
return self;
|
|
1541
1647
|
}
|
|
1542
1648
|
|
|
@@ -1557,7 +1663,7 @@ Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
|
1557
1663
|
unsigned char *private_key_data;
|
|
1558
1664
|
|
|
1559
1665
|
Check_Type(in_private_key_data, T_STRING);
|
|
1560
|
-
|
|
1666
|
+
context = Context_get(self);
|
|
1561
1667
|
|
|
1562
1668
|
if (RSTRING_LEN(in_private_key_data) != 32)
|
|
1563
1669
|
{
|
|
@@ -1566,15 +1672,17 @@ Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
|
1566
1672
|
}
|
|
1567
1673
|
|
|
1568
1674
|
result = KeyPair_alloc(Secp256k1_KeyPair_class);
|
|
1569
|
-
|
|
1675
|
+
CheckedTypedData_Get_Struct(result, KeyPair, &KeyPair_DataType, keypair);
|
|
1570
1676
|
|
|
1571
|
-
private_key_data = (unsigned char*)
|
|
1677
|
+
private_key_data = (unsigned char*)RSTRING_PTR(in_private_key_data);
|
|
1572
1678
|
|
|
1573
1679
|
if (secp256k1_keypair_create(context->ctx, &keypair->keypair, private_key_data) == 0)
|
|
1574
1680
|
{
|
|
1681
|
+
NativeValue_invalidate(result);
|
|
1575
1682
|
rb_raise(Secp256k1_Error_class, "invalid secret when attempting to create keypair");
|
|
1576
1683
|
}
|
|
1577
1684
|
|
|
1685
|
+
RB_GC_GUARD(self);
|
|
1578
1686
|
return result;
|
|
1579
1687
|
}
|
|
1580
1688
|
|
|
@@ -1605,12 +1713,12 @@ Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
|
1605
1713
|
return Qnil;
|
|
1606
1714
|
}
|
|
1607
1715
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
hash32 = (unsigned char*)StringValuePtr(in_hash32);
|
|
1716
|
+
context = Context_get(self);
|
|
1717
|
+
CheckedTypedData_Get_Struct(in_private_key, PrivateKey, &PrivateKey_DataType, private_key);
|
|
1611
1718
|
|
|
1612
1719
|
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
|
1613
|
-
|
|
1720
|
+
CheckedTypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
|
1721
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1614
1722
|
|
|
1615
1723
|
// Attempt to sign the hash of the given data
|
|
1616
1724
|
if (SUCCESS(SignData(context->ctx,
|
|
@@ -1618,9 +1726,12 @@ Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
|
1618
1726
|
private_key->data,
|
|
1619
1727
|
&(signature->sig))))
|
|
1620
1728
|
{
|
|
1729
|
+
RB_GC_GUARD(self);
|
|
1730
|
+
RB_GC_GUARD(in_private_key);
|
|
1621
1731
|
return signature_result;
|
|
1622
1732
|
}
|
|
1623
1733
|
|
|
1734
|
+
NativeValue_invalidate(signature_result);
|
|
1624
1735
|
rb_raise(Secp256k1_Error_class, "unable to compute signature");
|
|
1625
1736
|
return Qnil;
|
|
1626
1737
|
}
|
|
@@ -1643,10 +1754,10 @@ Context_tagged_sha256(VALUE self, VALUE in_tag, VALUE in_message)
|
|
|
1643
1754
|
Check_Type(in_tag, T_STRING);
|
|
1644
1755
|
Check_Type(in_message, T_STRING);
|
|
1645
1756
|
|
|
1646
|
-
|
|
1757
|
+
context = Context_get(self);
|
|
1647
1758
|
|
|
1648
|
-
tag = (unsigned char*)
|
|
1649
|
-
msg = (unsigned char*)
|
|
1759
|
+
tag = (unsigned char*)RSTRING_PTR(in_tag);
|
|
1760
|
+
msg = (unsigned char*)RSTRING_PTR(in_message);
|
|
1650
1761
|
|
|
1651
1762
|
if (secp256k1_tagged_sha256(context->ctx, hash32, tag, RSTRING_LEN(in_tag), msg, RSTRING_LEN(in_message)) != 1)
|
|
1652
1763
|
{
|
|
@@ -1683,11 +1794,11 @@ Context_verify(VALUE self, VALUE in_signature, VALUE in_pubkey, VALUE in_hash32)
|
|
|
1683
1794
|
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32-bytes in length");
|
|
1684
1795
|
}
|
|
1685
1796
|
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
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);
|
|
1689
1800
|
|
|
1690
|
-
hash32 = (unsigned char*)
|
|
1801
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1691
1802
|
|
|
1692
1803
|
if (secp256k1_ecdsa_verify(context->ctx,
|
|
1693
1804
|
&(signature->sig),
|
|
@@ -1729,19 +1840,19 @@ Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
|
1729
1840
|
return Qnil;
|
|
1730
1841
|
}
|
|
1731
1842
|
|
|
1732
|
-
|
|
1733
|
-
|
|
1843
|
+
context = Context_get(self);
|
|
1844
|
+
CheckedTypedData_Get_Struct(
|
|
1734
1845
|
in_private_key, PrivateKey, &PrivateKey_DataType, private_key
|
|
1735
1846
|
);
|
|
1736
|
-
hash32 = (unsigned char*)StringValuePtr(in_hash32);
|
|
1737
1847
|
|
|
1738
1848
|
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
|
|
1739
|
-
|
|
1849
|
+
CheckedTypedData_Get_Struct(
|
|
1740
1850
|
result,
|
|
1741
1851
|
RecoverableSignature,
|
|
1742
1852
|
&RecoverableSignature_DataType,
|
|
1743
1853
|
recoverable_signature
|
|
1744
1854
|
);
|
|
1855
|
+
hash32 = (unsigned char*)RSTRING_PTR(in_hash32);
|
|
1745
1856
|
|
|
1746
1857
|
if (SUCCESS(RecoverableSignData(context->ctx,
|
|
1747
1858
|
hash32,
|
|
@@ -1749,9 +1860,12 @@ Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
|
1749
1860
|
&(recoverable_signature->sig))))
|
|
1750
1861
|
{
|
|
1751
1862
|
recoverable_signature->ctx = secp256k1_context_clone(context->ctx);
|
|
1863
|
+
RB_GC_GUARD(self);
|
|
1864
|
+
RB_GC_GUARD(in_private_key);
|
|
1752
1865
|
return result;
|
|
1753
1866
|
}
|
|
1754
1867
|
|
|
1868
|
+
NativeValue_invalidate(result);
|
|
1755
1869
|
rb_raise(Secp256k1_Error_class, "unable to compute recoverable signature");
|
|
1756
1870
|
return Qnil;
|
|
1757
1871
|
}
|
|
@@ -1780,9 +1894,8 @@ Context_recoverable_signature_from_compact(
|
|
|
1780
1894
|
|
|
1781
1895
|
Check_Type(in_compact_sig, T_STRING);
|
|
1782
1896
|
Check_Type(in_recovery_id, T_FIXNUM);
|
|
1783
|
-
|
|
1897
|
+
context = Context_get(self);
|
|
1784
1898
|
|
|
1785
|
-
compact_sig = (unsigned char*)StringValuePtr(in_compact_sig);
|
|
1786
1899
|
recovery_id = FIX2INT(in_recovery_id);
|
|
1787
1900
|
|
|
1788
1901
|
if (RSTRING_LEN(in_compact_sig) != 64)
|
|
@@ -1798,12 +1911,13 @@ Context_recoverable_signature_from_compact(
|
|
|
1798
1911
|
}
|
|
1799
1912
|
|
|
1800
1913
|
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
|
|
1801
|
-
|
|
1914
|
+
CheckedTypedData_Get_Struct(
|
|
1802
1915
|
result,
|
|
1803
1916
|
RecoverableSignature,
|
|
1804
1917
|
&RecoverableSignature_DataType,
|
|
1805
1918
|
recoverable_signature
|
|
1806
1919
|
);
|
|
1920
|
+
compact_sig = (unsigned char*)RSTRING_PTR(in_compact_sig);
|
|
1807
1921
|
|
|
1808
1922
|
if (secp256k1_ecdsa_recoverable_signature_parse_compact(
|
|
1809
1923
|
context->ctx,
|
|
@@ -1812,9 +1926,11 @@ Context_recoverable_signature_from_compact(
|
|
|
1812
1926
|
recovery_id) == 1)
|
|
1813
1927
|
{
|
|
1814
1928
|
recoverable_signature->ctx = secp256k1_context_clone(context->ctx);
|
|
1929
|
+
RB_GC_GUARD(self);
|
|
1815
1930
|
return result;
|
|
1816
1931
|
}
|
|
1817
1932
|
|
|
1933
|
+
NativeValue_invalidate(result);
|
|
1818
1934
|
rb_raise(Secp256k1_DeserializationError_class, "unable to parse recoverable signature");
|
|
1819
1935
|
return Qnil;
|
|
1820
1936
|
}
|
|
@@ -1843,12 +1959,12 @@ Context_ecdh(VALUE self, VALUE point, VALUE scalar)
|
|
|
1843
1959
|
SharedSecret *shared_secret;
|
|
1844
1960
|
VALUE result;
|
|
1845
1961
|
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
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);
|
|
1849
1965
|
|
|
1850
1966
|
result = SharedSecret_alloc(Secp256k1_SharedSecret_class);
|
|
1851
|
-
|
|
1967
|
+
CheckedTypedData_Get_Struct(
|
|
1852
1968
|
result, SharedSecret, &SharedSecret_DataType, shared_secret
|
|
1853
1969
|
);
|
|
1854
1970
|
|
|
@@ -1859,12 +1975,16 @@ Context_ecdh(VALUE self, VALUE point, VALUE scalar)
|
|
|
1859
1975
|
NULL,
|
|
1860
1976
|
NULL) != 1)
|
|
1861
1977
|
{
|
|
1978
|
+
NativeValue_invalidate(result);
|
|
1862
1979
|
rb_raise(Secp256k1_Error_class, "invalid scalar provided to ecdh");
|
|
1863
1980
|
return Qnil;
|
|
1864
1981
|
}
|
|
1865
1982
|
|
|
1866
1983
|
rb_iv_set(result, "@data", rb_str_new((char*)shared_secret->data, 32));
|
|
1867
1984
|
|
|
1985
|
+
RB_GC_GUARD(self);
|
|
1986
|
+
RB_GC_GUARD(point);
|
|
1987
|
+
RB_GC_GUARD(scalar);
|
|
1868
1988
|
return result;
|
|
1869
1989
|
}
|
|
1870
1990
|
|
|
@@ -1879,19 +1999,14 @@ Context_sign_schnorr_custom(VALUE self, VALUE in_keypair, VALUE in_message, VALU
|
|
|
1879
1999
|
KeyPair* keypair;
|
|
1880
2000
|
SchnorrSignature* schnorr_sig;
|
|
1881
2001
|
unsigned char* msg;
|
|
1882
|
-
|
|
2002
|
+
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
|
|
1883
2003
|
unsigned char sig[64];
|
|
1884
2004
|
VALUE result;
|
|
1885
2005
|
|
|
1886
|
-
|
|
1887
|
-
|
|
2006
|
+
context = Context_get(self);
|
|
2007
|
+
CheckedTypedData_Get_Struct(in_keypair, KeyPair, &KeyPair_DataType, keypair);
|
|
1888
2008
|
|
|
1889
2009
|
Check_Type(in_message, T_STRING);
|
|
1890
|
-
if (RSTRING_LEN(in_message) != 32)
|
|
1891
|
-
{
|
|
1892
|
-
rb_raise(Secp256k1_Error_class, "schnorr signing message must be 32-bytes in length");
|
|
1893
|
-
return Qnil;
|
|
1894
|
-
}
|
|
1895
2010
|
|
|
1896
2011
|
if (!NIL_P(in_auxrand))
|
|
1897
2012
|
{
|
|
@@ -1903,17 +2018,17 @@ Context_sign_schnorr_custom(VALUE self, VALUE in_keypair, VALUE in_message, VALU
|
|
|
1903
2018
|
}
|
|
1904
2019
|
}
|
|
1905
2020
|
|
|
1906
|
-
msg = (unsigned char*)
|
|
1907
|
-
|
|
2021
|
+
msg = (unsigned char*)RSTRING_PTR(in_message);
|
|
2022
|
+
extraparams.ndata = NIL_P(in_auxrand) ? NULL : (void*)RSTRING_PTR(in_auxrand);
|
|
1908
2023
|
|
|
1909
|
-
if (
|
|
2024
|
+
if (secp256k1_schnorrsig_sign_custom(context->ctx, sig, msg, (size_t)RSTRING_LEN(in_message), &keypair->keypair, &extraparams) != 1)
|
|
1910
2025
|
{
|
|
1911
2026
|
rb_raise(Secp256k1_Error_class, "schnorr signing failed");
|
|
1912
2027
|
return Qnil;
|
|
1913
2028
|
}
|
|
1914
2029
|
|
|
1915
2030
|
result = SchnorrSignature_alloc(Secp256k1_SchnorrSignature_class);
|
|
1916
|
-
|
|
2031
|
+
CheckedTypedData_Get_Struct(result, SchnorrSignature, &SchnorrSignature_DataType, schnorr_sig);
|
|
1917
2032
|
memcpy(schnorr_sig->sig, sig, SCHNORR_SIG_SIZE_BYTES);
|
|
1918
2033
|
|
|
1919
2034
|
return result;
|
|
@@ -1922,6 +2037,84 @@ Context_sign_schnorr_custom(VALUE self, VALUE in_keypair, VALUE in_message, VALU
|
|
|
1922
2037
|
#endif // HAVE_SECP256K1_SCHNORRSIG_H
|
|
1923
2038
|
|
|
1924
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
|
+
|
|
1925
2118
|
// Secp256k1 module methods
|
|
1926
2119
|
//
|
|
1927
2120
|
|
|
@@ -2020,6 +2213,7 @@ void Init_rbsecp256k1(void)
|
|
|
2020
2213
|
);
|
|
2021
2214
|
rb_undef_alloc_func(Secp256k1_Context_class);
|
|
2022
2215
|
rb_define_alloc_func(Secp256k1_Context_class, Context_alloc);
|
|
2216
|
+
rb_define_method(Secp256k1_Context_class, "initialize_copy", Context_initialize_copy, 1);
|
|
2023
2217
|
rb_define_method(Secp256k1_Context_class,
|
|
2024
2218
|
"initialize",
|
|
2025
2219
|
Context_initialize,
|
|
@@ -2041,12 +2235,13 @@ void Init_rbsecp256k1(void)
|
|
|
2041
2235
|
Context_verify,
|
|
2042
2236
|
3);
|
|
2043
2237
|
|
|
2238
|
+
// Factories wrap initialized storage directly. Copy allocators create empty,
|
|
2239
|
+
// checked shells for Ruby dup/clone; direct construction is rejected.
|
|
2044
2240
|
// Secp256k1::KeyPair
|
|
2045
2241
|
Secp256k1_KeyPair_class = rb_define_class_under(Secp256k1_module,
|
|
2046
2242
|
"KeyPair",
|
|
2047
2243
|
rb_cObject);
|
|
2048
|
-
|
|
2049
|
-
rb_define_alloc_func(Secp256k1_KeyPair_class, KeyPair_alloc);
|
|
2244
|
+
ENABLE_VALUE_COPY(KeyPair);
|
|
2050
2245
|
rb_define_method(Secp256k1_KeyPair_class, "public_key", KeyPair_public_key, 0);
|
|
2051
2246
|
rb_define_method(Secp256k1_KeyPair_class, "private_key", KeyPair_private_key, 0);
|
|
2052
2247
|
rb_define_method(Secp256k1_KeyPair_class, "xonly_public_key", KeyPair_xonly_public_key, 0);
|
|
@@ -2056,8 +2251,7 @@ void Init_rbsecp256k1(void)
|
|
|
2056
2251
|
Secp256k1_PublicKey_class = rb_define_class_under(Secp256k1_module,
|
|
2057
2252
|
"PublicKey",
|
|
2058
2253
|
rb_cObject);
|
|
2059
|
-
|
|
2060
|
-
rb_define_alloc_func(Secp256k1_PublicKey_class, PublicKey_alloc);
|
|
2254
|
+
ENABLE_VALUE_COPY(PublicKey);
|
|
2061
2255
|
rb_define_method(Secp256k1_PublicKey_class,
|
|
2062
2256
|
"compressed",
|
|
2063
2257
|
PublicKey_compressed,
|
|
@@ -2083,8 +2277,7 @@ void Init_rbsecp256k1(void)
|
|
|
2083
2277
|
"XOnlyPublicKey",
|
|
2084
2278
|
rb_cObject);
|
|
2085
2279
|
|
|
2086
|
-
|
|
2087
|
-
rb_define_alloc_func(Secp256k1_XOnlyPublicKey_class, XOnlyPublicKey_alloc);
|
|
2280
|
+
ENABLE_VALUE_COPY(XOnlyPublicKey);
|
|
2088
2281
|
rb_define_method(Secp256k1_XOnlyPublicKey_class,
|
|
2089
2282
|
"serialized",
|
|
2090
2283
|
XOnlyPublicKey_serialized,
|
|
@@ -2100,8 +2293,7 @@ void Init_rbsecp256k1(void)
|
|
|
2100
2293
|
Secp256k1_PrivateKey_class = rb_define_class_under(
|
|
2101
2294
|
Secp256k1_module, "PrivateKey", rb_cObject
|
|
2102
2295
|
);
|
|
2103
|
-
|
|
2104
|
-
rb_define_alloc_func(Secp256k1_PrivateKey_class, PrivateKey_alloc);
|
|
2296
|
+
ENABLE_VALUE_COPY(PrivateKey);
|
|
2105
2297
|
rb_define_method(Secp256k1_PrivateKey_class, "data", PrivateKey_data, 0);
|
|
2106
2298
|
rb_define_method(Secp256k1_PrivateKey_class, "==", PrivateKey_equals, 1);
|
|
2107
2299
|
rb_define_singleton_method(
|
|
@@ -2115,8 +2307,7 @@ void Init_rbsecp256k1(void)
|
|
|
2115
2307
|
Secp256k1_Signature_class = rb_define_class_under(Secp256k1_module,
|
|
2116
2308
|
"Signature",
|
|
2117
2309
|
rb_cObject);
|
|
2118
|
-
|
|
2119
|
-
rb_define_alloc_func(Secp256k1_Signature_class, Signature_alloc);
|
|
2310
|
+
ENABLE_VALUE_COPY(Signature);
|
|
2120
2311
|
rb_define_method(Secp256k1_Signature_class,
|
|
2121
2312
|
"der_encoded",
|
|
2122
2313
|
Signature_der_encoded,
|
|
@@ -2153,11 +2344,7 @@ void Init_rbsecp256k1(void)
|
|
|
2153
2344
|
"RecoverableSignature",
|
|
2154
2345
|
rb_cObject
|
|
2155
2346
|
);
|
|
2156
|
-
|
|
2157
|
-
rb_define_alloc_func(
|
|
2158
|
-
Secp256k1_RecoverableSignature_class,
|
|
2159
|
-
RecoverableSignature_alloc
|
|
2160
|
-
);
|
|
2347
|
+
ENABLE_VALUE_COPY(RecoverableSignature);
|
|
2161
2348
|
rb_define_method(
|
|
2162
2349
|
Secp256k1_RecoverableSignature_class,
|
|
2163
2350
|
"compact",
|
|
@@ -2205,7 +2392,6 @@ void Init_rbsecp256k1(void)
|
|
|
2205
2392
|
rb_cObject
|
|
2206
2393
|
);
|
|
2207
2394
|
rb_undef_alloc_func(Secp256k1_SharedSecret_class);
|
|
2208
|
-
rb_define_alloc_func(Secp256k1_SharedSecret_class, SharedSecret_alloc);
|
|
2209
2395
|
rb_define_attr(Secp256k1_SharedSecret_class, "data", 1, 0);
|
|
2210
2396
|
|
|
2211
2397
|
// Context EC Diffie-Hellman methods
|
|
@@ -2222,8 +2408,7 @@ void Init_rbsecp256k1(void)
|
|
|
2222
2408
|
Secp256k1_module,
|
|
2223
2409
|
"SchnorrSignature",
|
|
2224
2410
|
rb_cObject);
|
|
2225
|
-
|
|
2226
|
-
rb_define_alloc_func(Secp256k1_SchnorrSignature_class, SchnorrSignature_alloc);
|
|
2411
|
+
ENABLE_VALUE_COPY(SchnorrSignature);
|
|
2227
2412
|
rb_define_method(Secp256k1_SchnorrSignature_class, "serialized", SchnorrSignature_serialized, 0);
|
|
2228
2413
|
rb_define_method(Secp256k1_SchnorrSignature_class, "verify", SchnorrSignature_verify, 2);
|
|
2229
2414
|
rb_define_method(Secp256k1_SchnorrSignature_class, "==", SchnorrSignature_equals, 1);
|