bitcoin-ruby 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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
|