secp256k1zkp 0.9.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 951b1330ba2ce304878210145ac200583994dad6
4
+ data.tar.gz: ac91e14b4c07918be085d3d32f0df83cafae6f7e
5
+ SHA512:
6
+ metadata.gz: b150ff39fd63b32f55f324fc99abf20d336e961a7a2348dc5cf26527726a52a18dc7cb006eead9fae9533eb94c9d2f302532e2bc6e474a64424814e04010cff5
7
+ data.tar.gz: 5b58160792d93e8b46b998e25e0de1773e73ee90c137f742c4ef76cf88ba7bc629e38e1aa0d6fbb6926b900477d02c439fb2dd279be96f8923768ae3afd51857
@@ -0,0 +1 @@
1
+ # secp256k1zkp
@@ -0,0 +1,5 @@
1
+ require "rake/extensiontask"
2
+
3
+ Rake::ExtensionTask.new "secp256k1zkp" do |ext|
4
+ ext.lib_dir = "lib/secp256k1zkp"
5
+ end
@@ -0,0 +1,85 @@
1
+ #encoding:utf-8
2
+
3
+ require 'mini_portile2'
4
+ require 'mkmf'
5
+ require 'zip'
6
+
7
+ class Secp256k1Recipe < MiniPortile
8
+
9
+ LIBSECP256K1_ZIP_URL = 'https://github.com/syalon/secp256k1-zkp/archive/bd067945ead3b514fba884abd0de95fc4b5db9ae.zip'
10
+ LIBSECP256K1_SHA256 = '379f7920d382d2b54bc5c092bb6c39b03c7f74508369cac5464cb9cbd8459dc0'
11
+
12
+ def initialize
13
+ super('libsecp256k1', '0.0.0')
14
+ @tarball = File.join(Dir.pwd, "/ports/archives/libsecp256k1.zip")
15
+ @files = ["file://#{@tarball}"]
16
+ self.configure_options += [
17
+ "--disable-benchmark",
18
+ "--disable-exhaustive-tests",
19
+ "--disable-tests",
20
+ "--disable-debug",
21
+ "--enable-experimental",
22
+ "--with-pic=yes"
23
+ ]
24
+ end
25
+
26
+ def configure
27
+ if RUBY_PLATFORM =~ /mingw|mswin/
28
+ execute('autogen', %w[sh ./autogen.sh])
29
+ else
30
+ execute('autogen', %w[./autogen.sh])
31
+ end
32
+ super
33
+ end
34
+
35
+ def download
36
+ download_file_http(LIBSECP256K1_ZIP_URL, @tarball)
37
+ verify_file(local_path: @tarball, sha256: LIBSECP256K1_SHA256) if LIBSECP256K1_SHA256
38
+ end
39
+
40
+ def downloaded?
41
+ File.exist?(@tarball)
42
+ end
43
+
44
+ def extract_zip_file(file, destination)
45
+ FileUtils.mkdir_p(destination)
46
+
47
+ Zip::File.open(file) do |zip_file|
48
+ zip_file.each do |f|
49
+ fpath = File.join(destination, f.name)
50
+ zip_file.extract(f, fpath) unless File.exist?(fpath)
51
+ end
52
+ end
53
+ end
54
+
55
+ def extract
56
+ files_hashs.each do |file|
57
+ extract_zip_file(file[:local_path], tmp_path)
58
+ end
59
+ end
60
+ end
61
+
62
+ recipe = Secp256k1Recipe.new
63
+ recipe.cook
64
+ recipe.activate
65
+
66
+ append_cflags(
67
+ [
68
+ "-I#{recipe.path}/include",
69
+ "-fPIC",
70
+ "-Wno-undef",
71
+ "-Wall"
72
+ ]
73
+ )
74
+
75
+ append_ldflags(
76
+ [
77
+ "-Wl,--no-as-needed"
78
+ ]
79
+ )
80
+
81
+ $LIBPATH = ["#{recipe.path}/lib"] | $LIBPATH
82
+ have_library("secp256k1")
83
+ have_library("gmp")
84
+ have_header('secp256k1')
85
+ create_makefile('secp256k1zkp')
@@ -0,0 +1,739 @@
1
+ /**
2
+ * secp256k1zkp.c
3
+ */
4
+
5
+ #include <ruby.h>
6
+ #include <secp256k1.h>
7
+
8
+ /*
9
+ * 宏 - 类型检测
10
+ */
11
+ #define Check_AnyType(obj, klass) \
12
+ if (rb_obj_class(obj) != klass) \
13
+ { \
14
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", \
15
+ rb_obj_classname(obj), rb_class2name(klass)); \
16
+ }
17
+
18
+ /**
19
+ * Secp256k1Zkp
20
+ * - Context
21
+ * - PublicKey
22
+ * - PrivateKey
23
+ */
24
+ static VALUE rb_mSecp256k1 = Qnil;
25
+ static VALUE rb_cSecp256k1Context = Qnil;
26
+ static VALUE rb_cSecp256k1PublicKey = Qnil;
27
+ static VALUE rb_cSecp256k1PrivateKey = Qnil;
28
+
29
+ /**
30
+ * 全局上下文
31
+ */
32
+ static secp256k1_context_t *_g_secp256k1_context_ptr = 0;
33
+
34
+ /**
35
+ * 部分数据类型定义
36
+ */
37
+ typedef struct
38
+ {
39
+ secp256k1_context_t *ctx; // Context used by libsecp256k1 library
40
+ int flags;
41
+ } rb_struct_context;
42
+
43
+ /**
44
+ * 各种数据结构字节数定义
45
+ */
46
+ #define kByteSizePrivateKeyData 32
47
+ #define kByteSizePublicKeyPoint 65
48
+ #define kByteSizeCompressedPublicKeyData 33
49
+ #define kByteSizeCompactSignature 65
50
+ #define kByteSizeBlindFactor 32
51
+ #define kByteSizeCommitment 33
52
+ #define kByteSizeSha256 32
53
+
54
+ typedef struct
55
+ {
56
+ unsigned char data[kByteSizePrivateKeyData];
57
+ } rb_struct_private_key;
58
+
59
+ // the full non-compressed version of the ECC point
60
+ typedef struct
61
+ {
62
+ unsigned char data[kByteSizePublicKeyPoint];
63
+ } rb_struct_pubkey_point;
64
+
65
+ typedef struct
66
+ {
67
+ unsigned char data[kByteSizeCompressedPublicKeyData];
68
+ } rb_struct_pubkey_compressed;
69
+
70
+ typedef struct
71
+ {
72
+ unsigned char data[kByteSizeCompactSignature];
73
+ } rb_struct_compact_signature;
74
+
75
+ typedef struct
76
+ {
77
+ unsigned char data[kByteSizeBlindFactor];
78
+ } rb_struct_blind_factor_type;
79
+
80
+ typedef struct
81
+ {
82
+ unsigned char data[kByteSizeCommitment];
83
+ } rb_struct_commitment_type;
84
+
85
+ /**
86
+ * Secp256k1Zkp::Context
87
+ */
88
+ static void Context_free(void *data)
89
+ {
90
+ rb_struct_context *context = (rb_struct_context *)data;
91
+ secp256k1_context_destroy(context->ctx);
92
+ context->flags = 0;
93
+ xfree(context);
94
+ }
95
+
96
+ static const rb_data_type_t rb_type_context = {
97
+ "Context",
98
+ {0, Context_free, 0},
99
+ 0,
100
+ 0,
101
+ RUBY_TYPED_FREE_IMMEDIATELY};
102
+
103
+ static VALUE dm_context_alloc(VALUE klass)
104
+ {
105
+ rb_struct_context *context = ALLOC(rb_struct_context);
106
+ MEMZERO(context, rb_struct_context, 1);
107
+
108
+ return TypedData_Wrap_Struct(klass, &rb_type_context, context);
109
+ }
110
+
111
+ /**
112
+ * Secp256k1Zkp::PublicKey
113
+ */
114
+ static void PublicKey_free(void *data)
115
+ {
116
+ xfree((rb_struct_pubkey_compressed *)data);
117
+ }
118
+
119
+ static const rb_data_type_t rb_type_public_key = {
120
+ "PublicKey",
121
+ {0, PublicKey_free, 0},
122
+ 0,
123
+ 0,
124
+ RUBY_TYPED_FREE_IMMEDIATELY};
125
+
126
+ static VALUE dm_public_key_alloc(VALUE klass)
127
+ {
128
+ rb_struct_pubkey_compressed *public_key = ALLOC(rb_struct_pubkey_compressed);
129
+ MEMZERO(public_key, rb_struct_pubkey_compressed, 1);
130
+
131
+ return TypedData_Wrap_Struct(klass, &rb_type_public_key, public_key);
132
+ }
133
+
134
+ /**
135
+ * Secp256k1Zkp::PrivateKey
136
+ */
137
+ static void PrivateKey_free(void *data)
138
+ {
139
+ xfree((rb_struct_private_key *)data);
140
+ }
141
+
142
+ static const rb_data_type_t rb_type_private_key = {
143
+ "PrivateKey",
144
+ {0, PrivateKey_free, 0},
145
+ 0,
146
+ 0,
147
+ RUBY_TYPED_FREE_IMMEDIATELY};
148
+
149
+ static VALUE dm_private_key_alloc(VALUE klass)
150
+ {
151
+ rb_struct_private_key *private_key = ALLOC(rb_struct_private_key);
152
+ MEMZERO(private_key, rb_struct_private_key, 1);
153
+
154
+ return TypedData_Wrap_Struct(klass, &rb_type_private_key, private_key);
155
+ }
156
+
157
+ /**
158
+ * Secp256k1Zkp::Context.new(flags)
159
+ *
160
+ * 创建Secp256k1上下文对象。
161
+ *
162
+ * @param flags [Fixnum] 上下文标记。
163
+ * @return [Context]
164
+ */
165
+ static VALUE dm_context_initialize(VALUE self, VALUE flags)
166
+ {
167
+ rb_struct_context *context;
168
+ int i_flags;
169
+
170
+ Check_Type(flags, T_FIXNUM);
171
+ i_flags = FIX2INT(flags);
172
+
173
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
174
+
175
+ context->ctx = secp256k1_context_create(i_flags);
176
+ context->flags = i_flags;
177
+
178
+ return self;
179
+ }
180
+
181
+ /**
182
+ * Secp256k1Zkp::Context#is_valid_public_keydata?(public_keydata)
183
+ *
184
+ * 是否是有效的公钥判断。
185
+ *
186
+ * @param public_keydata [String] 压缩公钥字符串。
187
+ * @return [Boolean]
188
+ */
189
+ static VALUE dm_context_verify_public_keydata(VALUE self, VALUE public_keydata)
190
+ {
191
+ rb_struct_context *context;
192
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
193
+
194
+ if (RB_TYPE_P(public_keydata, T_STRING) && secp256k1_ec_pubkey_verify(context->ctx, (const unsigned char *)RSTRING_PTR(public_keydata), (int)RSTRING_LEN(public_keydata)))
195
+ {
196
+ return Qtrue;
197
+ }
198
+
199
+ return Qfalse;
200
+ }
201
+
202
+ /**
203
+ * Secp256k1Zkp::Context#is_valid_private_keydata?(private_keydata)
204
+ *
205
+ * 是否是有效的私钥判断。
206
+ *
207
+ * @param private_keydata [String] 私钥字符串。
208
+ * @return [Boolean]
209
+ */
210
+ static VALUE dm_context_verify_private_keydata(VALUE self, VALUE private_keydata)
211
+ {
212
+ rb_struct_context *context;
213
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
214
+
215
+ if (RB_TYPE_P(private_keydata, T_STRING) &&
216
+ RSTRING_LEN(private_keydata) == kByteSizePrivateKeyData &&
217
+ secp256k1_ec_seckey_verify(context->ctx, (const unsigned char *)RSTRING_PTR(private_keydata)))
218
+ {
219
+ return Qtrue;
220
+ }
221
+
222
+ return Qfalse;
223
+ }
224
+
225
+ /**
226
+ * Secp256k1Zkp::Context#clone #dup
227
+ *
228
+ * 克隆Secp256k1上下文对象。
229
+ *
230
+ * @return [Context]
231
+ */
232
+ static VALUE dm_context_clone(VALUE self)
233
+ {
234
+ rb_struct_context *context;
235
+ rb_struct_context *context_new;
236
+ VALUE new_instance;
237
+
238
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
239
+
240
+ new_instance = dm_context_alloc(rb_cSecp256k1Context);
241
+ TypedData_Get_Struct(new_instance, rb_struct_context, &rb_type_context, context_new);
242
+ context_new->ctx = secp256k1_context_clone(context->ctx);
243
+ context_new->flags = context->flags;
244
+
245
+ return new_instance;
246
+ }
247
+
248
+ static int extended_nonce_function(unsigned char *nonce32, const unsigned char *msg32,
249
+ const unsigned char *key32, unsigned int attempt,
250
+ const void *data)
251
+ {
252
+ unsigned int *extra = (unsigned int *)data;
253
+ (*extra)++;
254
+ return secp256k1_nonce_function_default(nonce32, msg32, key32, *extra, 0);
255
+ };
256
+
257
+ static int is_canonical(const rb_struct_compact_signature *sign)
258
+ {
259
+ const unsigned char *c = sign->data;
260
+ if (!(c[1] & 0x80) && !(c[1] == 0 && !(c[2] & 0x80)) && !(c[33] & 0x80) && !(c[33] == 0 && !(c[34] & 0x80)))
261
+ {
262
+ return 1;
263
+ }
264
+ return 0;
265
+ }
266
+
267
+ /**
268
+ * Secp256k1Zkp::Context#sign_compact(message_digest, private_key)
269
+ *
270
+ * 生成紧凑格式的 ECDSA 签名(recId + 64字节)。
271
+ *
272
+ * @param message_digest [String] 待签名的消息摘要(SHA256摘要、32字节)。
273
+ * @param private_key [Secp256k1Zkp::PrivateKey] 私钥。
274
+ * @return [String]
275
+ */
276
+ static VALUE dm_context_sign_compact(VALUE self, VALUE message_digest, VALUE private_key)
277
+ {
278
+ rb_struct_context *context;
279
+ rb_struct_private_key *sp_private_key;
280
+ const unsigned char *digest32;
281
+ int require_canonical;
282
+ int recid;
283
+ unsigned int counter;
284
+ rb_struct_compact_signature signature = {
285
+ 0,
286
+ };
287
+
288
+ SafeStringValue(message_digest);
289
+ if (RSTRING_LEN(message_digest) != kByteSizeSha256)
290
+ {
291
+ rb_raise(rb_eRuntimeError, "invalid message digest32.");
292
+ }
293
+ Check_AnyType(private_key, rb_cSecp256k1PrivateKey);
294
+
295
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
296
+
297
+ // check flags
298
+ if (!(context->flags & SECP256K1_CONTEXT_SIGN))
299
+ {
300
+ rb_raise(rb_eRuntimeError, "invalid secp256k1 context, missing `SECP256K1_CONTEXT_SIGN` flag.");
301
+ }
302
+
303
+ TypedData_Get_Struct(private_key, rb_struct_private_key, &rb_type_private_key, sp_private_key);
304
+
305
+ // 初始化部分参数
306
+ digest32 = (const unsigned char *)RSTRING_PTR(message_digest);
307
+ require_canonical = 0; // 0 or 1
308
+ counter = 0;
309
+
310
+ // 循环计算签名,直到找到合适的 canonical 签名。
311
+ do
312
+ {
313
+ if (!secp256k1_ecdsa_sign_compact(context->ctx, digest32,
314
+ &signature.data[1],
315
+ sp_private_key->data,
316
+ extended_nonce_function,
317
+ &counter, &recid))
318
+ {
319
+ return Qnil;
320
+ }
321
+ } while (require_canonical && !is_canonical(&signature));
322
+ signature.data[0] = 27 + 4 + recid;
323
+
324
+ return rb_str_new((const char *)&signature.data[0], sizeof(signature.data));
325
+ }
326
+
327
+ /**
328
+ * Secp256k1Zkp::Context#pedersen_commit(blind_factor, value)
329
+ *
330
+ * 生成佩德森承诺。
331
+ *
332
+ * @param blind_factor [String] 盲化因子。
333
+ * @param value [Integer] 承诺的数值。
334
+ * @return [String]
335
+ */
336
+ static VALUE dm_context_pedersen_commit(VALUE self, VALUE blind_factor, VALUE value)
337
+ {
338
+ rb_struct_context *context;
339
+ rb_struct_commitment_type commitment = {
340
+ 0,
341
+ };
342
+
343
+ SafeStringValue(blind_factor);
344
+ if (RSTRING_LEN(blind_factor) != kByteSizeBlindFactor)
345
+ {
346
+ rb_raise(rb_eRuntimeError, "invalid blind_factor.");
347
+ }
348
+
349
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
350
+
351
+ // check flags
352
+ if (!(context->flags & SECP256K1_CONTEXT_SIGN))
353
+ {
354
+ rb_raise(rb_eRuntimeError, "invalid secp256k1 context, missing `SECP256K1_CONTEXT_SIGN` flag.");
355
+ }
356
+ if (!(context->flags & SECP256K1_CONTEXT_COMMIT))
357
+ {
358
+ rb_raise(rb_eRuntimeError, "invalid secp256k1 context, missing `SECP256K1_CONTEXT_COMMIT` flag.");
359
+ }
360
+
361
+ if (!secp256k1_pedersen_commit(context->ctx, commitment.data, (unsigned char *)RSTRING_PTR(blind_factor), (uint64_t)NUM2ULL(value)))
362
+ {
363
+ return Qnil;
364
+ }
365
+
366
+ return rb_str_new((const char *)&commitment.data[0], sizeof(commitment.data));
367
+ }
368
+
369
+ /**
370
+ * Secp256k1Zkp::Context#pedersen_blind_sum(blinds_in, non_neg)
371
+ *
372
+ * 盲化因子求和。
373
+ *
374
+ * @param blinds_in [Array] 盲化因子数组。
375
+ * @param non_neg [Integer] 正因子数量。
376
+ * @return [String]
377
+ */
378
+ static VALUE dm_context_pedersen_blind_sum(VALUE self, VALUE blinds_in, VALUE non_neg)
379
+ {
380
+ rb_struct_context *context;
381
+ long blinds_in_size;
382
+ rb_struct_blind_factor_type result = {
383
+ 0,
384
+ };
385
+
386
+ Check_Type(blinds_in, T_ARRAY);
387
+
388
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
389
+
390
+ blinds_in_size = RARRAY_LEN(blinds_in);
391
+ if (blinds_in_size <= 0)
392
+ {
393
+ return Qnil;
394
+ }
395
+ const unsigned char *blinds[blinds_in_size];
396
+ for (long i = 0; i < blinds_in_size; ++i)
397
+ {
398
+ VALUE blind_factor = rb_ary_entry(blinds_in, i);
399
+ SafeStringValue(blind_factor);
400
+ blinds[i] = (const unsigned char *)RSTRING_PTR(blind_factor);
401
+ }
402
+
403
+ if (!secp256k1_pedersen_blind_sum(context->ctx, result.data, blinds, (int)blinds_in_size, (uint32_t)NUM2UINT(non_neg)))
404
+ {
405
+ return Qnil;
406
+ }
407
+
408
+ return rb_str_new((const char *)&result.data[0], sizeof(result.data));
409
+ }
410
+
411
+ /**
412
+ * Secp256k1Zkp::Context#range_proof_sign(min_value, commit, commit_blind, nonce, base10_exp, min_bits, actual_value)
413
+ *
414
+ * 生成范围证明。
415
+ *
416
+ * @param * 参考 secp256k1_rangeproof_sign 参数。
417
+ * @return [String]
418
+ */
419
+ static VALUE dm_context_range_proof_sign(VALUE self, VALUE min_value, VALUE commit, VALUE commit_blind, VALUE nonce, VALUE base10_exp, VALUE min_bits, VALUE actual_value)
420
+ {
421
+ rb_struct_context *context;
422
+ unsigned char proof[5134];
423
+ int proof_len;
424
+
425
+ SafeStringValue(commit);
426
+ SafeStringValue(commit_blind);
427
+ SafeStringValue(nonce);
428
+
429
+ TypedData_Get_Struct(self, rb_struct_context, &rb_type_context, context);
430
+
431
+ // check flags
432
+ if (!(context->flags & SECP256K1_CONTEXT_SIGN))
433
+ {
434
+ rb_raise(rb_eRuntimeError, "invalid secp256k1 context, missing `SECP256K1_CONTEXT_SIGN` flag.");
435
+ }
436
+ if (!(context->flags & SECP256K1_CONTEXT_COMMIT))
437
+ {
438
+ rb_raise(rb_eRuntimeError, "invalid secp256k1 context, missing `SECP256K1_CONTEXT_COMMIT` flag.");
439
+ }
440
+ if (!(context->flags & SECP256K1_CONTEXT_RANGEPROOF))
441
+ {
442
+ rb_raise(rb_eRuntimeError, "invalid secp256k1 context, missing `SECP256K1_CONTEXT_RANGEPROOF` flag.");
443
+ }
444
+
445
+ proof_len = sizeof(proof);
446
+
447
+ if (!secp256k1_rangeproof_sign(context->ctx, proof, &proof_len, (uint64_t)NUM2ULL(min_value),
448
+ (const unsigned char *)RSTRING_PTR(commit), (const unsigned char *)RSTRING_PTR(commit_blind), (const unsigned char *)RSTRING_PTR(nonce),
449
+ (int8_t)FIX2INT(base10_exp), (uint8_t)FIX2INT(min_bits), (uint64_t)NUM2ULL(actual_value)))
450
+ {
451
+ return Qnil;
452
+ }
453
+
454
+ return rb_str_new((const char *)proof, proof_len);
455
+ }
456
+
457
+ /**
458
+ * Secp256k1Zkp::PublicKey.new(public_keydata)
459
+ *
460
+ * 创建公钥对象。
461
+ *
462
+ * @param public_keydata [String] 压缩公钥字符串。
463
+ * @return [Secp256k1Zkp::PublicKey]
464
+ */
465
+ static VALUE dm_public_key_initialize(VALUE self, VALUE public_keydata)
466
+ {
467
+ rb_struct_pubkey_compressed *public_key;
468
+ TypedData_Get_Struct(self, rb_struct_pubkey_compressed, &rb_type_public_key, public_key);
469
+
470
+ SafeStringValue(public_keydata);
471
+ if (!secp256k1_ec_pubkey_verify(_g_secp256k1_context_ptr, (const unsigned char *)RSTRING_PTR(public_keydata), (int)RSTRING_LEN(public_keydata)))
472
+ {
473
+ rb_raise(rb_eRuntimeError, "invalid public key data.");
474
+ }
475
+
476
+ memcpy(public_key->data, RSTRING_PTR(public_keydata), sizeof(public_key->data));
477
+
478
+ return self;
479
+ }
480
+
481
+ /**
482
+ * Secp256k1Zkp::PublicKey#bytes
483
+ *
484
+ * 获取公钥数据。
485
+ *
486
+ * @return [String]
487
+ */
488
+ static VALUE dm_public_key_bytes(VALUE self)
489
+ {
490
+ rb_struct_pubkey_compressed *public_key;
491
+ VALUE data = rb_iv_get(self, "data");
492
+ if (NIL_P(data))
493
+ {
494
+ TypedData_Get_Struct(self, rb_struct_pubkey_compressed, &rb_type_public_key, public_key);
495
+ data = rb_str_freeze(rb_str_new((const char *)public_key->data, sizeof(public_key->data)));
496
+ rb_iv_set(self, "data", data);
497
+ }
498
+ return data;
499
+ }
500
+
501
+ static VALUE public_key_tweak(VALUE self, VALUE tweak, int (*tweak_func)(const secp256k1_context_t *ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak))
502
+ {
503
+ rb_struct_pubkey_compressed *public_key;
504
+ rb_struct_pubkey_compressed *new_public_key;
505
+ VALUE new_instance;
506
+
507
+ SafeStringValue(tweak);
508
+ if (RSTRING_LEN(tweak) != kByteSizePrivateKeyData)
509
+ {
510
+ rb_raise(rb_eRuntimeError, "invalid private key data.");
511
+ }
512
+
513
+ TypedData_Get_Struct(self, rb_struct_pubkey_compressed, &rb_type_public_key, public_key);
514
+
515
+ new_instance = dm_public_key_alloc(rb_cSecp256k1PublicKey);
516
+ TypedData_Get_Struct(new_instance, rb_struct_pubkey_compressed, &rb_type_public_key, new_public_key);
517
+ memcpy(new_public_key->data, public_key->data, sizeof(public_key->data));
518
+
519
+ if (!tweak_func(_g_secp256k1_context_ptr, new_public_key->data, sizeof(new_public_key->data), (const unsigned char *)RSTRING_PTR(tweak)))
520
+ {
521
+ rb_raise(rb_eRuntimeError, "tweak error.");
522
+ }
523
+
524
+ return new_instance;
525
+ }
526
+
527
+ /**
528
+ * Secp256k1Zkp::PublicKey#tweak_add(tweak)
529
+ * Secp256k1Zkp::PublicKey#+(tweak)
530
+ *
531
+ * 公钥加法,返回新的公钥。
532
+ *
533
+ * @param tweak [String] 参数。
534
+ * @return [Secp256k1Zkp::PublicKey]
535
+ */
536
+ static VALUE dm_public_key_tweak_add(VALUE self, VALUE tweak)
537
+ {
538
+ return public_key_tweak(self, tweak, secp256k1_ec_pubkey_tweak_add);
539
+ }
540
+
541
+ /**
542
+ * Secp256k1Zkp::PublicKey#tweak_mul(tweak)
543
+ * Secp256k1Zkp::PublicKey#*(tweak)
544
+ *
545
+ * 公钥乘法,返回新的公钥。
546
+ *
547
+ * @param tweak [String] 参数。
548
+ * @return [Secp256k1Zkp::PublicKey]
549
+ */
550
+ static VALUE dm_public_key_tweak_mul(VALUE self, VALUE tweak)
551
+ {
552
+ return public_key_tweak(self, tweak, secp256k1_ec_pubkey_tweak_mul);
553
+ }
554
+
555
+ /**
556
+ * Secp256k1Zkp::PrivateKey.new(private_keydata)
557
+ *
558
+ * 创建私钥对象。
559
+ *
560
+ * @param private_keydata [String] 私钥字符串。
561
+ * @return [Secp256k1Zkp::PrivateKey]
562
+ */
563
+ static VALUE dm_private_key_initialize(VALUE self, VALUE private_keydata)
564
+ {
565
+ rb_struct_private_key *private_key;
566
+ TypedData_Get_Struct(self, rb_struct_private_key, &rb_type_private_key, private_key);
567
+
568
+ SafeStringValue(private_keydata);
569
+ if (RSTRING_LEN(private_keydata) != sizeof(private_key->data) ||
570
+ !secp256k1_ec_seckey_verify(_g_secp256k1_context_ptr, (const unsigned char *)RSTRING_PTR(private_keydata)))
571
+ {
572
+ rb_raise(rb_eRuntimeError, "invalid private key data.");
573
+ }
574
+
575
+ memcpy(private_key->data, RSTRING_PTR(private_keydata), sizeof(private_key->data));
576
+
577
+ return self;
578
+ }
579
+
580
+ /**
581
+ * Secp256k1Zkp::PrivateKey#bytes
582
+ *
583
+ * 获取私钥数据。
584
+ *
585
+ * @return [String]
586
+ */
587
+ static VALUE dm_private_key_bytes(VALUE self)
588
+ {
589
+ rb_struct_private_key *private_key;
590
+ VALUE data = rb_iv_get(self, "data");
591
+ if (NIL_P(data))
592
+ {
593
+ TypedData_Get_Struct(self, rb_struct_private_key, &rb_type_private_key, private_key);
594
+ data = rb_str_freeze(rb_str_new((const char *)private_key->data, sizeof(private_key->data)));
595
+ rb_iv_set(self, "data", data);
596
+ }
597
+ return data;
598
+ }
599
+
600
+ static VALUE private_key_tweak(VALUE self, VALUE tweak, int (*tweak_func)(const secp256k1_context_t *ctx, unsigned char *seckey, const unsigned char *tweak))
601
+ {
602
+ rb_struct_private_key *private_key;
603
+ rb_struct_private_key *new_private_key;
604
+ VALUE v_private_key;
605
+
606
+ SafeStringValue(tweak);
607
+ if (RSTRING_LEN(tweak) != kByteSizePrivateKeyData)
608
+ {
609
+ rb_raise(rb_eRuntimeError, "invalid private key data.");
610
+ }
611
+
612
+ TypedData_Get_Struct(self, rb_struct_private_key, &rb_type_private_key, private_key);
613
+
614
+ v_private_key = dm_private_key_alloc(rb_cSecp256k1PrivateKey);
615
+ TypedData_Get_Struct(v_private_key, rb_struct_private_key, &rb_type_private_key, new_private_key);
616
+ memcpy(new_private_key->data, private_key->data, sizeof(private_key->data));
617
+
618
+ if (!tweak_func(_g_secp256k1_context_ptr, new_private_key->data, (const unsigned char *)RSTRING_PTR(tweak)))
619
+ {
620
+ rb_raise(rb_eRuntimeError, "tweak error.");
621
+ }
622
+
623
+ return v_private_key;
624
+ }
625
+
626
+ /**
627
+ * Secp256k1Zkp::PrivateKey#tweak_add(tweak)
628
+ * Secp256k1Zkp::PrivateKey#+(tweak)
629
+ *
630
+ * 私钥加法,返回新的私钥。
631
+ *
632
+ * @param tweak [String] 参数。
633
+ * @return [Secp256k1Zkp::PrivateKey]
634
+ */
635
+ static VALUE dm_private_key_tweak_add(VALUE self, VALUE tweak)
636
+ {
637
+ return private_key_tweak(self, tweak, secp256k1_ec_privkey_tweak_add);
638
+ }
639
+
640
+ /**
641
+ * Secp256k1Zkp::PrivateKey#tweak_mul(tweak)
642
+ * Secp256k1Zkp::PrivateKey#*(tweak)
643
+ *
644
+ * 私钥乘法,返回新的私钥。
645
+ *
646
+ * @param tweak [String] 参数。
647
+ * @return [Secp256k1Zkp::PrivateKey]
648
+ */
649
+ static VALUE dm_private_key_tweak_mul(VALUE self, VALUE tweak)
650
+ {
651
+ return private_key_tweak(self, tweak, secp256k1_ec_privkey_tweak_mul);
652
+ }
653
+
654
+ /**
655
+ * Secp256k1Zkp::PrivateKey#to_public_key
656
+ *
657
+ * 根据私钥创建对应公钥。
658
+ *
659
+ * @return [Secp256k1Zkp::PublicKey]
660
+ */
661
+ static VALUE dm_private_key_to_public_key(VALUE self)
662
+ {
663
+ rb_struct_private_key *private_key;
664
+ rb_struct_pubkey_compressed *output_public_key;
665
+ VALUE v_public_key;
666
+ int pubkey_len;
667
+
668
+ TypedData_Get_Struct(self, rb_struct_private_key, &rb_type_private_key, private_key);
669
+
670
+ v_public_key = dm_public_key_alloc(rb_cSecp256k1PublicKey);
671
+ TypedData_Get_Struct(v_public_key, rb_struct_pubkey_compressed, &rb_type_public_key, output_public_key);
672
+
673
+ pubkey_len = sizeof(output_public_key->data);
674
+ if (!secp256k1_ec_pubkey_create(_g_secp256k1_context_ptr, output_public_key->data, &pubkey_len, private_key->data, 1))
675
+ {
676
+ rb_raise(rb_eRuntimeError, "generate public key error.");
677
+ }
678
+
679
+ return v_public_key;
680
+ }
681
+
682
+ /**
683
+ * 扩展初始化(类似 main 函数入口)
684
+ */
685
+ void Init_secp256k1zkp()
686
+ {
687
+ if (!_g_secp256k1_context_ptr)
688
+ {
689
+ _g_secp256k1_context_ptr = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
690
+ }
691
+
692
+ // Secp256k1Zkp
693
+ rb_mSecp256k1 = rb_define_module("Secp256k1Zkp");
694
+
695
+ rb_define_const(rb_mSecp256k1, "SECP256K1_CONTEXT_VERIFY", INT2FIX(SECP256K1_CONTEXT_VERIFY));
696
+ rb_define_const(rb_mSecp256k1, "SECP256K1_CONTEXT_SIGN", INT2FIX(SECP256K1_CONTEXT_SIGN));
697
+ rb_define_const(rb_mSecp256k1, "SECP256K1_CONTEXT_COMMIT", INT2FIX(SECP256K1_CONTEXT_COMMIT));
698
+ rb_define_const(rb_mSecp256k1, "SECP256K1_CONTEXT_RANGEPROOF", INT2FIX(SECP256K1_CONTEXT_RANGEPROOF));
699
+
700
+ // Secp256k1Zkp::Context
701
+ rb_cSecp256k1Context = rb_define_class_under(rb_mSecp256k1, "Context", rb_cObject);
702
+
703
+ rb_undef_alloc_func(rb_cSecp256k1Context);
704
+ rb_define_alloc_func(rb_cSecp256k1Context, dm_context_alloc);
705
+ rb_define_method(rb_cSecp256k1Context, "initialize", dm_context_initialize, 1);
706
+ rb_define_method(rb_cSecp256k1Context, "is_valid_public_keydata?", dm_context_verify_public_keydata, 1);
707
+ rb_define_method(rb_cSecp256k1Context, "is_valid_private_keydata?", dm_context_verify_private_keydata, 1);
708
+ rb_define_method(rb_cSecp256k1Context, "clone", dm_context_clone, 0);
709
+ rb_define_method(rb_cSecp256k1Context, "dup", dm_context_clone, 0);
710
+ rb_define_method(rb_cSecp256k1Context, "sign_compact", dm_context_sign_compact, 2);
711
+ rb_define_method(rb_cSecp256k1Context, "pedersen_commit", dm_context_pedersen_commit, 2);
712
+ rb_define_method(rb_cSecp256k1Context, "pedersen_blind_sum", dm_context_pedersen_blind_sum, 2);
713
+ rb_define_method(rb_cSecp256k1Context, "range_proof_sign", dm_context_range_proof_sign, 7);
714
+
715
+ // Secp256k1Zkp::PublicKey
716
+ rb_cSecp256k1PublicKey = rb_define_class_under(rb_mSecp256k1, "PublicKey", rb_cObject);
717
+
718
+ rb_undef_alloc_func(rb_cSecp256k1PublicKey);
719
+ rb_define_alloc_func(rb_cSecp256k1PublicKey, dm_public_key_alloc);
720
+ rb_define_method(rb_cSecp256k1PublicKey, "initialize", dm_public_key_initialize, 1);
721
+ rb_define_method(rb_cSecp256k1PublicKey, "bytes", dm_public_key_bytes, 0);
722
+ rb_define_method(rb_cSecp256k1PublicKey, "tweak_add", dm_public_key_tweak_add, 1);
723
+ rb_define_method(rb_cSecp256k1PublicKey, "tweak_mul", dm_public_key_tweak_mul, 1);
724
+ rb_define_alias(rb_cSecp256k1PublicKey, "+", "tweak_add");
725
+ rb_define_alias(rb_cSecp256k1PublicKey, "*", "tweak_mul");
726
+
727
+ // Secp256k1Zkp::PrivateKey
728
+ rb_cSecp256k1PrivateKey = rb_define_class_under(rb_mSecp256k1, "PrivateKey", rb_cObject);
729
+
730
+ rb_undef_alloc_func(rb_cSecp256k1PrivateKey);
731
+ rb_define_alloc_func(rb_cSecp256k1PrivateKey, dm_private_key_alloc);
732
+ rb_define_method(rb_cSecp256k1PrivateKey, "initialize", dm_private_key_initialize, 1);
733
+ rb_define_method(rb_cSecp256k1PrivateKey, "bytes", dm_private_key_bytes, 0);
734
+ rb_define_method(rb_cSecp256k1PrivateKey, "tweak_add", dm_private_key_tweak_add, 1);
735
+ rb_define_method(rb_cSecp256k1PrivateKey, "tweak_mul", dm_private_key_tweak_mul, 1);
736
+ rb_define_alias(rb_cSecp256k1PrivateKey, "+", "tweak_add");
737
+ rb_define_alias(rb_cSecp256k1PrivateKey, "*", "tweak_mul");
738
+ rb_define_method(rb_cSecp256k1PrivateKey, "to_public_key", dm_private_key_to_public_key, 0);
739
+ }
@@ -0,0 +1,11 @@
1
+ #encoding:utf-8
2
+
3
+ module Secp256k1Zkp
4
+ end
5
+
6
+ require 'secp256k1zkp/secp256k1zkp'
7
+ require 'secp256k1zkp/version'
8
+ require 'secp256k1zkp/utils'
9
+ require 'secp256k1zkp/context'
10
+ require 'secp256k1zkp/public_key'
11
+ require 'secp256k1zkp/private_key'
@@ -0,0 +1,15 @@
1
+ #encoding:utf-8
2
+
3
+ module Secp256k1Zkp
4
+
5
+ SECP256K1_CONTEXT_ALL = SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_COMMIT | SECP256K1_CONTEXT_RANGEPROOF
6
+
7
+ class Context
8
+
9
+ def self.default
10
+ return new(SECP256K1_CONTEXT_ALL)
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,30 @@
1
+ #encoding:utf-8
2
+
3
+ require 'securerandom'
4
+
5
+ module Secp256k1Zkp
6
+
7
+ class PrivateKey
8
+
9
+ def self.random
10
+ # # => REMARK:私钥有效范围。[1, secp256k1 curve order)。REMARK:大部分 lib 范围是 [1, secp256k1 curve order] 的闭区间,c库范围为开区间。
11
+ # sec = SecureRandom.random_number(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - 1) + 1
12
+ # new(hex_decode("%064x" % sec))
13
+ new(SecureRandom.random_bytes(32))
14
+ end
15
+
16
+ def shared_secret(public_key)
17
+ return public_key * self.bytes
18
+ end
19
+
20
+ def hex_encode(data)
21
+ return data.unpack("H*").first.downcase
22
+ end
23
+
24
+ def hex_decode(data)
25
+ return [data].pack("H*")
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,13 @@
1
+ #encoding:utf-8
2
+
3
+ module Secp256k1Zkp
4
+
5
+ class PublicKey
6
+
7
+ def shared_secret(private_key)
8
+ return self * private_key.bytes
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,20 @@
1
+ #encoding:utf-8
2
+
3
+ require 'digest'
4
+
5
+ module Secp256k1Zkp
6
+
7
+ module Utils
8
+
9
+ module_function
10
+
11
+ #------------------------------------------------------------------------
12
+ # ● 计算sha1
13
+ #------------------------------------------------------------------------
14
+ def sha1(str)
15
+ return Digest::SHA1.hexdigest(str)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,7 @@
1
+ #encoding:utf-8
2
+
3
+ module Secp256k1Zkp
4
+
5
+ VERSION = '0.9.0'.freeze
6
+
7
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: secp256k1zkp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - jokenshi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mini_portile2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ description:
42
+ email: developer@jokenshi.com
43
+ executables: []
44
+ extensions:
45
+ - ext/secp256k1zkp/extconf.rb
46
+ extra_rdoc_files: []
47
+ files:
48
+ - README.md
49
+ - Rakefile
50
+ - ext/secp256k1zkp/extconf.rb
51
+ - ext/secp256k1zkp/secp256k1zkp.c
52
+ - lib/secp256k1zkp.rb
53
+ - lib/secp256k1zkp/context.rb
54
+ - lib/secp256k1zkp/private_key.rb
55
+ - lib/secp256k1zkp/public_key.rb
56
+ - lib/secp256k1zkp/utils.rb
57
+ - lib/secp256k1zkp/version.rb
58
+ homepage: https://github.com/jokenshi/ruby-secp256zkp.git
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - ext
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.6.14.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: native extension gem for secp256k1-zkp.
83
+ test_files: []