secp256k1zkp 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []