eth 0.4.12 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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,130 +0,0 @@
1
- module Eth
2
- module Utils
3
-
4
- extend self
5
-
6
- def normalize_address(address)
7
- if address.nil? || address == ''
8
- ''
9
- elsif address.size == 40
10
- hex_to_bin address
11
- elsif address.size == 42 && address[0..1] == '0x'
12
- hex_to_bin address[2..-1]
13
- else
14
- address
15
- end
16
- end
17
-
18
- def bin_to_hex(string)
19
- RLP::Utils.encode_hex string
20
- end
21
-
22
- def hex_to_bin(string)
23
- RLP::Utils.decode_hex remove_hex_prefix(string)
24
- end
25
-
26
- def base256_to_int(str)
27
- RLP::Sedes.big_endian_int.deserialize str.sub(/\A(\x00)+/, '')
28
- end
29
-
30
- def int_to_base256(int)
31
- RLP::Sedes.big_endian_int.serialize int
32
- end
33
-
34
- def v_r_s_for(signature)
35
- [
36
- signature[0].bytes[0],
37
- Utils.base256_to_int(signature[1..32]),
38
- Utils.base256_to_int(signature[33..65]),
39
- ]
40
- end
41
-
42
- def prefix_hex(hex)
43
- hex.match(/\A0x/) ? hex : "0x#{hex}"
44
- end
45
-
46
- def remove_hex_prefix(s)
47
- s[0,2] == '0x' ? s[2..-1] : s
48
- end
49
-
50
- def bin_to_prefixed_hex(binary)
51
- prefix_hex bin_to_hex(binary)
52
- end
53
-
54
- def prefix_message(message)
55
- "\x19Ethereum Signed Message:\n#{message.length}#{message}"
56
- end
57
-
58
- def public_key_to_address(hex)
59
- bytes = hex_to_bin(hex)
60
- address_bytes = Utils.keccak256(bytes[1..-1])[-20..-1]
61
- format_address bin_to_prefixed_hex(address_bytes)
62
- end
63
-
64
- def sha256(x)
65
- Digest::SHA256.digest x
66
- end
67
-
68
- def keccak256(x)
69
- Digest::SHA3.new(256).digest(x)
70
- end
71
-
72
- def keccak512(x)
73
- Digest::SHA3.new(512).digest(x)
74
- end
75
-
76
- def keccak256_rlp(x)
77
- keccak256 RLP.encode(x)
78
- end
79
-
80
- def ripemd160(x)
81
- Digest::RMD160.digest x
82
- end
83
-
84
- def hash160(x)
85
- ripemd160 sha256(x)
86
- end
87
-
88
- def zpad(x, l)
89
- lpad x, BYTE_ZERO, l
90
- end
91
-
92
- def zunpad(x)
93
- x.sub(/\A\x00+/, '')
94
- end
95
-
96
- def zpad_int(n, l=32)
97
- zpad encode_int(n), l
98
- end
99
-
100
- def zpad_hex(s, l=32)
101
- zpad decode_hex(s), l
102
- end
103
-
104
- def valid_address?(address)
105
- Address.new(address).valid?
106
- end
107
-
108
- def format_address(address)
109
- Address.new(address).checksummed
110
- end
111
-
112
-
113
-
114
- private
115
-
116
- def lpad(x, symbol, l)
117
- return x if x.size >= l
118
- symbol * (l - x.size) + x
119
- end
120
-
121
- def encode_int(n)
122
- unless n.is_a?(Integer) && n >= 0 && n <= UINT_MAX
123
- raise ArgumentError, "Integer invalid or out of range: #{n}"
124
- end
125
-
126
- int_to_base256 n
127
- end
128
-
129
- end
130
- end