Regression fix in addr.py, improvements in mmgen-txsign.

This commit is contained in:
The MMGen Project 2014-08-06 20:37:29 +04:00
commit ea449e652a
8 changed files with 72 additions and 70 deletions

View file

@ -80,7 +80,8 @@ def generate_addrs(seed, addrnums, opts):
addrnums.sort() # needed only if caller didn't sort
ws = 'key' if 'keys' in opts['gen_what'] else 'address'
if t_addrs != 1: wp = ws+"s" if ws == 'key' else ws+"es"
if t_addrs == 1: wp = ws
else: wp = ws+"s" if ws == 'key' else ws+"es"
while pos != t_addrs:
seed = sha512(seed).digest()

View file

@ -369,10 +369,11 @@ def _get_seed_from_brain_passphrase(words,opts):
# Vars for mmgen_*crypt functions only
salt_len,sha256_len,nonce_len = 32,32,32
def mmgen_encrypt(data,what="data",hash_preset='3',opts={}):
def mmgen_encrypt(data,what="data",hash_preset='',opts={}):
salt,iv,nonce = get_random(salt_len,opts),\
get_random(g.aesctr_iv_len,opts), get_random(nonce_len,opts)
hp,m = (hash_preset,"user-requested") if hash_preset else ('3',"default")
hp = hash_preset or get_hash_preset_from_user('3',what)
m = "default" if hp == '3' else "user-requested"
vmsg("Encrypting %s" % what)
qmsg("Using %s hash preset of '%s'" % (m,hp))
passwd = get_new_passphrase("passphrase",{})
@ -382,11 +383,12 @@ def mmgen_encrypt(data,what="data",hash_preset='3',opts={}):
return salt+iv+enc_d
def mmgen_decrypt(data,what="data",hash_preset='3',opts={}):
def mmgen_decrypt(data,what="data",hash_preset='',opts={}):
dstart = salt_len + g.aesctr_iv_len
salt,iv,enc_d = data[:salt_len],data[salt_len:dstart],data[dstart:]
hp,m = (hash_preset,"user-requested") if hash_preset else ('3',"default")
vmsg("Preparing to decrypt %s" % what)
hp = hash_preset or get_hash_preset_from_user('3',what)
m = "default" if hp == '3' else "user-requested"
qmsg("Using %s hash preset of '%s'" % (m,hp))
passwd = get_mmgen_passphrase("Enter passphrase: ",{})
key = make_key(passwd, salt, hp)

View file

@ -20,25 +20,24 @@
main.py - Script launcher for the MMGen suite
"""
import sys, termios
from mmgen.util import msg
def launch_addrgen(): import mmgen.main_addrgen
def launch_addrimport(): import mmgen.main_addrimport
def launch_keygen(): import mmgen.main_addrgen
def launch_passchg(): import mmgen.main_passchg
def launch_pywallet(): import mmgen.main_pywallet
def launch_tool(): import mmgen.main_tool
def launch_txcreate(): import mmgen.main_txcreate
def launch_txsend(): import mmgen.main_txsend
def launch_txsign(): import mmgen.main_txsign
def launch_walletchk(): import mmgen.main_walletchk
def launch_walletgen(): import mmgen.main_walletgen
def main(progname):
import sys, termios
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
if progname == "addrgen": import mmgen.main_addrgen
elif progname == "addrimport": import mmgen.main_addrimport
elif progname == "keygen": import mmgen.main_addrgen
elif progname == "passchg": import mmgen.main_passchg
elif progname == "pywallet": import mmgen.main_pywallet
elif progname == "tool": import mmgen.main_tool
elif progname == "txcreate": import mmgen.main_txcreate
elif progname == "txsend": import mmgen.main_txsend
elif progname == "txsign": import mmgen.main_txsign
elif progname == "walletchk": import mmgen.main_walletchk
elif progname == "walletgen": import mmgen.main_walletgen
try: eval("launch_"+progname+"()")
except KeyboardInterrupt:
msg("\nUser interrupt")
sys.stderr.write("\nUser interrupt\n")
termios.tcsetattr(fd, termios.TCSADRAIN, old)
sys.exit(1)

View file

@ -161,8 +161,7 @@ addr_data_str = format_addr_data(
outfile_base = "{}[{}]".format(seed_id, fmt_addr_idxs(addr_idxs))
if 'flat_list' in opts and user_confirm("Encrypt key list?"):
hp = get_hash_preset_from_user('3')
addr_data_str = mmgen_encrypt(addr_data_str,"key list",hp,opts)
addr_data_str = mmgen_encrypt(addr_data_str,"key list","",opts)
enc_ext = "." + g.mmenc_ext
else: enc_ext = ""

View file

@ -100,7 +100,6 @@ if 'from_incog_hex' in opts or 'from_incog_hidden' in opts:
opts['from_incog'] = True
if 'all_keys_from_file' in opts:
opts['keys_from_file'] = opts['all_keys_from_file']
# opts['skip_key_preverify'] = True
if not infiles: usage(help_data)
for i in infiles: check_infile(i)
@ -110,20 +109,19 @@ c = connect_to_bitcoind()
saved_seeds = {}
tx_files = [i for i in set(infiles) if get_extension(i) == g.rawtx_ext]
addrfiles = [a for a in set(infiles) if get_extension(a) == g.addrfile_ext]
infiles = list(set(infiles) - set(tx_files) - set(addrfiles))
seed_files = list(set(infiles) - set(tx_files) - set(addrfiles))
if not "info" in opts: do_license_msg(immed=True)
if 'keys_from_file' in opts:
from mmgen.crypto import mmgen_decrypt
fn = opts['keys_from_file']
d = get_data_from_file(fn,"keylist")
if get_extension(fn) == g.mmenc_ext or not \
is_b58_str(remove_comments(d.split("\n"))[0][:55]):
is_btc_key(remove_comments(d.split("\n"))[0][:55]):
qmsg("Keylist appears to be encrypted")
from mmgen.crypto import mmgen_decrypt
while True:
hp = get_hash_preset_from_user('3')
d_dec = mmgen_decrypt(d,"encrypted keylist",hp,opts)
d_dec = mmgen_decrypt(d,"encrypted keylist","",opts)
if d_dec: d = d_dec; break
else: msg("Trying again...")
keys_from_file = remove_comments(d.split("\n"))
@ -157,8 +155,9 @@ for tx_file in tx_files:
sys.exit(2)
if other_inputs and keys and not 'skip_key_preverify' in opts:
a = [i['address'] for i in other_inputs]
preverify_keys(a, keys)
addrs = [i['address'] for i in other_inputs]
mm_inputs = mmgen_inputs if 'all_keys_from_file' in opts else []
preverify_keys(addrs, keys, mm_inputs)
opts['skip_key_preverify'] = True
if 'all_keys_from_file' in opts:
@ -168,7 +167,7 @@ for tx_file in tx_files:
confirm_or_exit(txmsg['skip_mapping_checks_warning'],"continue")
else:
check_mmgen_to_btc_addr_mappings(
mmgen_inputs,b2m_map,infiles,saved_seeds,opts)
mmgen_inputs,b2m_map,seed_files,saved_seeds,opts)
if len(tx_files) > 1:
msg("\nTransaction %s/%s:" % (tx_files.index(tx_file)+1,len(tx_files)))
@ -185,7 +184,7 @@ for tx_file in tx_files:
if mmgen_inputs and not 'all_keys_from_file' in opts:
ml = [i['account'].split()[0] for i in mmgen_inputs]
keys += get_keys_for_mmgen_addrs(ml,infiles,saved_seeds,opts)
keys += get_keys_for_mmgen_addrs(ml,seed_files,saved_seeds,opts)
if 'use_wallet_dat' in opts:
sig_tx = sign_tx_with_bitcoind_wallet(c,tx_hex,sig_data,keys,opts)
@ -207,7 +206,8 @@ for tx_file in tx_files:
repr(inputs_data),
repr(b2m_map)
)
write_to_file(outfile,data,opts,"signed transaction",True,True)
confirm = False if g.quiet else True
write_to_file(outfile,data,opts,"signed transaction",confirm,True)
else:
msg("failed\nSome keys were missing. Transaction could not be signed.")
sys.exit(3)

View file

@ -72,8 +72,8 @@ commands = {
"pubkey2addr": ['<public key in hex format> [str]'],
"pubkey2hexaddr": ['<public key in hex format> [str]'],
"privhex2addr": ['<private key in hex format> [str]','compressed [bool=False]'],
"encrypt": ['<infile> [str]','outfile [str=""]','hash_preset [str="3"]'],
"decrypt": ['<infile> [str]','outfile [str=""]','hash_preset [str="3"]'],
"encrypt": ['<infile> [str]','outfile [str=""]','hash_preset [str=""]'],
"decrypt": ['<infile> [str]','outfile [str=""]','hash_preset [str=""]'],
"rand2file": ['<outfile> [str]','<nbytes> [str]','threads [int=4]'],
"bytespec": ['<bytespec> [str]'],
}
@ -416,9 +416,9 @@ def hex2wif(hexpriv,compressed=False):
print bitcoin.hextowif(hexpriv,compressed)
def encrypt(infile,outfile="",hash_preset='3'):
def encrypt(infile,outfile="",hash_preset=''):
data = get_data_from_file(infile,"data for encryption")
enc_d = mmgen_encrypt(data,"",hash_preset,opts)
enc_d = mmgen_encrypt(data,"user data","",opts)
if outfile == '-':
write_to_stdout(enc_d,"encrypted data",confirm=True)
else:
@ -427,9 +427,9 @@ def encrypt(infile,outfile="",hash_preset='3'):
write_to_file(outfile, enc_d, opts,"encrypted data",True,True)
def decrypt(infile,outfile="",hash_preset='3'):
def decrypt(infile,outfile="",hash_preset=''):
enc_d = get_data_from_file(infile,"encrypted data")
dec_d = mmgen_decrypt(enc_d,"",hash_preset,opts)
dec_d = mmgen_decrypt(enc_d,"user data","",opts)
if outfile == '-':
write_to_stdout(dec_d,"decrypted data",confirm=True)
else:

View file

@ -137,6 +137,7 @@ def is_btc_amt(amt):
def normalize_btc_amt(amt):
# amt must be a string!
ret = is_btc_amt(amt)
if ret: return ret
else: sys.exit(3)
@ -460,10 +461,15 @@ def is_b58_str(s):
if ch not in b58a: return False
return True
def is_btc_key(s):
if s == "": return False
compressed = False if s[0] == '5' else True
from mmgen.bitcoin import wiftohex
return True if wiftohex(s,compressed) else False
def mmaddr2btcaddr_bitcoind(c,mmaddr,acct_data):
# We don't want to create a new object, so we'll use append()
# Don't want to create a new object, so use append()
if not acct_data:
for i in c.listaccounts():
acct_data.append(i)
@ -677,31 +683,21 @@ def sign_tx_with_bitcoind_wallet(c,tx_hex,sig_data,keys,opts):
return sig_tx
def preverify_keys(addrs_orig, keys_orig):
def preverify_keys(addrs_in, keys_in, mm_inputs):
addrs,keys,wrong_keys = set(addrs_orig[0:]),set(keys_orig[0:]),[]
if len(keys) < len(addrs):
msg("ERROR: not enough keys (%s) for number of non-%s addresses (%s)" %
(len(keys),g.proj_name,len(addrs)))
sys.exit(2)
addrs,keys,extra_keys = set(addrs_in),set(keys_in),[]
import mmgen.bitcoin as b
qmsg_r('Checking that user-supplied key list contains valid keys...')
invalid_keys = []
for n,k in enumerate(keys,1):
c = False if k[0] == '5' else True
if b.wiftohex(k,compressed=c) == False:
invalid_keys.append(k)
invalid_keys = [k for k in keys if not is_btc_key(k)]
if invalid_keys:
s = "" if len(invalid_keys) == 1 else "s"
msg("\n%s/%s invalid key%s in keylist!\n" % (len(invalid_keys),len(keys),s))
sys.exit(2)
else: qmsg("OK")
qmsg("OK")
# Check that keys match addresses:
msg('Pre-verifying keys in user-supplied key list (Ctrl-C to skip)')
@ -716,19 +712,23 @@ def preverify_keys(addrs_orig, keys_orig):
addrs.remove(addr)
if not addrs: break
else:
wrong_keys.append(k)
extra_keys.append(k)
except KeyboardInterrupt:
msg("\nSkipping")
else:
msg("")
if wrong_keys:
s = "" if len(wrong_keys) == 1 else "s"
msg("%s extra key%s found" % (len(wrong_keys),s))
if extra_keys:
s = "" if len(extra_keys) == 1 else "s"
msg("%s extra key%s found" % (len(extra_keys),s))
if addrs:
mms = dict([(i['address'],i['account'].split()[0])
for i in mm_inputs if i['address'] in addrs])
s = "" if len(addrs) == 1 else "es"
msg("No keys found for the following address%s:" % s)
print " %s" % "\n ".join(addrs)
msg(
"Cannot sign transaction. No keys found for the following address%s:"%s)
for a in sorted(addrs):
print " %s%s" % (a, " ({})".format(mms[a]) if a in mms else "")
sys.exit(2)

View file

@ -347,14 +347,14 @@ def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=
if 'outdir' in opts: outfile = make_full_path(opts['outdir'],outfile)
if confirm_overwrite:
from os import stat
try:
stat(outfile)
except:
pass
else:
from os import stat
try: stat(outfile)
except: pass
else:
if confirm_overwrite:
confirm_or_exit("","File '%s' already exists\nOverwrite?" % outfile)
else:
msg("Overwriting file '%s'" % outfile)
f = open_file_or_exit(outfile,'w')
try:
@ -685,8 +685,9 @@ def export_to_hidden_incog(incog_enc,opts):
from mmgen.term import kb_hold_protect,get_char
def get_hash_preset_from_user(hp='3'):
p = "Enter hash preset, or hit ENTER to accept the default ('%s'): " % hp
def get_hash_preset_from_user(hp='3',what="data"):
p = "Enter hash preset for %s, or ENTER to accept the default ('%s'): " \
% (what,hp)
while True:
ret = my_raw_input(p)
if ret: