eth 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c7f1809a30053f40f6c3c5682eeb7e95be171c56
4
- data.tar.gz: 9f521ec59a2069fe3f0786181d03ec41ae8622dd
3
+ metadata.gz: '0519da7b184daeca3bf8e6a8012abd792f421f06'
4
+ data.tar.gz: d65b599489e12a20ee73a78e25abea66ffb635f5
5
5
  SHA512:
6
- metadata.gz: 0b1802ce64192a04eee29893fce5e4da2bb30ebff491ae5ec5a8e6d71324d28e6b899b88b88bf502d56cdc159e29c38cbcbc04aeebf04fe8242b2282c1e5dc35
7
- data.tar.gz: 469313348eadc5fac799fe9364f7a1be450a7cc30cc3e105da8574c249022d5190f7d7d36852c31bd95617133b64e2fc7fdf4d310b6d5617639f23c8061b68b1
6
+ metadata.gz: 744749e5509964bc220becaf7bf008146a4b4c2b437f3ea74abfbe4b63efeccb9faf8715e9fa260486a2212ca8ac93b16c3c658961832674da2106a3da4dc1b6
7
+ data.tar.gz: a217f4e86b31b2de76307f1bef5069e168e36b9e0000b07afc7fcb0759ffca14608c211624f7e33ae85f0cff472dbd8de7b1000c1be407b6050e9a61c7c38db6
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .ruby-version
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.3]
10
+
11
+ ### Added
12
+ - Eth::Key::Encrypter class to handle encrypting keys.
13
+ - Eth::Key.encrypt as a nice wrapper around Encrypter class.
14
+ - Eth::Key::Decrypter class to handle encrypting keys.
15
+ - Eth::Key.decrypt as a nice wrapper around Decrypter class.
16
+
9
17
  ## [0.4.2]
10
18
 
11
19
  ### Added
data/README.md CHANGED
@@ -28,10 +28,18 @@ key.private_hex
28
28
  key.public_hex
29
29
  key.address # EIP55 checksummed address
30
30
  ```
31
- Or import and existing one:
31
+ Import an existing key:
32
32
  ```ruby
33
33
  old_key = Eth::Key.new priv: private_key
34
34
  ```
35
+ Or decrypt an [encrypted key](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition):
36
+ ```ruby
37
+ decrypted_key = Eth::Key.decrypt File.read('./some/path.json'), 'p455w0rD'
38
+ ```
39
+ You can also encrypt your keys for use with other ethereum libraries:
40
+ ```ruby
41
+ encrypted_key_info = Eth::Key.encrypt key, 'p455w0rD'
42
+ ```
35
43
 
36
44
  ### Transactions
37
45
 
@@ -66,7 +74,7 @@ Eth::Utils.valid_address? address
66
74
 
67
75
  Or add a checksum to an existing address:
68
76
  ```ruby
69
- Eth::Utils.valid_address? "0x4bc787699093f11316e819b5692be04a712c4e69" # => "0x4bc787699093f11316e819B5692be04A712C4E69"
77
+ Eth::Utils.format_address "0x4bc787699093f11316e819b5692be04a712c4e69" # => "0x4bc787699093f11316e819B5692be04A712C4E69"
70
78
  ```
71
79
 
72
80
  ### Configure
@@ -1,8 +1,22 @@
1
1
  module Eth
2
2
  class Key
3
+ autoload :Decrypter, 'eth/key/decrypter'
4
+ autoload :Encrypter, 'eth/key/encrypter'
3
5
 
4
6
  attr_reader :private_key, :public_key
5
7
 
8
+ def self.encrypt(key, password)
9
+ key = new(priv: key) unless key.is_a?(Key)
10
+
11
+ Encrypter.perform key.private_hex, password
12
+ end
13
+
14
+ def self.decrypt(data, password)
15
+ priv = Decrypter.perform data, password
16
+ new priv: priv
17
+ end
18
+
19
+
6
20
  def initialize(priv: nil)
7
21
  @private_key = MoneyTree::PrivateKey.new key: priv
8
22
  @public_key = MoneyTree::PublicKey.new private_key, compressed: false
@@ -0,0 +1,87 @@
1
+ require 'json'
2
+
3
+ class Eth::Key::Decrypter
4
+ include Eth::Utils
5
+
6
+ def self.perform(data, password)
7
+ new(data, password).perform
8
+ end
9
+
10
+ def initialize(data, password)
11
+ @data = JSON.parse(data)
12
+ @password = password
13
+ end
14
+
15
+ def perform
16
+ derive_key password
17
+ check_macs
18
+ bin_to_hex decrypted_data
19
+ end
20
+
21
+
22
+ private
23
+
24
+ attr_reader :data, :key, :password
25
+
26
+ def derive_key(password)
27
+ @key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_length, digest)
28
+ end
29
+
30
+ def check_macs
31
+ mac1 = keccak256(key[(key_length/2), key_length] + ciphertext)
32
+ mac2 = hex_to_bin crypto_data['mac']
33
+
34
+ if mac1 != mac2
35
+ raise "Message Authentications Codes do not match!"
36
+ end
37
+ end
38
+
39
+ def decrypted_data
40
+ @decrypted_data ||= cipher.update(ciphertext) + cipher.final
41
+ end
42
+
43
+ def crypto_data
44
+ @crypto_data ||= data['crypto'] || data['Crypto']
45
+ end
46
+
47
+ def ciphertext
48
+ hex_to_bin crypto_data['ciphertext']
49
+ end
50
+
51
+ def cipher_name
52
+ "aes-128-ctr"
53
+ end
54
+
55
+ def cipher
56
+ @cipher ||= OpenSSL::Cipher.new(cipher_name).tap do |cipher|
57
+ cipher.decrypt
58
+ cipher.key = key[0, (key_length/2)]
59
+ cipher.iv = iv
60
+ end
61
+ end
62
+
63
+ def iv
64
+ hex_to_bin crypto_data['cipherparams']['iv']
65
+ end
66
+
67
+ def salt
68
+ hex_to_bin crypto_data['kdfparams']['salt']
69
+ end
70
+
71
+ def iterations
72
+ crypto_data['kdfparams']['c'].to_i
73
+ end
74
+
75
+ def key_length
76
+ 32
77
+ end
78
+
79
+ def digest
80
+ OpenSSL::Digest.new digest_name
81
+ end
82
+
83
+ def digest_name
84
+ "sha256"
85
+ end
86
+
87
+ end
@@ -0,0 +1,127 @@
1
+ require 'json'
2
+
3
+ class Eth::Key::Encrypter
4
+ include Eth::Utils
5
+
6
+ def self.perform(key, password, options = {})
7
+ new(key, options).perform(password)
8
+ end
9
+
10
+ def initialize(key, options = {})
11
+ @key = key
12
+ @options = options
13
+ end
14
+
15
+ def perform(password)
16
+ derive_key password
17
+ encrypt
18
+
19
+ data.to_json
20
+ end
21
+
22
+ def data
23
+ {
24
+ crypto: {
25
+ cipher: cipher_name,
26
+ cipherparams: {
27
+ iv: bin_to_hex(iv),
28
+ },
29
+ ciphertext: bin_to_hex(encrypted_key),
30
+ kdf: "pbkdf2",
31
+ kdfparams: {
32
+ c: iterations,
33
+ dklen: 32,
34
+ prf: prf,
35
+ salt: bin_to_hex(salt),
36
+ },
37
+ mac: bin_to_hex(mac),
38
+ },
39
+ id: id,
40
+ version: 3,
41
+ }.tap do |data|
42
+ data[:address] = address unless options[:skip_address]
43
+ end
44
+ end
45
+
46
+ def id
47
+ @id ||= options[:id] || SecureRandom.uuid
48
+ end
49
+
50
+
51
+ private
52
+
53
+ attr_reader :derived_key, :encrypted_key, :key, :options
54
+
55
+ def cipher
56
+ @cipher ||= OpenSSL::Cipher.new(cipher_name).tap do |cipher|
57
+ cipher.encrypt
58
+ cipher.iv = iv
59
+ cipher.key = derived_key[0, (key_length/2)]
60
+ end
61
+ end
62
+
63
+ def digest
64
+ @digest ||= OpenSSL::Digest.new digest_name
65
+ end
66
+
67
+ def derive_key(password)
68
+ @derived_key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_length, digest)
69
+ end
70
+
71
+ def encrypt
72
+ @encrypted_key = cipher.update(hex_to_bin key) + cipher.final
73
+ end
74
+
75
+ def mac
76
+ keccak256(derived_key[(key_length/2), key_length] + encrypted_key)
77
+ end
78
+
79
+ def cipher_name
80
+ "aes-128-ctr"
81
+ end
82
+
83
+ def digest_name
84
+ "sha256"
85
+ end
86
+
87
+ def prf
88
+ "hmac-#{digest_name}"
89
+ end
90
+
91
+ def key_length
92
+ 32
93
+ end
94
+
95
+ def salt_length
96
+ 32
97
+ end
98
+
99
+ def iv_length
100
+ 16
101
+ end
102
+
103
+ def iterations
104
+ options[:iterations] || 262_144
105
+ end
106
+
107
+ def salt
108
+ @salt ||= if options[:salt]
109
+ hex_to_bin options[:salt]
110
+ else
111
+ SecureRandom.random_bytes(salt_length)
112
+ end
113
+ end
114
+
115
+ def iv
116
+ @iv ||= if options[:iv]
117
+ hex_to_bin options[:iv]
118
+ else
119
+ SecureRandom.random_bytes(iv_length)
120
+ end
121
+ end
122
+
123
+ def address
124
+ Eth::Key.new(priv: key).address
125
+ end
126
+
127
+ end
@@ -1,3 +1,3 @@
1
1
  module Eth
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Ellis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-28 00:00:00.000000000 Z
11
+ date: 2017-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: digest-sha3
@@ -145,6 +145,8 @@ files:
145
145
  - lib/eth/address.rb
146
146
  - lib/eth/gas.rb
147
147
  - lib/eth/key.rb
148
+ - lib/eth/key/decrypter.rb
149
+ - lib/eth/key/encrypter.rb
148
150
  - lib/eth/open_ssl.rb
149
151
  - lib/eth/secp256k1.rb
150
152
  - lib/eth/sedes.rb
@@ -171,9 +173,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
173
  version: '0'
172
174
  requirements: []
173
175
  rubyforge_project:
174
- rubygems_version: 2.5.1
176
+ rubygems_version: 2.6.8
175
177
  signing_key:
176
178
  specification_version: 4
177
179
  summary: Simple API to sign Ethereum transactions.
178
180
  test_files: []
179
- has_rdoc: