class Neb::Key
Constants
- CIPHER_NAME
- DKLEN
- KDF
- KDF_N
- KDF_P
- KDF_R
- KEY_CURRENT_VERSION
- KEY_VERSION_3
- MACHASH
Attributes
address[RW]
iv[RW]
mac[RW]
password[RW]
private_key[RW]
salt[RW]
Public Class Methods
convert_iv(iv)
click to toggle source
# File lib/neb/key.rb, line 125 def convert_iv(iv) return iv if iv.length == 16 return Utils.hex_to_bin(iv) if iv.length == 32 raise ArgumentError.new("iv must be 16 bytes") end
convert_salt(salt)
click to toggle source
# File lib/neb/key.rb, line 118 def convert_salt(salt) return salt if salt.length == 32 return Utils.hex_to_bin(salt) if salt.length == 64 raise ArgumentError.new("salt must be 32 bytes") end
decrypt(key_data, password)
click to toggle source
# File lib/neb/key.rb, line 63 def decrypt(key_data, password) key_data = Utils.from_json(key_data) if key_data.is_a?(String) key_data = key_data.deep_symbolize_keys! raise InvalidJSONKeyError("key data validate failed") if !validate?(key_data) version = key_data[:version] address = key_data[:address] crypto = key_data[:crypto] cipher = crypto[:cipher] salt = convert_salt(crypto[:kdfparams][:salt]) dklen = crypto[:kdfparams][:dklen] kdf_n = crypto[:kdfparams][:n] kdf_r = crypto[:kdfparams][:r] kdf_p = crypto[:kdfparams][:p] iv = convert_iv(crypto[:cipherparams][:iv]) derived_key = Utils.scrypt(password, salt, kdf_n, kdf_r, kdf_p, dklen) ciphertext_bin = Utils.hex_to_bin(crypto[:ciphertext]) if version == KEY_CURRENT_VERSION mac = Utils.keccak256([derived_key[16, 16], ciphertext_bin, iv, cipher].join) else mac = Utils.keccak256([derived_key[16, 16], ciphertext_bin].join) # KeyVersion3 end raise InvalidJSONKeyError.new("mac is wrong") if Utils.bin_to_hex(mac) != crypto[:mac] private_key = Utils.aes_decrypt(ciphertext_bin, derived_key[0, 16], iv) Utils.bin_to_hex(private_key) end
encrypt(address, private_key, password)
click to toggle source
# File lib/neb/key.rb, line 59 def encrypt(address, private_key, password) new(address: address, private_key: private_key, password: password).encrypt end
new(address: nil, private_key: nil, password: nil, salt: nil, iv: nil)
click to toggle source
# File lib/neb/key.rb, line 20 def initialize(address: nil, private_key: nil, password: nil, salt: nil, iv: nil) @address = Address.new(address) if address @private_key = PrivateKey.new(private_key) if private_key @password = password @salt = self.class.convert_salt(salt || Utils.random_bytes(32)) @iv = self.class.convert_iv(iv || Utils.random_bytes(16)) end
validate?(key_data)
click to toggle source
# File lib/neb/key.rb, line 96 def validate?(key_data) key_data = Utils.from_json(key_data) if key_data.is_a?(String) [:version, :id, :address, :crypto].each do |k| return false if !key_data.keys.include?(k) end return false if key_data[:version] != KEY_CURRENT_VERSION && key_data[:version] != KEY_VERSION_3 [:ciphertext, :cipherparams, :cipher, :kdf, :kdfparams, :mac, :machash].each do |k| return false if !key_data[:crypto].keys.include?(k) end return false if !key_data[:crypto][:cipherparams].keys.include?(:iv) [:dklen, :salt, :n, :r, :p].each do |k| return false if !key_data[:crypto][:kdfparams].keys.include?(k) end true end
Public Instance Methods
encrypt()
click to toggle source
# File lib/neb/key.rb, line 28 def encrypt derived_key = Utils.scrypt(password, salt, KDF_N, KDF_R, KDF_P, DKLEN) ciphertext_bin = Utils.aes_encrypt(private_key.encode(:bin), derived_key[0, 16], iv) mac_bin = Utils.keccak256([derived_key[16, 16], ciphertext_bin, iv, CIPHER_NAME].join) { version: KEY_CURRENT_VERSION, id: Utils.uuid, address: address.to_s, crypto: { ciphertext: Utils.bin_to_hex(ciphertext_bin), cipherparams: { iv: Utils.bin_to_hex(iv) }, cipher: CIPHER_NAME, kdf: KDF, kdfparams: { dklen: DKLEN, salt: Utils.bin_to_hex(salt), n: KDF_N, r: KDF_R, p: KDF_P }, mac: Utils.bin_to_hex(mac_bin), machash: MACHASH } } end