digix-eth 0.5.6 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/eth.rb +1 -0
- data/lib/eth/key.rb +0 -18
- data/lib/eth/open_ssl.rb +114 -45
- data/lib/eth/rpc_signer.rb +8 -17
- data/lib/eth/signature.rb +1 -37
- data/lib/eth/utils.rb +0 -15
- data/lib/eth/version.rb +3 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 43a5e80aa64d950c81657c85b61b4a0babc7851241f6d17d85034638f1bb6e9a
|
4
|
+
data.tar.gz: 3a5bb0b47309bd0b9f581eed6bce46586cc11dfa097c83eca69de2a74c9dc3c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da241931604056061eede8aa5b522fc1d3edba48114539259d58b018b279da6720aed6be4042e81ddfd5a1a14882f295f0a7a7e715991a10b2160a1cd9b786f2
|
7
|
+
data.tar.gz: 157c851f34a50f92d2114748658c2c4fce00126e423a8810932bac218097dd8aed887536d0d7f30b1b699a3e8e80d51d776cc586a78f8e0df0a7bf9675862960
|
data/lib/eth.rb
CHANGED
data/lib/eth/key.rb
CHANGED
@@ -85,24 +85,6 @@ module Eth
|
|
85
85
|
public_hex == OpenSsl.recover_compact(hash, signature)
|
86
86
|
end
|
87
87
|
|
88
|
-
def get_signer_key(message, signature)
|
89
|
-
hash = message_hash(message)
|
90
|
-
signer_public_hex = OpenSsl.recover_compact(hash, signature)
|
91
|
-
signer_public_key = MoneyTree::PublicKey.new(signer_public_hex, compressed: false)
|
92
|
-
signer_key = Eth::Key.new
|
93
|
-
signer_key.public_key = signer_public_key
|
94
|
-
return signer_key
|
95
|
-
end
|
96
|
-
|
97
|
-
def verify_rpc_signature(message, signature, signer_address)
|
98
|
-
signer = get_signer_key(message, signature)
|
99
|
-
signer.address == signer_address
|
100
|
-
end
|
101
|
-
|
102
|
-
def verify_rpc_signature_no_prefix(message, signature, signer_address)
|
103
|
-
prefixed_message = Eth::Utils.prefix_message(message)
|
104
|
-
verify_rpc_signature(prefixed_message, signature, signer_address)
|
105
|
-
end
|
106
88
|
|
107
89
|
private
|
108
90
|
|
data/lib/eth/open_ssl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# originally lifted from https://github.com/lian/bitcoin-ruby
|
2
4
|
# thanks to everyone there for figuring this out
|
3
5
|
|
@@ -8,50 +10,101 @@ module Eth
|
|
8
10
|
if FFI::Platform.windows?
|
9
11
|
ffi_lib 'libeay32', 'ssleay32'
|
10
12
|
else
|
11
|
-
ffi_lib [
|
13
|
+
ffi_lib [
|
14
|
+
'libssl.so.1.1.0', 'libssl.so.1.1',
|
15
|
+
'libssl.so.1.0.0', 'libssl.so.10',
|
16
|
+
'ssl'
|
17
|
+
]
|
12
18
|
end
|
13
19
|
|
14
20
|
NID_secp256k1 = 714
|
15
21
|
POINT_CONVERSION_COMPRESSED = 2
|
16
22
|
POINT_CONVERSION_UNCOMPRESSED = 4
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
# OpenSSL 1.1.0 version as a numerical version value as defined in:
|
25
|
+
# https://www.openssl.org/docs/man1.1.0/man3/OpenSSL_version.html
|
26
|
+
VERSION_1_1_0_NUM = 0x10100000
|
27
|
+
|
28
|
+
# OpenSSL 1.1.0 engine constants, taken from:
|
29
|
+
# https://github.com/openssl/openssl/blob/2be8c56a39b0ec2ec5af6ceaf729df154d784a43/include/openssl/crypto.h
|
30
|
+
OPENSSL_INIT_ENGINE_RDRAND = 0x00000200
|
31
|
+
OPENSSL_INIT_ENGINE_DYNAMIC = 0x00000400
|
32
|
+
OPENSSL_INIT_ENGINE_CRYPTODEV = 0x00001000
|
33
|
+
OPENSSL_INIT_ENGINE_CAPI = 0x00002000
|
34
|
+
OPENSSL_INIT_ENGINE_PADLOCK = 0x00004000
|
35
|
+
OPENSSL_INIT_ENGINE_ALL_BUILTIN = (
|
36
|
+
OPENSSL_INIT_ENGINE_RDRAND |
|
37
|
+
OPENSSL_INIT_ENGINE_DYNAMIC |
|
38
|
+
OPENSSL_INIT_ENGINE_CRYPTODEV |
|
39
|
+
OPENSSL_INIT_ENGINE_CAPI |
|
40
|
+
OPENSSL_INIT_ENGINE_PADLOCK
|
41
|
+
)
|
42
|
+
|
43
|
+
# OpenSSL 1.1.0 load strings constant, taken from:
|
44
|
+
# https://github.com/openssl/openssl/blob/c162c126be342b8cd97996346598ecf7db56130f/include/openssl/ssl.h
|
45
|
+
OPENSSL_INIT_LOAD_SSL_STRINGS = 0x00200000
|
46
|
+
|
47
|
+
# This is the very first function we need to use to determine what version
|
48
|
+
# of OpenSSL we are interacting with.
|
49
|
+
begin
|
50
|
+
attach_function :OpenSSL_version_num, [], :ulong
|
51
|
+
rescue FFI::NotFoundError
|
52
|
+
attach_function :SSLeay, [], :long
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the version of SSL present.
|
56
|
+
#
|
57
|
+
# @return [Integer] version number as an integer.
|
58
|
+
def self.version
|
59
|
+
if respond_to?(:OpenSSL_version_num)
|
60
|
+
OpenSSL_version_num()
|
61
|
+
else
|
62
|
+
SSLeay()
|
63
|
+
end
|
64
|
+
end
|
22
65
|
|
66
|
+
if version >= VERSION_1_1_0_NUM
|
67
|
+
# Initialization procedure for the library was changed in OpenSSL 1.1.0
|
68
|
+
attach_function :OPENSSL_init_ssl, %i[uint64 pointer], :int
|
69
|
+
else
|
70
|
+
attach_function :SSL_library_init, [], :int
|
71
|
+
attach_function :ERR_load_crypto_strings, [], :void
|
72
|
+
attach_function :SSL_load_error_strings, [], :void
|
73
|
+
end
|
74
|
+
|
75
|
+
attach_function :RAND_poll, [], :int
|
23
76
|
attach_function :BN_CTX_free, [:pointer], :int
|
24
77
|
attach_function :BN_CTX_new, [], :pointer
|
25
|
-
attach_function :BN_add, [
|
26
|
-
attach_function :BN_bin2bn, [
|
27
|
-
attach_function :BN_bn2bin, [
|
28
|
-
attach_function :BN_cmp, [
|
78
|
+
attach_function :BN_add, %i[pointer pointer pointer], :int
|
79
|
+
attach_function :BN_bin2bn, %i[pointer int pointer], :pointer
|
80
|
+
attach_function :BN_bn2bin, %i[pointer pointer], :int
|
81
|
+
attach_function :BN_cmp, %i[pointer pointer], :int
|
29
82
|
attach_function :BN_dup, [:pointer], :pointer
|
30
83
|
attach_function :BN_free, [:pointer], :int
|
31
|
-
attach_function :BN_mod_inverse, [
|
32
|
-
attach_function :BN_mod_mul, [
|
33
|
-
attach_function :BN_mod_sub, [
|
34
|
-
attach_function :BN_mul_word, [
|
84
|
+
attach_function :BN_mod_inverse, %i[pointer pointer pointer pointer], :pointer
|
85
|
+
attach_function :BN_mod_mul, %i[pointer pointer pointer pointer pointer], :int
|
86
|
+
attach_function :BN_mod_sub, %i[pointer pointer pointer pointer pointer], :int
|
87
|
+
attach_function :BN_mul_word, %i[pointer int], :int
|
35
88
|
attach_function :BN_new, [], :pointer
|
36
89
|
attach_function :BN_num_bits, [:pointer], :int
|
37
|
-
attach_function :BN_rshift, [
|
38
|
-
attach_function :BN_set_word, [
|
90
|
+
attach_function :BN_rshift, %i[pointer pointer int], :int
|
91
|
+
attach_function :BN_set_word, %i[pointer int], :int
|
39
92
|
attach_function :ECDSA_SIG_free, [:pointer], :void
|
40
|
-
attach_function :ECDSA_do_sign, [
|
41
|
-
attach_function :EC_GROUP_get_curve_GFp, [
|
93
|
+
attach_function :ECDSA_do_sign, %i[pointer uint pointer], :pointer
|
94
|
+
attach_function :EC_GROUP_get_curve_GFp, %i[pointer pointer pointer pointer pointer], :int
|
42
95
|
attach_function :EC_GROUP_get_degree, [:pointer], :int
|
43
|
-
attach_function :EC_GROUP_get_order, [
|
96
|
+
attach_function :EC_GROUP_get_order, %i[pointer pointer pointer], :int
|
44
97
|
attach_function :EC_KEY_free, [:pointer], :int
|
45
98
|
attach_function :EC_KEY_get0_group, [:pointer], :pointer
|
46
99
|
attach_function :EC_KEY_new_by_curve_name, [:int], :pointer
|
47
|
-
attach_function :EC_KEY_set_conv_form, [
|
48
|
-
attach_function :EC_KEY_set_private_key, [
|
49
|
-
attach_function :EC_KEY_set_public_key, [
|
100
|
+
attach_function :EC_KEY_set_conv_form, %i[pointer int], :void
|
101
|
+
attach_function :EC_KEY_set_private_key, %i[pointer pointer], :int
|
102
|
+
attach_function :EC_KEY_set_public_key, %i[pointer pointer], :int
|
50
103
|
attach_function :EC_POINT_free, [:pointer], :int
|
51
|
-
attach_function :EC_POINT_mul, [
|
104
|
+
attach_function :EC_POINT_mul, %i[pointer pointer pointer pointer pointer pointer], :int
|
52
105
|
attach_function :EC_POINT_new, [:pointer], :pointer
|
53
|
-
attach_function :EC_POINT_set_compressed_coordinates_GFp, [
|
54
|
-
attach_function :i2o_ECPublicKey, [
|
106
|
+
attach_function :EC_POINT_set_compressed_coordinates_GFp, %i[pointer pointer pointer int pointer], :int
|
107
|
+
attach_function :i2o_ECPublicKey, %i[pointer pointer], :uint
|
55
108
|
|
56
109
|
class << self
|
57
110
|
def BN_num_bytes(ptr)
|
@@ -59,14 +112,16 @@ module Eth
|
|
59
112
|
end
|
60
113
|
|
61
114
|
def sign_compact(hash, private_key, public_key_hex)
|
62
|
-
private_key = [private_key].pack(
|
115
|
+
private_key = [private_key].pack('H*') if private_key.bytesize >= 64
|
63
116
|
pubkey_compressed = false
|
64
117
|
|
65
118
|
init_ffi_ssl
|
66
119
|
eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
|
67
120
|
priv_key = BN_bin2bn(private_key, private_key.bytesize, BN_new())
|
68
121
|
|
69
|
-
group
|
122
|
+
group = EC_KEY_get0_group(eckey)
|
123
|
+
order = BN_new()
|
124
|
+
ctx = BN_CTX_new()
|
70
125
|
EC_GROUP_get_order(group, order, ctx)
|
71
126
|
|
72
127
|
pub_key = EC_POINT_new(group)
|
@@ -82,32 +137,36 @@ module Eth
|
|
82
137
|
BN_free(priv_key)
|
83
138
|
EC_KEY_free(eckey)
|
84
139
|
|
85
|
-
buf
|
86
|
-
|
140
|
+
buf = FFI::MemoryPointer.new(:uint8, 32)
|
141
|
+
rec_id = nil
|
142
|
+
head = nil
|
143
|
+
r, s = signature.get_array_of_pointer(0, 2).map { |i| BN_bn2bin(i, buf); buf.read_string(BN_num_bytes(i)).rjust(32, "\x00") }
|
87
144
|
|
88
|
-
if signature.get_array_of_pointer(0, 2).all?{|i| BN_num_bits(i) <= 256 }
|
89
|
-
4.times
|
90
|
-
head = [
|
145
|
+
if signature.get_array_of_pointer(0, 2).all? { |i| BN_num_bits(i) <= 256 }
|
146
|
+
4.times do |i|
|
147
|
+
head = [Eth.v_base + i].pack('C')
|
91
148
|
if public_key_hex == recover_public_key_from_signature(hash, [head, r, s].join, i, pubkey_compressed)
|
92
149
|
rec_id = i; break
|
93
150
|
end
|
94
|
-
|
151
|
+
end
|
95
152
|
end
|
96
153
|
|
97
154
|
ECDSA_SIG_free(signature)
|
98
155
|
|
99
|
-
[
|
156
|
+
[head, [r, s]].join if rec_id
|
100
157
|
end
|
101
158
|
|
102
159
|
def recover_public_key_from_signature(message_hash, signature, rec_id, is_compressed)
|
103
|
-
return nil if rec_id < 0
|
160
|
+
return nil if (rec_id < 0) || (signature.bytesize != 65)
|
161
|
+
|
104
162
|
init_ffi_ssl
|
105
163
|
|
106
164
|
signature = FFI::MemoryPointer.from_string(signature)
|
107
165
|
r = BN_bin2bn(signature[1], 32, BN_new())
|
108
166
|
s = BN_bin2bn(signature[33], 32, BN_new())
|
109
167
|
|
110
|
-
_n
|
168
|
+
_n = 0
|
169
|
+
i = rec_id / 2
|
111
170
|
eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
|
112
171
|
|
113
172
|
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED) if is_compressed
|
@@ -137,7 +196,10 @@ module Eth
|
|
137
196
|
BN_rshift(e, e, 8 - (n & 7)) if 8 * message_hash.bytesize > n
|
138
197
|
|
139
198
|
ctx = BN_CTX_new()
|
140
|
-
zero
|
199
|
+
zero = BN_new()
|
200
|
+
rr = BN_new()
|
201
|
+
sor = BN_new()
|
202
|
+
eor = BN_new()
|
141
203
|
BN_set_word(zero, 0)
|
142
204
|
BN_mod_sub(e, zero, e, order, ctx)
|
143
205
|
BN_mod_inverse(rr, r, order, ctx)
|
@@ -148,7 +210,7 @@ module Eth
|
|
148
210
|
BN_CTX_free(ctx)
|
149
211
|
|
150
212
|
bn_free_each r, s, order, x, field, e, zero, rr, sor, eor
|
151
|
-
[big_r, big_q].each{|j| EC_POINT_free(j) }
|
213
|
+
[big_r, big_q].each { |j| EC_POINT_free(j) }
|
152
214
|
|
153
215
|
recover_public_hex eckey
|
154
216
|
end
|
@@ -165,18 +227,26 @@ module Eth
|
|
165
227
|
|
166
228
|
def init_ffi_ssl
|
167
229
|
return if @ssl_loaded
|
168
|
-
|
169
|
-
|
170
|
-
|
230
|
+
|
231
|
+
if version >= VERSION_1_1_0_NUM
|
232
|
+
OPENSSL_init_ssl(
|
233
|
+
OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_ENGINE_ALL_BUILTIN,
|
234
|
+
nil
|
235
|
+
)
|
236
|
+
else
|
237
|
+
SSL_library_init()
|
238
|
+
ERR_load_crypto_strings()
|
239
|
+
SSL_load_error_strings()
|
240
|
+
end
|
241
|
+
|
171
242
|
RAND_poll()
|
172
243
|
@ssl_loaded = true
|
173
244
|
end
|
174
245
|
|
175
|
-
|
176
246
|
private
|
177
247
|
|
178
248
|
def bn_free_each(*list)
|
179
|
-
list.each{|j| BN_free(j) }
|
249
|
+
list.each { |j| BN_free(j) }
|
180
250
|
end
|
181
251
|
|
182
252
|
def recover_public_hex(eckey)
|
@@ -184,14 +254,13 @@ module Eth
|
|
184
254
|
buf = FFI::MemoryPointer.new(:uint8, length)
|
185
255
|
ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
|
186
256
|
pub_hex = if i2o_ECPublicKey(eckey, ptr) == length
|
187
|
-
|
188
|
-
|
257
|
+
buf.read_string(length).unpack('H*')[0]
|
258
|
+
end
|
189
259
|
|
190
260
|
EC_KEY_free(eckey)
|
191
261
|
|
192
262
|
pub_hex
|
193
263
|
end
|
194
264
|
end
|
195
|
-
|
196
265
|
end
|
197
266
|
end
|
data/lib/eth/rpc_signer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Eth
|
2
2
|
class RpcSigner
|
3
3
|
|
4
|
+
|
4
5
|
attr_accessor :key
|
5
6
|
|
6
7
|
def initialize(key)
|
@@ -9,27 +10,17 @@ module Eth
|
|
9
10
|
|
10
11
|
def sign_message(message)
|
11
12
|
payload = Eth::Signature.new(message)
|
12
|
-
payload.
|
13
|
-
payload.
|
14
|
-
payload.
|
15
|
-
payload.signature = @key.
|
13
|
+
payload.prefixed_message = Eth::Utils.prefix_message(message)
|
14
|
+
payload.hash = Eth::Utils.keccak256(payload.prefixed_message)
|
15
|
+
payload.hash_hex = Eth::Utils.bin_to_prefixed_hex(payload.hash)
|
16
|
+
payload.signature = @key.sign(payload.prefixed_message)
|
17
|
+
payload.signature_hex = Eth::Utils.bin_to_prefixed_hex(payload.signature)
|
16
18
|
payload.v, payload.r, payload.s = Eth::Utils.v_r_s_for(payload.signature)
|
17
|
-
payload.
|
19
|
+
payload.rpc = Eth::Utils.zpad_int(payload.r, 32) + Eth::Utils.zpad_int(payload.s, 32) + [(payload.v - 27)].pack('C')
|
20
|
+
payload.rpc_hex = Eth::Utils.bin_to_prefixed_hex(payload.rpc)
|
18
21
|
return payload
|
19
22
|
end
|
20
23
|
|
21
|
-
class << self
|
22
|
-
|
23
|
-
|
24
|
-
def ecrecover_address(message_hash_hex, signature_hex)
|
25
|
-
message_hash = Eth::Utils.hex_to_bin(message_hash_hex)
|
26
|
-
signature = Eth::Utils.hex_to_bin(signature_hex)
|
27
|
-
public_key = Eth::OpenSsl.recover_compact(message_hash, signature)
|
28
|
-
signer = Eth::Utils.public_key_to_address(public_key)
|
29
|
-
return signer
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
24
|
end
|
34
25
|
|
35
26
|
|
data/lib/eth/signature.rb
CHANGED
@@ -1,43 +1,7 @@
|
|
1
|
-
class String
|
2
|
-
|
3
|
-
def to_urlsafe_base64
|
4
|
-
if is_hex?
|
5
|
-
Base64.urlsafe_encode64(Eth::Utils.hex_to_bin(self))
|
6
|
-
else
|
7
|
-
Base64.urlsafe_encode64(self)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def from_urlsafe_base64
|
12
|
-
Base64.urlsafe_decode64(self)
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_hex
|
16
|
-
if self.is_hex?
|
17
|
-
return self
|
18
|
-
else
|
19
|
-
Eth::Utils.bin_to_prefixed_hex(self)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def is_hex?
|
24
|
-
!self.gsub("0x", '')[/\H/]
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
1
|
module Eth
|
30
2
|
class Signature
|
31
3
|
|
32
|
-
attr_accessor :message,
|
33
|
-
:signer,
|
34
|
-
:padded_message,
|
35
|
-
:hash,
|
36
|
-
:signature,
|
37
|
-
:rpc_signature,
|
38
|
-
:v,
|
39
|
-
:r,
|
40
|
-
:s
|
4
|
+
attr_accessor :message, :signer, :prefixed_message, :hash, :hash_hex, :signature, :signature_hex, :rpc, :rpc_hex, :v, :r, :s
|
41
5
|
|
42
6
|
def initialize(message)
|
43
7
|
@message = message
|
data/lib/eth/utils.rb
CHANGED
@@ -37,21 +37,6 @@ module Eth
|
|
37
37
|
RLP::Sedes.big_endian_int.serialize int
|
38
38
|
end
|
39
39
|
|
40
|
-
def from_rpc_signature_hex(signature)
|
41
|
-
buffer = Eth::Utils.hex_to_bin(signature).bytes
|
42
|
-
if buffer.length != 65
|
43
|
-
raise ArgumentError.new('Invalid signature length')
|
44
|
-
end
|
45
|
-
v = buffer[64]
|
46
|
-
v += 27 if v < 27
|
47
|
-
r = buffer[0..32]
|
48
|
-
s = buffer[33..64]
|
49
|
-
signature = [v, r, s].flatten.pack('C*')
|
50
|
-
signature_hex = Eth::Utils.bin_to_prefixed_hex(signature)
|
51
|
-
payload = {v: v, r: r, s: s, signature: signature, signature_hex: signature_hex}
|
52
|
-
return payload
|
53
|
-
end
|
54
|
-
|
55
40
|
def v_r_s_for(signature)
|
56
41
|
[
|
57
42
|
signature[0].bytes[0],
|
data/lib/eth/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: digix-eth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Ellis
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-08-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: digest-sha3
|
@@ -221,8 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0'
|
223
223
|
requirements: []
|
224
|
-
|
225
|
-
rubygems_version: 2.6.12
|
224
|
+
rubygems_version: 3.0.3
|
226
225
|
signing_key:
|
227
226
|
specification_version: 4
|
228
227
|
summary: Simple API to sign Ethereum transactions.
|