keyfile.py (3258B)
1 # standard imports 2 import os 3 import logging 4 import sys 5 import json 6 import argparse 7 import getpass 8 import stat 9 10 # external impors 11 import coincurve 12 from hexathon import strip_0x 13 14 # local imports 15 from funga.error import DecryptError 16 from funga.eth.keystore.keyfile import ( 17 from_file, 18 to_dict, 19 ) 20 21 22 from funga.eth.encoding import ( 23 private_key_to_address, 24 private_key_to_public_key, 25 private_key_from_bytes, 26 ) 27 28 29 logging.basicConfig(level=logging.WARNING) 30 logg = logging.getLogger() 31 32 argparser = argparse.ArgumentParser() 33 argparser.add_argument('-d', '--decrypt', dest='d', type=str, help='decrypt file') 34 argparser.add_argument('--private-key', dest='private_key', action='store_true', help='output private key instead of address') 35 argparser.add_argument('--passphrase-file', dest='passphrase_file', type=str, help='Keystore file to use for signing or address') 36 argparser.add_argument('-0', dest='nonl', action='store_true', help='no newline at end of output') 37 argparser.add_argument('-z', action='store_true', help='zero-length password') 38 argparser.add_argument('-k', type=str, help='load private key from file') 39 argparser.add_argument('-p', '--public-key', dest='p', action='store_true', help='return public key instead of address') 40 argparser.add_argument('-v', action='store_true', help='be verbose') 41 args = argparser.parse_args() 42 43 if args.v: 44 logg.setLevel(logging.DEBUG) 45 46 mode = 'create' 47 secret = False 48 if args.d: 49 mode = 'decrypt' 50 if args.private_key: 51 secret = True 52 53 pk_hex = os.environ.get('PRIVATE_KEY') 54 if args.k != None: 55 f = open(args.k, 'r') 56 pk_hex = f.read(66) 57 f.close() 58 59 def main(): 60 global pk_hex 61 62 passphrase = os.environ.get('WALLET_PASSPHRASE', os.environ.get('PASSPHRASE')) 63 64 if args.z: 65 passphrase = '' 66 else: 67 fp = getattr(args, 'passphrase_file') 68 if fp != None: 69 st = os.stat(fp) 70 if stat.S_IMODE(st.st_mode) & (stat.S_IRWXO | stat.S_IRWXG) > 0: 71 logg.warning('others than owner have access on password file') 72 f = open(fp, 'r') 73 passphrase = f.read() 74 f.close() 75 76 r = None 77 if mode == 'decrypt': 78 if passphrase == None: 79 passphrase = getpass.getpass('decryption phrase: ') 80 try: 81 r = from_file(args.d, passphrase).hex() 82 except DecryptError: 83 sys.stderr.write('Invalid passphrase\n') 84 sys.exit(1) 85 if not secret: 86 pk = private_key_from_bytes(bytes.fromhex(r)) 87 r = None 88 if args.p: 89 r = private_key_to_public_key(pk) 90 else: 91 r = private_key_to_address(pk) 92 elif mode == 'create': 93 if passphrase == None: 94 passphrase = getpass.getpass('encryption phrase: ') 95 pk_bytes = None 96 if pk_hex != None: 97 pk_hex = strip_0x(pk_hex) 98 pk_bytes = bytes.fromhex(pk_hex) 99 else: 100 pk_bytes = os.urandom(32) 101 pk = coincurve.PrivateKey(secret=pk_bytes) 102 o = to_dict(pk_bytes, passphrase=passphrase) 103 r = json.dumps(o) 104 105 if not args.nonl: 106 r += "\n" 107 sys.stdout.write(r) 108 109 110 if __name__ == '__main__': 111 main()