Various bugfixes, better password handling

This commit is contained in:
philemon 2014-03-15 00:57:33 +04:00
commit 3302ac774f
9 changed files with 91 additions and 43 deletions

View file

@ -3,6 +3,7 @@ mmgen-addrgen
mmgen-addrimport
mmgen-keygen
mmgen-passchg
mmgen-pywallet
mmgen-txcreate
mmgen-txsend
mmgen-txsign
@ -30,7 +31,6 @@ mmgen/rpc/proxy.py
mmgen/rpc/util.py
scripts/bitcoind-walletunlock.py
scripts/deinstall.sh
scripts/pywallet.py
tests/addr.py
tests/bitcoin.py
tests/mn_electrum.py

View file

@ -163,7 +163,13 @@ if invoked_as == "addrgen":
else:
if not 'no_addresses' in opts: opts['print_secret'] = True
seed = get_seed(infile,opts)
# Repeat on incorrect pw entry
silent = False
while True:
seed = get_seed(infile,opts,silent=silent)
silent = True
if seed: break
seed_id = make_chksum_8(seed)
addr_data = generate_addrs(seed, addr_list, opts)
addr_data_str = format_addr_data(addr_data, seed_id, opts)

View file

@ -66,9 +66,13 @@ infile = cmd_args[0]
label,metadata,hash_preset,salt,enc_seed = get_data_from_wallet(infile,opts)
seed_id,key_id = metadata[:2]
oldp = "" if 'keep_old_passphrase' in opts else "old "
passwd = " ".join(get_words("","",("Enter %spassphrase: " % oldp),opts))
key = make_key(passwd, salt, hash_preset)
seed = decrypt_seed(enc_seed, key, seed_id, key_id)
# Repeat on incorrect pw entry
while True:
passwd = " ".join(get_words("","",("Enter %spassphrase: " % oldp),opts))
key = make_key(passwd, salt, hash_preset)
seed = decrypt_seed(enc_seed, key, seed_id, key_id)
if seed: break
changed = {}

View file

@ -109,7 +109,7 @@ if user_confirm("View transaction data? ",default_yes=False):
view_tx_data(c,inputs_data,tx_hex,metadata)
# Are inputs mmgen addresses?
infile,mmgen_addrs,other_addrs,keys = "",[],[],[]
mmgen_addrs,other_addrs,keys = [],[],[]
for i in inputs_data:
if verify_mmgen_label(i['account']):
@ -121,9 +121,11 @@ if mmgen_addrs and not 'force_wallet_dat' in opts:
# Check that all the seed IDs are the same:
seed_ids = list(set([i['account'][:8] for i in mmgen_addrs]))
while seed_ids:
infile = False
if cmd_args:
infile = cmd_args.pop()
ext = infile.split(".")[-1]
found = False
for e,o in (
(wallet_ext, {}),
(mn_ext, {"from_mnemonic":True}),
@ -131,15 +133,29 @@ if mmgen_addrs and not 'force_wallet_dat' in opts:
(brain_ext, {})
):
if e == ext:
found = True
if e == brain_ext:
if "from_brain" in opts: o = opts
else:
msg("'--from-brain' option must be specified for brainwallet file")
sys.exit(2)
seed = get_seed(infile,o)
silent = False
while True:
seed = get_seed(infile,o,silent=silent)
silent = True
if seed: break
if not found:
msg("%s: invalid file extension" % ext)
sys.exit(2)
elif "from_brain" in opts or "from_mnemonic" in opts or "from_seed" in opts:
msg("Need data for seed ID %s" % seed_ids[0])
seed = get_seed("",opts)
silent = False
while True:
seed = get_seed("",opts,silent=silent)
silent = True
if seed: break
else:
msg("One of '-b', '-m' or '-s' must be specified for seed IDs: %s" %
" ".join(seed_ids))
@ -158,7 +174,9 @@ if mmgen_addrs and not 'force_wallet_dat' in opts:
keys += [i['wif'] for i in generate_addrs(seed, seed_id_addrs, o)]
else:
msg("Supplied seed ID (%s) is incorrect" % seed_id)
sys.exit(2)
if infile:
msg("Invalid input file: %s" % infile)
sys.exit(2)
if other_addrs:
if 'keys_from_file' in opts:

View file

@ -151,8 +151,12 @@ if debug: display_user_random_data(usr_keys,key_timings)
usr_rand_data = sha256(usr_keys).digest() + \
sha256("".join(key_timings)).digest()
s = get_seed(infile,opts,no_wallet=True)
if s: seed = s
if 'from_mnemonic' in opts or 'from_brain' in opts or 'from_seed' in opts:
silent = False
while True:
seed = get_seed(infile,opts,silent=silent)
silent = True
if seed: break
else:
# Truncate random data for smaller seed lengths
seed = os_rand_data[0] + usr_rand_data

View file

@ -108,7 +108,10 @@ def generate_addrs(seed, addrnums, opts):
out.append(el)
w = opts['gen_what']
if t_addrs == 1: w = w[:-1]
if t_addrs == 1:
import re
w = re.sub('e*s$','',w)
sys.stderr.write("\rGenerated %s %s%s\n"%(t_addrs, w, " "*15))
return out

View file

@ -50,12 +50,12 @@ def get_seed_from_mnemonic(mn,wl):
if len(mn) not in mnemonic_lens:
msg("Bad mnemonic (%i words). Allowed numbers of words: %s" %
(len(mn)," ".join([str(i) for i in mnemonic_lens])))
sys.exit(2)
return False
for w in mn:
if w not in wl:
msg("Bad mnemonic: '%s' is not in the wordlist" % w)
sys.exit(2)
return False
from binascii import unhexlify
seed = unhexlify(baseNtohex(mn_base,mn,wl,mn_fill(mn)))

View file

@ -536,7 +536,7 @@ def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
if 'outdir' in opts:
outfile = "%s/%s" % (opts['outdir'], outfile)
label = opts['label'] if 'label' in opts else "None"
label = opts['label'] if 'label' in opts else "No Label"
from mmgen.bitcoin import b58encode_pad
@ -572,14 +572,15 @@ def write_walletdat_dump_to_file(wallet_id,data,num_keys,ext,what,opts):
msg("wallet.dat %s saved to file '%s'" % (what,outfile))
def compare_checksums(chksum1, desc1, chksum2, desc2):
def compare_checksums(chksum1, desc1, chksum2, desc2):
if chksum1.lower() == chksum2.lower():
msg("OK (%s)" % chksum1.upper())
return True
else:
msg("ERROR!\nComputed checksum %s (%s) doesn't match checksum %s (%s)" \
% (desc1,chksum1,desc2,chksum2))
if debug:
msg("ERROR!\nComputed checksum %s (%s) doesn't match checksum %s (%s)" \
% (desc1,chksum1,desc2,chksum2))
return False
def _is_hex(s):
@ -588,7 +589,7 @@ def _is_hex(s):
else: return True
def check_mmseed_format(words):
def _check_mmseed_format(words):
valid = False
what = "%s data" % seed_ext
@ -602,12 +603,10 @@ def check_mmseed_format(words):
msg("Incorrect length of checksum (%s) in %s" % (chklen,what))
else: valid = True
if valid == False:
msg("Invalid %s data" % seed_ext)
sys.exit(3)
return valid
def check_wallet_format(infile, lines, opts):
def check_wallet_format(infile, lines, opts):
def vmsg(s):
if 'verbose' in opts: msg(s)
@ -638,9 +637,10 @@ def _check_chksum_6(chk,val,desc,infile):
msg("%s checksum passed: %s" % (desc.capitalize(),chk))
def get_data_from_wallet(infile,opts):
def get_data_from_wallet(infile,opts,silent=False):
msg("Getting {} wallet data from file '{}'".format(proj_name,infile))
if not silent:
msg("Getting {} wallet data from file '{}'".format(proj_name,infile))
f = open_file_or_exit(infile, 'r')
@ -719,9 +719,11 @@ def get_words(infile,what,prompt,opts):
return words
def get_seed_from_seed_data(words):
def _get_seed_from_seed_data(words):
check_mmseed_format(words)
if not _check_mmseed_format(words):
msg("Invalid %s data" % seed_ext)
return False
stored_chk = words[0]
seed_b58 = "".join(words[1:])
@ -733,19 +735,23 @@ def get_seed_from_seed_data(words):
seed = b58decode_pad(seed_b58)
if seed == False:
msg("Invalid b58 number: %s" % val)
sys.exit(9)
return False
msg("%s data produces seed ID: %s" % (seed_ext,make_chksum_8(seed)))
return seed
else:
msg("Invalid checksum for {} seed".format(proj_name))
sys.exit(9)
return False
def get_seed_from_wallet(infile,opts,
prompt="Enter {} wallet passphrase: ".format(proj_name)):
def get_seed_from_wallet(
infile,
opts,
prompt="Enter {} wallet passphrase: ".format(proj_name),
silent=False
):
wdata = get_data_from_wallet(infile,opts)
wdata = get_data_from_wallet(infile,opts,silent=silent)
label,metadata,hash_preset,salt,enc_seed = wdata
if 'verbose' in opts: _display_control_data(*wdata)
@ -770,8 +776,8 @@ def decrypt_seed(enc_seed, key, seed_id, key_id):
msg_r("Checking key...")
chk = make_chksum_8(key)
if not compare_checksums(chk, "of key", key_id, "in header"):
msg("Passphrase incorrect?")
sys.exit(3)
msg("Incorrect passphrase")
return False
msg_r("Decrypting seed with key...")
@ -793,21 +799,22 @@ def decrypt_seed(enc_seed, key, seed_id, key_id):
else:
msg("Incorrect passphrase")
sys.exit(3)
return False
if debug: msg("key: %s" % hexlify(key))
return dec_seed
def get_seed(infile,opts,no_wallet=False):
def get_seed(infile,opts,silent=False):
if 'from_mnemonic' in opts:
prompt = "Enter mnemonic: "
what = "mnemonic"
words = get_words(infile,"mnemonic data",prompt,opts)
wl = get_default_wordlist()
from mmgen.mnemonic import get_seed_from_mnemonic
return get_seed_from_mnemonic(words,wl)
seed = get_seed_from_mnemonic(words,wl)
elif 'from_brain' in opts:
if 'quiet' not in opts:
confirm_or_exit(
@ -816,16 +823,22 @@ def get_seed(infile,opts,no_wallet=False):
*_get_from_brain_opt_params(opts)),
"continue")
prompt = "Enter brainwallet passphrase: "
what = "brainwallet"
words = get_words(infile,"brainwallet data",prompt,opts)
return _get_seed_from_brain_passphrase(words,opts)
seed = _get_seed_from_brain_passphrase(words,opts)
elif 'from_seed' in opts:
prompt = "Enter seed in %s format: " % seed_ext
what = "seed"
words = get_words(infile,"seed data",prompt,opts)
return get_seed_from_seed_data(words)
elif no_wallet:
return False
seed = _get_seed_from_seed_data(words)
else:
return get_seed_from_wallet(infile, opts)
return get_seed_from_wallet(infile, opts, silent=silent)
if infile and not seed:
msg("Invalid %s file: %s" % (what,infile))
sys.exit(2)
return seed
def remove_blanks_comments(lines):

View file

@ -3,7 +3,7 @@ from distutils.core import setup
setup(
name = 'mmgen',
version = '0.6.4',
version = '0.6.5',
author = 'Philemon',
author_email = 'mmgen-py@yandex.com',
url = 'https://github.com/mmgen/mmgen',