eth 0.4.17 → 0.5.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.
data/lib/eth/open_ssl.rb DELETED
@@ -1,264 +0,0 @@
1
- # originally lifted from https://github.com/lian/bitcoin-ruby
2
- # thanks to everyone there for figuring this out
3
-
4
- module Eth
5
- class OpenSsl
6
- extend FFI::Library
7
-
8
- if FFI::Platform.windows?
9
- ffi_lib 'libeay32', 'ssleay32'
10
- else
11
- ffi_lib [
12
- 'libssl.so.1.1.0', 'libssl.so.1.1',
13
- 'libssl.so.1.0.0', 'libssl.so.10',
14
- 'ssl'
15
- ]
16
- end
17
-
18
- NID_secp256k1 = 714
19
- POINT_CONVERSION_COMPRESSED = 2
20
- POINT_CONVERSION_UNCOMPRESSED = 4
21
-
22
- # OpenSSL 1.1.0 version as a numerical version value as defined in:
23
- # https://www.openssl.org/docs/man1.1.0/man3/OpenSSL_version.html
24
- VERSION_1_1_0_NUM = 0x10100000
25
-
26
- # OpenSSL 1.1.0 engine constants, taken from:
27
- # https://github.com/openssl/openssl/blob/2be8c56a39b0ec2ec5af6ceaf729df154d784a43/include/openssl/crypto.h
28
- OPENSSL_INIT_ENGINE_RDRAND = 0x00000200
29
- OPENSSL_INIT_ENGINE_DYNAMIC = 0x00000400
30
- OPENSSL_INIT_ENGINE_CRYPTODEV = 0x00001000
31
- OPENSSL_INIT_ENGINE_CAPI = 0x00002000
32
- OPENSSL_INIT_ENGINE_PADLOCK = 0x00004000
33
- OPENSSL_INIT_ENGINE_ALL_BUILTIN = (
34
- OPENSSL_INIT_ENGINE_RDRAND |
35
- OPENSSL_INIT_ENGINE_DYNAMIC |
36
- OPENSSL_INIT_ENGINE_CRYPTODEV |
37
- OPENSSL_INIT_ENGINE_CAPI |
38
- OPENSSL_INIT_ENGINE_PADLOCK
39
- )
40
-
41
- # OpenSSL 1.1.0 load strings constant, taken from:
42
- # https://github.com/openssl/openssl/blob/c162c126be342b8cd97996346598ecf7db56130f/include/openssl/ssl.h
43
- OPENSSL_INIT_LOAD_SSL_STRINGS = 0x00200000
44
-
45
- # This is the very first function we need to use to determine what version
46
- # of OpenSSL we are interacting with.
47
- begin
48
- attach_function :OpenSSL_version_num, [], :ulong
49
- rescue FFI::NotFoundError
50
- attach_function :SSLeay, [], :long
51
- end
52
-
53
- # Returns the version of SSL present.
54
- #
55
- # @return [Integer] version number as an integer.
56
- def self.version
57
- if self.respond_to?(:OpenSSL_version_num)
58
- OpenSSL_version_num()
59
- else
60
- SSLeay()
61
- end
62
- end
63
-
64
- if version >= VERSION_1_1_0_NUM
65
- # Initialization procedure for the library was changed in OpenSSL 1.1.0
66
- attach_function :OPENSSL_init_ssl, [:uint64, :pointer], :int
67
- else
68
- attach_function :SSL_library_init, [], :int
69
- attach_function :ERR_load_crypto_strings, [], :void
70
- attach_function :SSL_load_error_strings, [], :void
71
- end
72
-
73
- attach_function :RAND_poll, [], :int
74
- attach_function :BN_CTX_free, [:pointer], :int
75
- attach_function :BN_CTX_new, [], :pointer
76
- attach_function :BN_add, [:pointer, :pointer, :pointer], :int
77
- attach_function :BN_bin2bn, [:pointer, :int, :pointer], :pointer
78
- attach_function :BN_bn2bin, [:pointer, :pointer], :int
79
- attach_function :BN_cmp, [:pointer, :pointer], :int
80
- attach_function :BN_dup, [:pointer], :pointer
81
- attach_function :BN_free, [:pointer], :int
82
- attach_function :BN_mod_inverse, [:pointer, :pointer, :pointer, :pointer], :pointer
83
- attach_function :BN_mod_mul, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
84
- attach_function :BN_mod_sub, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
85
- attach_function :BN_mul_word, [:pointer, :int], :int
86
- attach_function :BN_new, [], :pointer
87
- attach_function :BN_num_bits, [:pointer], :int
88
- attach_function :BN_rshift, [:pointer, :pointer, :int], :int
89
- attach_function :BN_set_word, [:pointer, :int], :int
90
- attach_function :ECDSA_SIG_free, [:pointer], :void
91
- attach_function :ECDSA_do_sign, [:pointer, :uint, :pointer], :pointer
92
- attach_function :EC_GROUP_get_curve_GFp, [:pointer, :pointer, :pointer, :pointer, :pointer], :int
93
- attach_function :EC_GROUP_get_degree, [:pointer], :int
94
- attach_function :EC_GROUP_get_order, [:pointer, :pointer, :pointer], :int
95
- attach_function :EC_KEY_free, [:pointer], :int
96
- attach_function :EC_KEY_get0_group, [:pointer], :pointer
97
- attach_function :EC_KEY_new_by_curve_name, [:int], :pointer
98
- attach_function :EC_KEY_set_conv_form, [:pointer, :int], :void
99
- attach_function :EC_KEY_set_private_key, [:pointer, :pointer], :int
100
- attach_function :EC_KEY_set_public_key, [:pointer, :pointer], :int
101
- attach_function :EC_POINT_free, [:pointer], :int
102
- attach_function :EC_POINT_mul, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
103
- attach_function :EC_POINT_new, [:pointer], :pointer
104
- attach_function :EC_POINT_set_compressed_coordinates_GFp, [:pointer, :pointer, :pointer, :int, :pointer], :int
105
- attach_function :i2o_ECPublicKey, [:pointer, :pointer], :uint
106
-
107
- class << self
108
- def BN_num_bytes(ptr)
109
- (BN_num_bits(ptr) + 7) / 8
110
- end
111
-
112
- def sign_compact(hash, private_key, public_key_hex)
113
- private_key = [private_key].pack("H*") if private_key.bytesize >= 64
114
- pubkey_compressed = false
115
-
116
- init_ffi_ssl
117
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
118
- priv_key = BN_bin2bn(private_key, private_key.bytesize, BN_new())
119
-
120
- group, order, ctx = EC_KEY_get0_group(eckey), BN_new(), BN_CTX_new()
121
- EC_GROUP_get_order(group, order, ctx)
122
-
123
- pub_key = EC_POINT_new(group)
124
- EC_POINT_mul(group, pub_key, priv_key, nil, nil, ctx)
125
- EC_KEY_set_private_key(eckey, priv_key)
126
- EC_KEY_set_public_key(eckey, pub_key)
127
-
128
- signature = ECDSA_do_sign(hash, hash.bytesize, eckey)
129
-
130
- BN_free(order)
131
- BN_CTX_free(ctx)
132
- EC_POINT_free(pub_key)
133
- BN_free(priv_key)
134
- EC_KEY_free(eckey)
135
-
136
- buf, rec_id, head = FFI::MemoryPointer.new(:uint8, 32), nil, nil
137
- 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") }
138
-
139
- if signature.get_array_of_pointer(0, 2).all?{|i| BN_num_bits(i) <= 256 }
140
- 4.times{|i|
141
- head = [ Eth.v_base + i ].pack("C")
142
- if public_key_hex == recover_public_key_from_signature(hash, [head, r, s].join, i, pubkey_compressed)
143
- rec_id = i; break
144
- end
145
- }
146
- end
147
-
148
- ECDSA_SIG_free(signature)
149
-
150
- [ head, [r,s] ].join if rec_id
151
- end
152
-
153
- def recover_public_key_from_signature(message_hash, signature, rec_id, is_compressed)
154
- return nil if rec_id < 0 or signature.bytesize != 65
155
- init_ffi_ssl
156
-
157
- signature = FFI::MemoryPointer.from_string(signature)
158
- r = BN_bin2bn(signature[1], 32, BN_new())
159
- s = BN_bin2bn(signature[33], 32, BN_new())
160
-
161
- _n, i = 0, rec_id / 2
162
- eckey = EC_KEY_new_by_curve_name(NID_secp256k1)
163
-
164
- EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED) if is_compressed
165
-
166
- group = EC_KEY_get0_group(eckey)
167
- order = BN_new()
168
- EC_GROUP_get_order(group, order, nil)
169
- x = BN_dup(order)
170
- BN_mul_word(x, i)
171
- BN_add(x, x, r)
172
-
173
- field = BN_new()
174
- EC_GROUP_get_curve_GFp(group, field, nil, nil, nil)
175
-
176
- if BN_cmp(x, field) >= 0
177
- bn_free_each r, s, order, x, field
178
- EC_KEY_free(eckey)
179
- return nil
180
- end
181
-
182
- big_r = EC_POINT_new(group)
183
- EC_POINT_set_compressed_coordinates_GFp(group, big_r, x, rec_id % 2, nil)
184
-
185
- big_q = EC_POINT_new(group)
186
- n = EC_GROUP_get_degree(group)
187
- e = BN_bin2bn(message_hash, message_hash.bytesize, BN_new())
188
- BN_rshift(e, e, 8 - (n & 7)) if 8 * message_hash.bytesize > n
189
-
190
- ctx = BN_CTX_new()
191
- zero, rr, sor, eor = BN_new(), BN_new(), BN_new(), BN_new()
192
- BN_set_word(zero, 0)
193
- BN_mod_sub(e, zero, e, order, ctx)
194
- BN_mod_inverse(rr, r, order, ctx)
195
- BN_mod_mul(sor, s, rr, order, ctx)
196
- BN_mod_mul(eor, e, rr, order, ctx)
197
- EC_POINT_mul(group, big_q, eor, big_r, sor, ctx)
198
- EC_KEY_set_public_key(eckey, big_q)
199
- BN_CTX_free(ctx)
200
-
201
- bn_free_each r, s, order, x, field, e, zero, rr, sor, eor
202
- [big_r, big_q].each{|j| EC_POINT_free(j) }
203
-
204
- recover_public_hex eckey
205
- end
206
-
207
- def recover_compact(hash, signature)
208
- return false if signature.bytesize != 65
209
-
210
- version = signature.unpack('C')[0]
211
-
212
- # Version of signature should be 27 or 28, but 0 and 1 are also possible versions
213
- # which can show up in Ledger hardwallet signings
214
- if version < 27
215
- version += 27
216
- end
217
-
218
- v_base = Eth.replayable_v?(version) ? Eth.replayable_chain_id : Eth.v_base
219
-
220
- return false if version < v_base
221
-
222
- recover_public_key_from_signature(hash, signature, (version - v_base), false)
223
- end
224
-
225
- def init_ffi_ssl
226
- return if @ssl_loaded
227
- if version >= VERSION_1_1_0_NUM
228
- OPENSSL_init_ssl(
229
- OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_ENGINE_ALL_BUILTIN,
230
- nil
231
- )
232
- else
233
- SSL_library_init()
234
- ERR_load_crypto_strings()
235
- SSL_load_error_strings()
236
- end
237
-
238
- RAND_poll()
239
- @ssl_loaded = true
240
- end
241
-
242
-
243
- private
244
-
245
- def bn_free_each(*list)
246
- list.each{|j| BN_free(j) }
247
- end
248
-
249
- def recover_public_hex(eckey)
250
- length = i2o_ECPublicKey(eckey, nil)
251
- buf = FFI::MemoryPointer.new(:uint8, length)
252
- ptr = FFI::MemoryPointer.new(:pointer).put_pointer(0, buf)
253
- pub_hex = if i2o_ECPublicKey(eckey, ptr) == length
254
- buf.read_string(length).unpack("H*")[0]
255
- end
256
-
257
- EC_KEY_free(eckey)
258
-
259
- pub_hex
260
- end
261
- end
262
-
263
- end
264
- end
data/lib/eth/secp256k1.rb DELETED
@@ -1,7 +0,0 @@
1
- module Eth
2
- class Secp256k1
3
-
4
- N = 115792089237316195423570985008687907852837564279074904382605163141518161494337
5
-
6
- end
7
- end
data/lib/eth/sedes.rb DELETED
@@ -1,40 +0,0 @@
1
- module Eth
2
- module Sedes
3
- include RLP::Sedes
4
-
5
- extend self
6
-
7
- def address
8
- Binary.fixed_length(20, allow_empty: true)
9
- end
10
-
11
- def int20
12
- BigEndianInt.new(20)
13
- end
14
-
15
- def int32
16
- BigEndianInt.new(32)
17
- end
18
-
19
- def int256
20
- BigEndianInt.new(256)
21
- end
22
-
23
- def hash32
24
- Binary.fixed_length(32)
25
- end
26
-
27
- def trie_root
28
- Binary.fixed_length(32, allow_empty: true)
29
- end
30
-
31
- def big_endian_int
32
- RLP::Sedes.big_endian_int
33
- end
34
-
35
- def binary
36
- RLP::Sedes.binary
37
- end
38
-
39
- end
40
- end
data/lib/eth/utils.rb DELETED
@@ -1,129 +0,0 @@
1
- module Eth
2
- module Utils
3
- extend self
4
-
5
- def normalize_address(address)
6
- if address.nil? || address == ''
7
- ''
8
- elsif address.size == 40
9
- hex_to_bin address
10
- elsif address.size == 42 && address[0..1] == '0x'
11
- hex_to_bin address[2..-1]
12
- else
13
- address
14
- end
15
- end
16
-
17
- def bin_to_hex(string)
18
- RLP::Utils.encode_hex string
19
- end
20
-
21
- def hex_to_bin(string)
22
- RLP::Utils.decode_hex remove_hex_prefix(string)
23
- end
24
-
25
- def base256_to_int(str)
26
- RLP::Sedes.big_endian_int.deserialize str.sub(/\A(\x00)+/, '')
27
- end
28
-
29
- def int_to_base256(int)
30
- RLP::Sedes.big_endian_int.serialize int
31
- end
32
-
33
- def v_r_s_for(signature)
34
- [
35
- signature[0].bytes[0],
36
- Utils.base256_to_int(signature[1..32]),
37
- Utils.base256_to_int(signature[33..65]),
38
- ]
39
- end
40
-
41
- def prefix_hex(hex)
42
- hex.match(/\A0x/) ? hex : "0x#{hex}"
43
- end
44
-
45
- def remove_hex_prefix(s)
46
- s[0,2] == '0x' ? s[2..-1] : s
47
- end
48
-
49
- def bin_to_prefixed_hex(binary)
50
- prefix_hex bin_to_hex(binary)
51
- end
52
-
53
- def prefix_message(message)
54
- "\x19Ethereum Signed Message:\n#{message.length}#{message}"
55
- end
56
-
57
- def public_key_to_address(hex)
58
- bytes = hex_to_bin(hex)
59
- address_bytes = Utils.keccak256(bytes[1..-1])[-20..-1]
60
- format_address bin_to_prefixed_hex(address_bytes)
61
- end
62
-
63
- def sha256(x)
64
- Digest::SHA256.digest x
65
- end
66
-
67
- def keccak256(x)
68
- Digest::Keccak.new(256).digest(x)
69
- end
70
-
71
- def keccak512(x)
72
- Digest::Keccak.new(512).digest(x)
73
- end
74
-
75
- def keccak256_rlp(x)
76
- keccak256 RLP.encode(x)
77
- end
78
-
79
- def ripemd160(x)
80
- Digest::RMD160.digest x
81
- end
82
-
83
- def hash160(x)
84
- ripemd160 sha256(x)
85
- end
86
-
87
- def zpad(x, l)
88
- lpad x, BYTE_ZERO, l
89
- end
90
-
91
- def zunpad(x)
92
- x.sub(/\A\x00+/, '')
93
- end
94
-
95
- def zpad_int(n, l=32)
96
- zpad encode_int(n), l
97
- end
98
-
99
- def zpad_hex(s, l=32)
100
- zpad decode_hex(s), l
101
- end
102
-
103
- def valid_address?(address)
104
- Address.new(address).valid?
105
- end
106
-
107
- def format_address(address)
108
- Address.new(address).checksummed
109
- end
110
-
111
-
112
-
113
- private
114
-
115
- def lpad(x, symbol, l)
116
- return x if x.size >= l
117
- symbol * (l - x.size) + x
118
- end
119
-
120
- def encode_int(n)
121
- unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
122
- raise ArgumentError, "Integer invalid or out of range: #{n}"
123
- end
124
-
125
- int_to_base256 n
126
- end
127
-
128
- end
129
- end