#!/usr/bin/env python # This software is Copyright (c) 2017, Dhiru Kholia # and it is hereby released to the general public under the following terms: # # Redistribution and use in source and binary forms, with or without # modification, are permitted. # # Special thanks goes to @Chick3nman for coming up with the output hash format. # # References, # # https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition # # https://github.com/ethereum/go-ethereum/wiki/Passphrase-protected-key-store-spec, # v1 wallets are not supported (yet) import os import sys import traceback try: import json assert json except ImportError: try: sys.path.append(".") import simplejson as json except ImportError: sys.stderr.write("Please install json / simplejson module which is currently not installed.\n") sys.exit(1) def process_presale_wallet(filename, data): try: bkp = data["bkp"] except KeyError: sys.stdout.write("%s: presale wallet is missing 'bkp' field, this is unsupported!\n" % filename) return try: encseed = data["encseed"] ethaddr = data["ethaddr"] except KeyError: sys.stdout.write("%s: presale wallet is missing necessary fields!\n" % filename) return # 16 bytes of bkp should be enough sys.stdout.write("%s:$ethereum$w*%s*%s*%s\n" % (os.path.basename(filename), encseed, ethaddr, bkp[:32])) def process_file(filename): try: f = open(filename, "rb") except IOError: e = sys.exc_info()[1] sys.stderr.write("%s\n" % str(e)) return data = f.read().decode("utf-8") sys.stderr.write("WARNING: Upon successful password recovery, this hash format may expose your PRIVATE KEY. Do not share extracted hashes with any untrusted parties!\n") try: data = json.loads(data) try: crypto = data["crypto"] except KeyError: try: crypto = data["Crypto"] except: # hack for presale wallet process_presale_wallet(filename, data) return cipher = crypto["cipher"] if cipher != "aes-128-ctr": sys.stdout.write("%s: unexpected cipher '%s' found\n" % (filename, cipher)) return -2 kdf = crypto["kdf"] ciphertext = crypto["ciphertext"] mac = crypto["mac"] if kdf == "scrypt": kdfparams = crypto["kdfparams"] n = kdfparams["n"] r = kdfparams["r"] p = kdfparams["p"] salt = kdfparams["salt"] sys.stdout.write("%s:$ethereum$s*%s*%s*%s*%s*%s*%s\n" % (os.path.basename(filename), n, r, p, salt, ciphertext, mac)) elif kdf == "pbkdf2": kdfparams = crypto["kdfparams"] n = kdfparams["c"] prf = kdfparams["prf"] if prf != 'hmac-sha256': sys.stdout.write("%s: unexpected prf '%s' found\n" % (filename, prf)) return salt = kdfparams["salt"] sys.stdout.write("%s:$ethereum$p*%s*%s*%s*%s\n" % (os.path.basename(filename), n, salt, ciphertext, mac)) else: assert 0 except: sys.stdout.write("%s: json parsing failed\n" % filename) traceback.print_exc() return -1 f.close() if __name__ == "__main__": if len(sys.argv) < 2: sys.stderr.write("Usage: %s [Ethereum Wallet files (Geth/Mist/MyEtherWallet)]\n" % sys.argv[0]) sys.exit(1) for j in range(1, len(sys.argv)): process_file(sys.argv[j])