funga-eth

Ethereum implementation of the funga keystore and signer
Info | Log | Files | Refs | README | LICENSE

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()