bitcoin-ruby 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/Gemfile.lock +1 -1
- data/lib/bitcoin/ffi/openssl.rb +6 -5
- data/lib/bitcoin/ffi/secp256k1.rb +139 -79
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/secp256k1_spec.rb +22 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa1430d4dfa8bcf7f4e23a098341ef1803797d8b
|
4
|
+
data.tar.gz: 1d4f1c0a5b163c7d42d07e4056d6a497719167b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a790a81f8a5bd8a94e8794e599b0ab5ca62f2b4568efce9924ffbc1fabd2805307ef9e8695cb2c9383907eff3ab62081fc8dd798d1985bcd11623e0155070c84
|
7
|
+
data.tar.gz: 5ab37c03ed8b4ba6f15a95c1ab29d564c2b5200309b75ef5667f9dc9f3003e267f8bf7c14ddf42fe9b56f53c6e26e221850e0f74af81e1fa731cfdd88e87218f
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/lib/bitcoin/ffi/openssl.rb
CHANGED
@@ -277,6 +277,8 @@ module OpenSSL_EC
|
|
277
277
|
end
|
278
278
|
|
279
279
|
def self.sign_compact(hash, private_key, public_key_hex = nil, pubkey_compressed = nil)
|
280
|
+
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
|
281
|
+
|
280
282
|
private_key = [private_key].pack("H*") if private_key.bytesize >= 64
|
281
283
|
private_key_hex = private_key.unpack("H*")[0]
|
282
284
|
|
@@ -295,7 +297,7 @@ module OpenSSL_EC
|
|
295
297
|
EC_KEY_set_private_key(eckey, priv_key)
|
296
298
|
EC_KEY_set_public_key(eckey, pub_key)
|
297
299
|
|
298
|
-
signature = ECDSA_do_sign(
|
300
|
+
signature = ECDSA_do_sign(msg32, msg32.size, eckey)
|
299
301
|
|
300
302
|
BN_free(order)
|
301
303
|
BN_CTX_free(ctx)
|
@@ -309,7 +311,7 @@ module OpenSSL_EC
|
|
309
311
|
if signature.get_array_of_pointer(0, 2).all?{|i| BN_num_bits(i) <= 256 }
|
310
312
|
4.times{|i|
|
311
313
|
head = [ 27 + i + (pubkey_compressed ? 4 : 0) ].pack("C")
|
312
|
-
if public_key_hex == recover_public_key_from_signature(
|
314
|
+
if public_key_hex == recover_public_key_from_signature(msg32.read_string(32), [head, r, s].join, i, pubkey_compressed)
|
313
315
|
rec_id = i; break
|
314
316
|
end
|
315
317
|
}
|
@@ -322,14 +324,13 @@ module OpenSSL_EC
|
|
322
324
|
|
323
325
|
def self.recover_compact(hash, signature)
|
324
326
|
return false if signature.bytesize != 65
|
325
|
-
|
326
|
-
#pubkey = recover_public_key_from_signature(hash, signature, (i & ~4), i >= 4)
|
327
|
+
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hash)
|
327
328
|
|
328
329
|
version = signature.unpack('C')[0]
|
329
330
|
return false if version < 27 or version > 34
|
330
331
|
|
331
332
|
compressed = (version >= 31) ? (version -= 4; true) : false
|
332
|
-
pubkey = recover_public_key_from_signature(
|
333
|
+
pubkey = recover_public_key_from_signature(msg32.read_string(32), signature, version-27, compressed)
|
333
334
|
end
|
334
335
|
|
335
336
|
# lifted from https://github.com/GemHQ/money-tree
|
@@ -1,8 +1,15 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
# bindings for secp256k1 inside bitcoin (https://github.com/bitcoin/bitcoin/tree/v0.
|
4
|
-
# tag: v0.
|
5
|
-
# commit:
|
3
|
+
# bindings for secp256k1 inside bitcoin (https://github.com/bitcoin/bitcoin/tree/v0.13.1/src/secp256k1)
|
4
|
+
# tag: v0.13.1
|
5
|
+
# commit: 03422e564b552c1d3c16ae854f8471f7cb39e25d
|
6
|
+
# bitcoin@master% git checkout v0.13.1
|
7
|
+
# bitcoin@tags/v0.13.1^0% cd src/secp256k1
|
8
|
+
# bitcoin@tags/v0.13.1^0 src/secp256k1% ./autogen.sh
|
9
|
+
# bitcoin@tags/v0.13.1^0 src/secp256k1% ./configure --enable-module-recovery
|
10
|
+
# bitcoin@tags/v0.13.1^0 src/secp256k1% make libsecp256k1.la
|
11
|
+
# bitcoin@tags/v0.13.1^0 src/secp256k1% nm -D .libs/libsecp256k1.so.0.0.0 | grep secp
|
12
|
+
# export SECP256K1_LIB_PATH=/path/to/bitcoin/src/secp256k1/.libs/libsecp256k1.so.0.0.0
|
6
13
|
|
7
14
|
require 'ffi'
|
8
15
|
|
@@ -10,70 +17,82 @@ module Bitcoin
|
|
10
17
|
module Secp256k1
|
11
18
|
extend FFI::Library
|
12
19
|
|
13
|
-
|
14
|
-
|
20
|
+
SECP256K1_FLAGS_TYPE_MASK = ((1 << 8) - 1)
|
21
|
+
SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0)
|
22
|
+
SECP256K1_FLAGS_TYPE_COMPRESSION = (1 << 1)
|
23
|
+
|
24
|
+
# The higher bits contain the actual data. Do not use directly.
|
25
|
+
SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8)
|
26
|
+
SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9)
|
27
|
+
SECP256K1_FLAGS_BIT_COMPRESSION = (1 << 8)
|
28
|
+
|
29
|
+
# Flags to pass to secp256k1_context_create.
|
30
|
+
SECP256K1_CONTEXT_VERIFY = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
|
31
|
+
SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
|
32
|
+
|
33
|
+
# Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export.
|
34
|
+
SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
|
35
|
+
SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION)
|
15
36
|
|
16
37
|
def self.ffi_load_functions(file)
|
17
38
|
class_eval <<-RUBY
|
18
39
|
ffi_lib [ %[#{file}] ]
|
19
40
|
|
20
41
|
##
|
21
|
-
# source: https://github.com/bitcoin/bitcoin/blob/v0.
|
42
|
+
# source: https://github.com/bitcoin/bitcoin/blob/v0.13.1/src/secp256k1/include/secp256k1.h
|
22
43
|
##
|
23
44
|
|
24
|
-
#
|
25
|
-
attach_function :secp256k1_context_create, [:
|
45
|
+
# secp256k1_context* secp256k1_context_create(unsigned int flags)
|
46
|
+
attach_function :secp256k1_context_create, [:uint], :pointer
|
26
47
|
|
27
|
-
#
|
28
|
-
attach_function :secp256k1_context_clone, [:pointer], :pointer
|
29
|
-
|
30
|
-
# void secp256k1_context_destroy(secp256k1_context_t* ctx)
|
48
|
+
# void secp256k1_context_destroy(secp256k1_context* ctx)
|
31
49
|
attach_function :secp256k1_context_destroy, [:pointer], :void
|
32
50
|
|
33
|
-
# int
|
34
|
-
attach_function :
|
51
|
+
# int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32)
|
52
|
+
attach_function :secp256k1_context_randomize, [:pointer, :pointer], :int
|
35
53
|
|
36
|
-
# int
|
37
|
-
attach_function :
|
54
|
+
# int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey)
|
55
|
+
attach_function :secp256k1_ec_seckey_verify, [:pointer, :pointer], :int
|
38
56
|
|
39
|
-
# int
|
40
|
-
attach_function :
|
57
|
+
# int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey)
|
58
|
+
attach_function :secp256k1_ec_pubkey_create, [:pointer, :pointer, :pointer], :int
|
41
59
|
|
42
|
-
# int
|
43
|
-
attach_function :
|
60
|
+
# int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags)
|
61
|
+
attach_function :secp256k1_ec_pubkey_serialize, [:pointer, :pointer, :pointer, :pointer, :uint], :int
|
44
62
|
|
45
|
-
# int
|
46
|
-
attach_function :
|
63
|
+
# int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata)
|
64
|
+
attach_function :secp256k1_ecdsa_sign_recoverable, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
|
47
65
|
|
48
|
-
# int
|
49
|
-
attach_function :
|
66
|
+
# int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig)
|
67
|
+
attach_function :secp256k1_ecdsa_recoverable_signature_serialize_compact, [:pointer, :pointer, :pointer, :pointer], :int
|
50
68
|
|
51
|
-
# int
|
52
|
-
attach_function :
|
69
|
+
# int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid)
|
70
|
+
attach_function :secp256k1_ecdsa_recoverable_signature_parse_compact, [:pointer, :pointer, :pointer, :int], :int
|
53
71
|
|
54
|
-
# int
|
55
|
-
attach_function :
|
72
|
+
# int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *msg32)
|
73
|
+
attach_function :secp256k1_ecdsa_recover, [:pointer, :pointer, :pointer, :pointer], :int
|
56
74
|
|
57
|
-
# int
|
58
|
-
attach_function :
|
75
|
+
# int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata)
|
76
|
+
attach_function :secp256k1_ecdsa_sign, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
|
59
77
|
|
60
|
-
# int
|
61
|
-
attach_function :
|
78
|
+
# int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig)
|
79
|
+
attach_function :secp256k1_ecdsa_signature_serialize_der, [:pointer, :pointer, :pointer, :pointer], :int
|
62
80
|
|
63
|
-
# int
|
64
|
-
attach_function :
|
81
|
+
# int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen)
|
82
|
+
attach_function :secp256k1_ec_pubkey_parse, [:pointer, :pointer, :pointer, :size_t], :int
|
65
83
|
|
66
|
-
# int
|
67
|
-
attach_function :
|
84
|
+
# int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin)
|
85
|
+
attach_function :secp256k1_ecdsa_signature_normalize, [:pointer, :pointer, :pointer], :int
|
68
86
|
|
69
|
-
# int
|
70
|
-
attach_function :
|
87
|
+
# int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey)
|
88
|
+
attach_function :secp256k1_ecdsa_verify, [:pointer, :pointer, :pointer, :pointer], :int
|
71
89
|
|
72
|
-
# int
|
73
|
-
attach_function :
|
90
|
+
# int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen)
|
91
|
+
attach_function :secp256k1_ecdsa_signature_parse_der, [:pointer, :pointer, :pointer, :size_t], :int
|
74
92
|
|
75
|
-
#
|
76
|
-
|
93
|
+
# TODO: add or port
|
94
|
+
# # int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen)
|
95
|
+
# attach_function :ecdsa_signature_parse_der_lax, [:pointer, :pointer, :pointer, :size_t], :int
|
77
96
|
RUBY
|
78
97
|
end
|
79
98
|
|
@@ -86,7 +105,7 @@ module Bitcoin
|
|
86
105
|
|
87
106
|
def self.with_context(flags=nil, seed=nil)
|
88
107
|
init
|
89
|
-
flags = flags || (
|
108
|
+
flags = flags || (SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN)
|
90
109
|
context = secp256k1_context_create(flags)
|
91
110
|
|
92
111
|
ret, tries, max = 0, 0, 20
|
@@ -109,15 +128,25 @@ module Bitcoin
|
|
109
128
|
raise "secp256k1_ec_seckey_verify in generate_key_pair failed." if tries >= max
|
110
129
|
tries += 1
|
111
130
|
|
112
|
-
|
113
|
-
ret = secp256k1_ec_seckey_verify(context,
|
131
|
+
seckey = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, SecureRandom.random_bytes(32))
|
132
|
+
ret = secp256k1_ec_seckey_verify(context, seckey)
|
114
133
|
end
|
115
134
|
|
116
|
-
|
117
|
-
result = secp256k1_ec_pubkey_create(context,
|
135
|
+
internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
|
136
|
+
result = secp256k1_ec_pubkey_create(context, internal_pubkey, seckey)
|
118
137
|
raise "error creating pubkey" unless result
|
119
138
|
|
120
|
-
|
139
|
+
pubkey, pubkey_len = FFI::MemoryPointer.new(:uchar, 65), FFI::MemoryPointer.new(:uint64)
|
140
|
+
result = if compressed
|
141
|
+
pubkey_len.put_uint64(0, 33)
|
142
|
+
secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_COMPRESSED)
|
143
|
+
else
|
144
|
+
pubkey_len.put_uint64(0, 65)
|
145
|
+
secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
|
146
|
+
end
|
147
|
+
raise "error serialize pubkey" unless result || pubkey_len.read_uint64 > 0
|
148
|
+
|
149
|
+
[ seckey.read_string(32), pubkey.read_string(pubkey_len.read_uint64) ]
|
121
150
|
end
|
122
151
|
end
|
123
152
|
|
@@ -128,53 +157,77 @@ module Bitcoin
|
|
128
157
|
|
129
158
|
def self.sign(data, priv_key)
|
130
159
|
with_context do |context|
|
131
|
-
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
|
132
160
|
seckey = FFI::MemoryPointer.new(:uchar, priv_key.bytesize).put_bytes(0, priv_key)
|
133
161
|
raise "priv_key invalid" unless secp256k1_ec_seckey_verify(context, seckey)
|
134
162
|
|
135
|
-
|
163
|
+
internal_signature = FFI::MemoryPointer.new(:uchar, 64)
|
164
|
+
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
|
136
165
|
|
137
|
-
|
138
|
-
|
166
|
+
ret, tries, max = 0, 0, 20
|
167
|
+
while ret != 1
|
168
|
+
raise "secp256k1_ecdsa_sign failed." if tries >= max
|
169
|
+
tries += 1
|
170
|
+
|
171
|
+
ret = secp256k1_ecdsa_sign(context, internal_signature, msg32, seckey, nil, nil)
|
139
172
|
end
|
140
173
|
|
141
|
-
|
174
|
+
signature, signature_len = FFI::MemoryPointer.new(:uchar, 72), FFI::MemoryPointer.new(:uint64).put_uint64(0, 72)
|
175
|
+
result = secp256k1_ecdsa_signature_serialize_der(context, signature, signature_len, internal_signature)
|
176
|
+
raise "secp256k1_ecdsa_signature_serialize_der failed" unless result
|
177
|
+
|
178
|
+
signature.read_string(signature_len.read_uint64)
|
142
179
|
end
|
143
180
|
end
|
144
181
|
|
145
|
-
def self.verify(data,
|
182
|
+
def self.verify(data, sig, pub_key)
|
146
183
|
with_context do |context|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
result =
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
184
|
+
return false if data.bytesize == 0
|
185
|
+
|
186
|
+
pubkey = FFI::MemoryPointer.new(:uchar, pub_key.bytesize).put_bytes(0, pub_key)
|
187
|
+
internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
|
188
|
+
result = secp256k1_ec_pubkey_parse(context, internal_pubkey, pubkey, pubkey.size)
|
189
|
+
return false unless result
|
190
|
+
|
191
|
+
signature = FFI::MemoryPointer.new(:uchar, sig.bytesize).put_bytes(0, sig)
|
192
|
+
internal_signature = FFI::MemoryPointer.new(:uchar, 64)
|
193
|
+
result = secp256k1_ecdsa_signature_parse_der(context, internal_signature, signature, signature.size)
|
194
|
+
#result = ecdsa_signature_parse_der_lax(context, internal_signature, signature, signature.size)
|
195
|
+
return false unless result
|
196
|
+
|
197
|
+
# libsecp256k1's ECDSA verification requires lower-S signatures, which have not historically been enforced in Bitcoin, so normalize them first.
|
198
|
+
secp256k1_ecdsa_signature_normalize(context, internal_signature, internal_signature)
|
199
|
+
|
200
|
+
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
|
201
|
+
result = secp256k1_ecdsa_verify(context, internal_signature, msg32, internal_pubkey)
|
202
|
+
|
203
|
+
return result ? true : false
|
160
204
|
end
|
161
205
|
end
|
162
206
|
|
163
207
|
def self.sign_compact(message, priv_key, compressed=true)
|
164
208
|
with_context do |context|
|
165
|
-
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, message)
|
166
|
-
sig64 = FFI::MemoryPointer.new(:uchar, 64)
|
167
|
-
rec_id = FFI::MemoryPointer.new(:int)
|
168
|
-
|
169
209
|
seckey = FFI::MemoryPointer.new(:uchar, priv_key.bytesize).put_bytes(0, priv_key)
|
170
210
|
raise "priv_key invalid" unless secp256k1_ec_seckey_verify(context, seckey)
|
171
211
|
|
172
|
-
|
173
|
-
|
212
|
+
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, message)
|
213
|
+
internal_recoverable_signature = FFI::MemoryPointer.new(:uchar, 65)
|
214
|
+
rec_id = FFI::MemoryPointer.new(:int).put_int(0, -1)
|
215
|
+
|
216
|
+
ret, tries, max = 0, 0, 20
|
217
|
+
while ret != 1
|
218
|
+
raise "secp256k1_ecdsa_sign_recoverable failed." if tries >= max
|
219
|
+
tries += 1
|
220
|
+
|
221
|
+
ret = secp256k1_ecdsa_sign_recoverable(context, internal_recoverable_signature, msg32, seckey, nil, nil)
|
174
222
|
end
|
175
223
|
|
224
|
+
recoverable_signature = FFI::MemoryPointer.new(:uchar, 64)
|
225
|
+
result = secp256k1_ecdsa_recoverable_signature_serialize_compact(context, recoverable_signature, rec_id, internal_recoverable_signature)
|
226
|
+
raise "secp256k1_ecdsa_recoverable_signature_serialize_compact failed" unless result
|
227
|
+
raise "secp256k1_ecdsa_recoverable_signature_serialize_compact failed" unless rec_id.read_int != -1
|
228
|
+
|
176
229
|
header = [27 + rec_id.read_int + (compressed ? 4 : 0)].pack("C")
|
177
|
-
[ header,
|
230
|
+
[ header, recoverable_signature.read_string(64) ].join
|
178
231
|
end
|
179
232
|
end
|
180
233
|
|
@@ -186,19 +239,26 @@ module Bitcoin
|
|
186
239
|
return nil if version < 27 || version > 34
|
187
240
|
|
188
241
|
compressed = version >= 31 ? true : false
|
242
|
+
flag = compressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED
|
189
243
|
version -= 4 if compressed
|
190
244
|
|
191
245
|
recid = version - 27
|
192
246
|
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, message)
|
193
|
-
|
194
|
-
pubkey = FFI::MemoryPointer.new(:uchar, pub_key_len = compressed ? 33 : 65)
|
195
|
-
pubkeylen = FFI::MemoryPointer.new(:int).write_int(pub_key_len)
|
247
|
+
recoverable_signature = FFI::MemoryPointer.new(:uchar, 64).put_bytes(0, signature[1..-1])
|
196
248
|
|
197
|
-
|
249
|
+
internal_recoverable_signature = FFI::MemoryPointer.new(:uchar, 65)
|
250
|
+
result = secp256k1_ecdsa_recoverable_signature_parse_compact(context, internal_recoverable_signature, recoverable_signature, recid)
|
251
|
+
return nil unless result
|
198
252
|
|
253
|
+
internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
|
254
|
+
result = secp256k1_ecdsa_recover(context, internal_pubkey, internal_recoverable_signature, msg32)
|
199
255
|
return nil unless result
|
200
256
|
|
201
|
-
pubkey.
|
257
|
+
pubkey, pubkey_len = FFI::MemoryPointer.new(:uchar, 65), FFI::MemoryPointer.new(:uint64).put_uint64(0, 65)
|
258
|
+
result = secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, flag)
|
259
|
+
raise "error serialize pubkey" unless result || pubkey_len.read_uint64 > 0
|
260
|
+
|
261
|
+
pubkey.read_string(pubkey_len.read_uint64)
|
202
262
|
end
|
203
263
|
end
|
204
264
|
|
data/lib/bitcoin/version.rb
CHANGED
@@ -27,6 +27,7 @@ describe 'libsecp256k1' do
|
|
27
27
|
priv, pub = Bitcoin::Secp256k1.generate_key_pair
|
28
28
|
signature = Bitcoin::Secp256k1.sign("derp", priv)
|
29
29
|
Bitcoin::Secp256k1.verify("derp", signature, pub).should == true
|
30
|
+
Bitcoin::Secp256k1.verify("DERP", signature, pub).should == true
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'sign compact and recover' do
|
@@ -51,6 +52,27 @@ describe 'libsecp256k1' do
|
|
51
52
|
first = Bitcoin::Secp256k1.sign("derp", priv)
|
52
53
|
second = Bitcoin::Secp256k1.sign("derp", priv)
|
53
54
|
first.should == second
|
55
|
+
|
56
|
+
priv, pub = Bitcoin::Secp256k1.generate_key_pair
|
57
|
+
second = Bitcoin::Secp256k1.sign("derp", priv)
|
58
|
+
first.should != second
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'openssl vs Secp256k1' do
|
62
|
+
k = Bitcoin::Key.new("82a0c421a0f67c7a88a329b2c15f2849aa1c8cfa9c9a6513f056f80ee8eaacc4", nil, compresed=false); k.pub
|
63
|
+
k.pub.should == "0490b0854581a291b83c1945775f156da22445df99e445581321ac3aa62535ff369334316dfd157acc7bb2e4d3eb85951f6d1b7f62f6f60a09e0dbd5c87d3ffae9"
|
64
|
+
|
65
|
+
message = "hello world"
|
66
|
+
priv = [k.priv].pack("H*")
|
67
|
+
|
68
|
+
sig1 = Bitcoin::OpenSSL_EC.sign_compact(message, priv, nil, compressed=false)
|
69
|
+
sig2 = Bitcoin::Secp256k1.sign_compact(message, priv, compressed=false)
|
70
|
+
|
71
|
+
Bitcoin::OpenSSL_EC.recover_compact(message, sig1).should == k.pub
|
72
|
+
Bitcoin::Secp256k1.recover_compact(message, sig1).unpack("H*")[0].should == k.pub
|
73
|
+
|
74
|
+
Bitcoin::OpenSSL_EC.recover_compact(message, sig2).should == k.pub
|
75
|
+
Bitcoin::Secp256k1.recover_compact(message, sig2).unpack("H*")[0] == k.pub
|
54
76
|
end
|
55
77
|
|
56
78
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitcoin-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- lian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: This is a ruby library for interacting with the bitcoin protocol/network
|
14
14
|
email:
|
@@ -245,7 +245,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
245
245
|
version: 1.3.6
|
246
246
|
requirements: []
|
247
247
|
rubyforge_project: bitcoin-ruby
|
248
|
-
rubygems_version: 2.5.
|
248
|
+
rubygems_version: 2.5.2
|
249
249
|
signing_key:
|
250
250
|
specification_version: 4
|
251
251
|
summary: bitcoin utils and protocol in ruby
|