digix-eth 0.5.6 → 0.5.7
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 +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.
|