class Eth::Key::Decrypter
def self.perform(data, password)
def self.perform(data, password) new(data, password).perform end
def check_macs
def check_macs mac1 = keccak256(key[(key_length/2), key_length] + ciphertext) mac2 = hex_to_bin crypto_data['mac'] if mac1 != mac2 raise "Message Authentications Codes do not match!" end end
def cipher
def cipher @cipher ||= OpenSSL::Cipher.new(cipher_name).tap do |cipher| cipher.decrypt cipher.key = key[0, (key_length/2)] cipher.iv = iv end end
def cipher_name
def cipher_name "aes-128-ctr" end
def ciphertext
def ciphertext hex_to_bin crypto_data['ciphertext'] end
def crypto_data
def crypto_data @crypto_data ||= data['crypto'] || data['Crypto'] end
def decrypted_data
def decrypted_data @decrypted_data ||= cipher.update(ciphertext) + cipher.final end
def derive_key(password)
def derive_key(password) case kdf when 'pbkdf2' @key = OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_length, digest) when 'scrypt' # OpenSSL 1.1 inclues OpenSSL::KDF.scrypt, but it is not available usually, otherwise we could do: OpenSSL::KDF.scrypt(password, salt: salt, N: n, r: r, p: p, length: key_length) @key = SCrypt::Engine.scrypt(password, salt, n, r, p, key_length) else raise "Unsupported key derivation function: #{kdf}!" end end
def digest
def digest OpenSSL::Digest.new digest_name end
def digest_name
def digest_name "sha256" end
def initialize(data, password)
def initialize(data, password) @data = JSON.parse(data) @password = password end
def iterations
def iterations crypto_data['kdfparams']['c'].to_i end
def iv
def iv hex_to_bin crypto_data['cipherparams']['iv'] end
def kdf
def kdf crypto_data['kdf'] end
def key_length
def key_length crypto_data['kdfparams']['dklen'].to_i end
def n
def n crypto_data['kdfparams']['n'].to_i end
def p
def p crypto_data['kdfparams']['p'].to_i end
def perform
def perform derive_key password check_macs bin_to_hex decrypted_data end
def r
def r crypto_data['kdfparams']['r'].to_i end
def salt
def salt hex_to_bin crypto_data['kdfparams']['salt'] end