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.
- checksums.yaml +7 -0
- data/README.md +1 -0
- data/Rakefile +5 -0
- data/ext/secp256k1zkp/extconf.rb +85 -0
- data/ext/secp256k1zkp/secp256k1zkp.c +739 -0
- data/lib/secp256k1zkp.rb +11 -0
- data/lib/secp256k1zkp/context.rb +15 -0
- data/lib/secp256k1zkp/private_key.rb +30 -0
- data/lib/secp256k1zkp/public_key.rb +13 -0
- data/lib/secp256k1zkp/utils.rb +20 -0
- data/lib/secp256k1zkp/version.rb +7 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -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
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# secp256k1zkp
|
data/Rakefile
ADDED
@@ -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
|
+
}
|
data/lib/secp256k1zkp.rb
ADDED
@@ -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,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
|
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: []
|