whitespace: wallet
This commit is contained in:
parent
362e581798
commit
7fdaba0f78
15 changed files with 239 additions and 227 deletions
|
|
@ -15,31 +15,42 @@ wallet.__init__: wallet class initializer
|
|||
import importlib
|
||||
from collections import namedtuple
|
||||
|
||||
from ..util import die,get_extension
|
||||
from ..util import die, get_extension
|
||||
from ..objmethods import MMGenObject
|
||||
from ..seed import Seed
|
||||
|
||||
_wd = namedtuple('wallet_data', ['type','name','ext','base_type','enc','fmt_codes'])
|
||||
_wd = namedtuple('wallet_data', ['type', 'name', 'ext', 'base_type', 'enc', 'fmt_codes'])
|
||||
|
||||
wallet_data = {
|
||||
'bip39': _wd('bip39', 'BIP39Mnemonic', 'bip39', 'mnemonic', False,('bip39',)),
|
||||
'brain': _wd('brain', 'Brainwallet', 'mmbrain',None, True, ('mmbrain','brainwallet','brain','bw')),
|
||||
'dieroll': _wd('dieroll', 'DieRollWallet', 'b6d', None, False,('b6d','die','dieroll')),
|
||||
'incog': _wd('incog', 'IncogWallet', 'mmincog','incog_base',True, ('mmincog','incog','icg','i')),
|
||||
'incog_hex': _wd('incog_hex', 'IncogWalletHex', 'mmincox','incog_base',True, ('mmincox','incox','incog_hex','ix','xi')),
|
||||
'incog_hidden':_wd('incog_hidden','IncogWalletHidden',None, 'incog_base',True, ('incog_hidden','hincog','ih','hi')),
|
||||
'mmgen': _wd('mmgen', 'MMGenWallet', 'mmdat', None, True, ('wallet','w')),
|
||||
'mmhex': _wd('mmhex', 'MMGenHexSeedFile', 'mmhex', None, False,('seedhex','hexseed','mmhex')),
|
||||
'plainhex': _wd('plainhex', 'PlainHexSeedFile', 'hex', None, False,('hex','rawhex','plainhex')),
|
||||
'seed': _wd('seed', 'MMGenSeedFile', 'mmseed', None, False,('mmseed','seed','s')),
|
||||
'words': _wd('words', 'MMGenMnemonic', 'mmwords','mnemonic', False,('mmwords','words','mnemonic','mn','m')),
|
||||
'bip39':
|
||||
_wd('bip39', 'BIP39Mnemonic', 'bip39', 'mnemonic', False, ('bip39',)),
|
||||
'brain':
|
||||
_wd('brain', 'Brainwallet', 'mmbrain', None, True, ('mmbrain','brainwallet','brain','bw')),
|
||||
'dieroll':
|
||||
_wd('dieroll', 'DieRollWallet', 'b6d', None, False, ('b6d','die','dieroll')),
|
||||
'incog':
|
||||
_wd('incog', 'IncogWallet', 'mmincog', 'incog_base', True, ('mmincog','incog','icg','i')),
|
||||
'incog_hex':
|
||||
_wd('incog_hex', 'IncogWalletHex', 'mmincox', 'incog_base', True, ('mmincox','incox','incog_hex','ix','xi')),
|
||||
'incog_hidden':
|
||||
_wd('incog_hidden', 'IncogWalletHidden', None, 'incog_base', True, ('incog_hidden','hincog','ih','hi')),
|
||||
'mmgen':
|
||||
_wd('mmgen', 'MMGenWallet', 'mmdat', None, True, ('wallet','w')),
|
||||
'mmhex':
|
||||
_wd('mmhex', 'MMGenHexSeedFile', 'mmhex', None, False, ('seedhex','hexseed','mmhex')),
|
||||
'plainhex':
|
||||
_wd('plainhex', 'PlainHexSeedFile', 'hex', None, False, ('hex','rawhex','plainhex')),
|
||||
'seed':
|
||||
_wd('seed', 'MMGenSeedFile', 'mmseed', None, False, ('mmseed','seed','s')),
|
||||
'words':
|
||||
_wd('words', 'MMGenMnemonic', 'mmwords', 'mnemonic', False, ('mmwords','words','mnemonic','mn','m')),
|
||||
}
|
||||
|
||||
def get_wallet_data(
|
||||
wtype = None,
|
||||
fmt_code = None,
|
||||
ext = None,
|
||||
die_on_fail = False ):
|
||||
die_on_fail = False):
|
||||
|
||||
if wtype:
|
||||
return wallet_data[wtype]
|
||||
|
|
@ -52,7 +63,7 @@ def get_wallet_data(
|
|||
if ext == v.ext:
|
||||
return v
|
||||
else:
|
||||
die(4,'no argument supplied!')
|
||||
die(4, 'no argument supplied!')
|
||||
|
||||
if die_on_fail:
|
||||
if fmt_code:
|
||||
|
|
@ -64,17 +75,17 @@ def get_wallet_cls(
|
|||
wtype = None,
|
||||
fmt_code = None,
|
||||
ext = None,
|
||||
die_on_fail = False ):
|
||||
die_on_fail = False):
|
||||
|
||||
return getattr(
|
||||
importlib.import_module( 'mmgen.wallet.{}'.format(
|
||||
importlib.import_module('mmgen.wallet.{}'.format(
|
||||
wtype or
|
||||
get_wallet_data(
|
||||
fmt_code = fmt_code,
|
||||
ext = ext,
|
||||
die_on_fail = die_on_fail ).type
|
||||
die_on_fail = die_on_fail).type
|
||||
)),
|
||||
'wallet' )
|
||||
'wallet')
|
||||
|
||||
def get_wallet_extensions(key):
|
||||
return {
|
||||
|
|
@ -89,14 +100,14 @@ def format_fmt_codes():
|
|||
','.join(v.fmt_codes)
|
||||
) for v in wallet_data.values()]
|
||||
w = max(len(i[0]) for i in d)
|
||||
ret = [f'{a:<{w}} {b:<9} {c}' for a,b,c in [
|
||||
('Format','FileExt','Valid codes'),
|
||||
('------','-------','-----------')
|
||||
] + sorted(d) ]
|
||||
ret = [f'{a:<{w}} {b:<9} {c}' for a, b, c in [
|
||||
('Format', 'FileExt', 'Valid codes'),
|
||||
('------', '-------', '-----------')
|
||||
] + sorted(d)]
|
||||
return '\n'.join(ret) + '\n'
|
||||
|
||||
def _get_me(modname):
|
||||
return MMGenObject.__new__( getattr( importlib.import_module(f'mmgen.wallet.{modname}'), 'wallet' ) )
|
||||
return MMGenObject.__new__(getattr(importlib.import_module(f'mmgen.wallet.{modname}'), 'wallet'))
|
||||
|
||||
def Wallet(
|
||||
cfg,
|
||||
|
|
@ -108,42 +119,42 @@ def Wallet(
|
|||
in_data = None,
|
||||
ignore_in_fmt = False,
|
||||
in_fmt = None,
|
||||
passwd_file = None ):
|
||||
passwd_file = None):
|
||||
|
||||
in_fmt = in_fmt or cfg.in_fmt
|
||||
|
||||
ss_out = (
|
||||
get_wallet_data(
|
||||
fmt_code = cfg.out_fmt,
|
||||
die_on_fail = True ).type
|
||||
if cfg.out_fmt else None )
|
||||
die_on_fail = True).type
|
||||
if cfg.out_fmt else None)
|
||||
|
||||
if seed or seed_bin:
|
||||
me = _get_me( ss_out or 'mmgen' ) # default to native wallet format
|
||||
me.seed = seed or Seed( cfg, seed_bin=seed_bin )
|
||||
me = _get_me(ss_out or 'mmgen') # default to native wallet format
|
||||
me.seed = seed or Seed(cfg, seed_bin=seed_bin)
|
||||
me.op = 'new'
|
||||
elif ss:
|
||||
me = _get_me( ss.type if passchg else (ss_out or 'mmgen') )
|
||||
me = _get_me(ss.type if passchg else (ss_out or 'mmgen'))
|
||||
me.seed = ss.seed
|
||||
me.ss_in = ss
|
||||
me.op = 'pwchg_new' if passchg else 'conv'
|
||||
elif fn or cfg.hidden_incog_input_params:
|
||||
if fn:
|
||||
wd = get_wallet_data(ext=get_extension(fn),die_on_fail=True)
|
||||
wd = get_wallet_data(ext=get_extension(fn), die_on_fail=True)
|
||||
if in_fmt and (not ignore_in_fmt) and in_fmt not in wd.fmt_codes:
|
||||
die(1,f'{in_fmt}: --in-fmt parameter does not match extension of input file')
|
||||
me = _get_me( wd.type )
|
||||
die(1, f'{in_fmt}: --in-fmt parameter does not match extension of input file')
|
||||
me = _get_me(wd.type)
|
||||
else:
|
||||
fn = ','.join(cfg.hidden_incog_input_params.split(',')[:-1]) # permit comma in filename
|
||||
me = _get_me( 'incog_hidden' )
|
||||
me = _get_me('incog_hidden')
|
||||
from ..filename import MMGenFile
|
||||
me.infile = MMGenFile( fn, subclass=type(me) )
|
||||
me.infile = MMGenFile(fn, subclass=type(me))
|
||||
me.op = 'pwchg_old' if passchg else 'old'
|
||||
elif in_fmt:
|
||||
me = _get_me( get_wallet_data(fmt_code=in_fmt).type )
|
||||
me = _get_me(get_wallet_data(fmt_code=in_fmt).type)
|
||||
me.op = 'pwchg_old' if passchg else 'old'
|
||||
else: # called with no arguments: initialize with random seed
|
||||
me = _get_me( ss_out or 'mmgen' ) # default to native wallet format
|
||||
me = _get_me(ss_out or 'mmgen') # default to native wallet format
|
||||
me.seed = Seed(cfg)
|
||||
me.op = 'new'
|
||||
|
||||
|
|
@ -151,9 +162,9 @@ def Wallet(
|
|||
|
||||
me.__init__(
|
||||
in_data = in_data,
|
||||
passwd_file = passwd_file )
|
||||
passwd_file = passwd_file)
|
||||
|
||||
return me
|
||||
|
||||
def check_wallet_extension(fn):
|
||||
get_wallet_data( ext=get_extension(fn), die_on_fail=True ) # raises exception on failure
|
||||
get_wallet_data(ext=get_extension(fn), die_on_fail=True) # raises exception on failure
|
||||
|
|
|
|||
|
|
@ -14,20 +14,20 @@ wallet.base: wallet base class
|
|||
|
||||
import os
|
||||
|
||||
from ..util import msg,die
|
||||
from ..util import msg, die
|
||||
from ..color import orange
|
||||
from ..objmethods import MMGenObject
|
||||
from . import wallet_data,get_wallet_cls
|
||||
from . import wallet_data, get_wallet_cls
|
||||
|
||||
class WalletMeta(type):
|
||||
|
||||
def __init__(cls,name,bases,namespace):
|
||||
t = cls.__module__.rsplit('.',maxsplit=1)[-1]
|
||||
def __init__(cls, name, bases, namespace):
|
||||
t = cls.__module__.rsplit('.', maxsplit=1)[-1]
|
||||
if t in wallet_data:
|
||||
for k,v in wallet_data[t]._asdict().items():
|
||||
setattr(cls,k,v)
|
||||
for k, v in wallet_data[t]._asdict().items():
|
||||
setattr(cls, k, v)
|
||||
|
||||
class wallet(MMGenObject,metaclass=WalletMeta):
|
||||
class wallet(MMGenObject, metaclass=WalletMeta):
|
||||
|
||||
desc = 'MMGen seed source'
|
||||
file_mode = 'text'
|
||||
|
|
@ -42,7 +42,7 @@ class wallet(MMGenObject,metaclass=WalletMeta):
|
|||
|
||||
def __init__(self,
|
||||
in_data = None,
|
||||
passwd_file = None ):
|
||||
passwd_file = None):
|
||||
|
||||
self.passwd_file = None if passwd_file is False else (passwd_file or self.cfg.passwd_file)
|
||||
self.ssdata = self.WalletData()
|
||||
|
|
@ -50,18 +50,18 @@ class wallet(MMGenObject,metaclass=WalletMeta):
|
|||
self.in_data = in_data
|
||||
|
||||
for c in reversed(self.__class__.__mro__):
|
||||
if hasattr(c,'_msg'):
|
||||
if hasattr(c, '_msg'):
|
||||
self.msg.update(c._msg)
|
||||
|
||||
if hasattr(self,'seed'):
|
||||
if hasattr(self, 'seed'):
|
||||
self._encrypt()
|
||||
return
|
||||
elif hasattr(self,'infile') or self.in_data or not self.cfg.stdin_tty:
|
||||
elif hasattr(self, 'infile') or self.in_data or not self.cfg.stdin_tty:
|
||||
self._deformat_once()
|
||||
self._decrypt_retry()
|
||||
else:
|
||||
if not self.stdin_ok:
|
||||
die(1,f'Reading from standard input not supported for {self.desc} format')
|
||||
die(1, f'Reading from standard input not supported for {self.desc} format')
|
||||
self._deformat_retry()
|
||||
self._decrypt_retry()
|
||||
|
||||
|
|
@ -69,31 +69,31 @@ class wallet(MMGenObject,metaclass=WalletMeta):
|
|||
a = self.desc,
|
||||
b = self.seed.sid.hl(),
|
||||
c = f' (seed length {self.seed.bitlen})' if self.seed.bitlen != 256 else '',
|
||||
d = '' if not hasattr(self,'mnemonic') or self.mnemonic.has_chksum else
|
||||
d = '' if not hasattr(self, 'mnemonic') or self.mnemonic.has_chksum else
|
||||
orange(' [mnemonic format has no checksum]')
|
||||
))
|
||||
|
||||
def _get_data(self):
|
||||
if hasattr(self,'infile'):
|
||||
if hasattr(self, 'infile'):
|
||||
from ..fileutil import get_data_from_file
|
||||
self.fmt_data = get_data_from_file(
|
||||
self.cfg,
|
||||
self.infile.name,
|
||||
self.desc,
|
||||
binary = self.file_mode=='binary' )
|
||||
binary = self.file_mode=='binary')
|
||||
elif self.in_data:
|
||||
self.fmt_data = self.in_data
|
||||
else:
|
||||
self.fmt_data = self._get_data_from_user(self.desc)
|
||||
|
||||
def _get_data_from_user(self,desc):
|
||||
def _get_data_from_user(self, desc):
|
||||
from ..ui import get_data_from_user
|
||||
return get_data_from_user( self.cfg, desc )
|
||||
return get_data_from_user(self.cfg, desc)
|
||||
|
||||
def _deformat_once(self):
|
||||
self._get_data()
|
||||
if not self._deformat():
|
||||
die(2,'Invalid format for input data')
|
||||
die(2, 'Invalid format for input data')
|
||||
|
||||
def _deformat_retry(self):
|
||||
while True:
|
||||
|
|
@ -110,7 +110,7 @@ class wallet(MMGenObject,metaclass=WalletMeta):
|
|||
self._format()
|
||||
return self.fmt_data
|
||||
|
||||
def write_to_file(self,outdir='',desc=''):
|
||||
def write_to_file(self, outdir='', desc=''):
|
||||
self._format()
|
||||
kwargs = {
|
||||
'desc': desc or self.desc,
|
||||
|
|
@ -121,16 +121,16 @@ class wallet(MMGenObject,metaclass=WalletMeta):
|
|||
|
||||
if outdir:
|
||||
# write_data_to_file(): outfile with absolute path overrides self.cfg.outdir
|
||||
of = os.path.abspath(os.path.join(outdir,self._filename()))
|
||||
of = os.path.abspath(os.path.join(outdir, self._filename()))
|
||||
|
||||
from ..fileutil import write_data_to_file
|
||||
write_data_to_file(
|
||||
self.cfg,
|
||||
of if outdir else self._filename(),
|
||||
self.fmt_data,
|
||||
**kwargs )
|
||||
**kwargs)
|
||||
|
||||
def check_usr_seed_len(self,bitlen=None):
|
||||
def check_usr_seed_len(self, bitlen=None):
|
||||
chk = bitlen or self.seed.bitlen
|
||||
if self.cfg.seed_len and self.cfg.seed_len != chk:
|
||||
die(1,f'ERROR: requested seed length ({self.cfg.seed_len}) doesn’t match seed length of source ({chk})')
|
||||
die(1, f'ERROR: requested seed length ({self.cfg.seed_len}) doesn’t match seed length of source ({chk})')
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class wallet(wallet):
|
|||
mn_type = 'BIP39'
|
||||
wl_id = 'bip39'
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
from ..bip39 import bip39
|
||||
self.conv_cls = bip39
|
||||
super().__init__(*args,**kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class wallet(wallet):
|
|||
def get_bw_params(self):
|
||||
# already checked
|
||||
a = self.cfg.brain_params.split(',')
|
||||
return int(a[0]),a[1]
|
||||
return int(a[0]), a[1]
|
||||
|
||||
def _deformat(self):
|
||||
self.brainpasswd = ' '.join(self.fmt_data.split())
|
||||
|
|
@ -35,11 +35,11 @@ class wallet(wallet):
|
|||
def _decrypt(self):
|
||||
d = self.ssdata
|
||||
if self.cfg.brain_params:
|
||||
bw_seed_len,d.hash_preset = self.get_bw_params()
|
||||
bw_seed_len, d.hash_preset = self.get_bw_params()
|
||||
else:
|
||||
if not self.cfg.seed_len:
|
||||
self.cfg._util.qmsg(f'Using default seed length of {yellow(str(Seed.dfl_len))} bits\n'
|
||||
+ 'If this is not what you want, use the --seed-len option' )
|
||||
+ 'If this is not what you want, use the --seed-len option')
|
||||
self._get_hash_preset()
|
||||
bw_seed_len = self.cfg.seed_len or Seed.dfl_len
|
||||
self.cfg._util.qmsg_r('Hashing brainwallet data. Please wait...')
|
||||
|
|
@ -48,9 +48,9 @@ class wallet(wallet):
|
|||
self.brainpasswd.encode(),
|
||||
b'',
|
||||
d.hash_preset,
|
||||
buflen = bw_seed_len // 8 )
|
||||
buflen = bw_seed_len // 8)
|
||||
self.cfg._util.qmsg('Done')
|
||||
self.seed = Seed( self.cfg, seed )
|
||||
self.seed = Seed(self.cfg, seed)
|
||||
msg(f'Seed ID: {self.seed.sid}')
|
||||
self.cfg._util.qmsg('Check this value against your records')
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ wallet.dieroll: dieroll wallet class
|
|||
"""
|
||||
|
||||
import time
|
||||
from ..util import msg,msg_r,die,fmt,remove_whitespace
|
||||
from ..util import msg, msg_r, die, fmt, remove_whitespace
|
||||
from ..util2 import block_format
|
||||
from ..seed import Seed
|
||||
from ..baseconv import baseconv
|
||||
|
|
@ -32,8 +32,8 @@ class wallet(wallet):
|
|||
interactive_input = False
|
||||
|
||||
def _format(self):
|
||||
d = baseconv('b6d').frombytes(self.seed.data,pad='seed',tostr=True) + '\n'
|
||||
self.fmt_data = block_format(d,gw=5,cols=5)
|
||||
d = baseconv('b6d').frombytes(self.seed.data, pad='seed', tostr=True) + '\n'
|
||||
self.fmt_data = block_format(d, gw=5, cols=5)
|
||||
|
||||
def _deformat(self):
|
||||
|
||||
|
|
@ -42,34 +42,34 @@ class wallet(wallet):
|
|||
rmap = bc.seedlen_map_rev
|
||||
|
||||
if not len(d) in rmap:
|
||||
die( 'SeedLengthError', '{!r}: invalid length for {} (must be one of {})'.format(
|
||||
die('SeedLengthError', '{!r}: invalid length for {} (must be one of {})'.format(
|
||||
len(d),
|
||||
self.desc,
|
||||
list(rmap) ))
|
||||
list(rmap)))
|
||||
|
||||
# truncate seed to correct length, discarding high bits
|
||||
seed_len = rmap[len(d)]
|
||||
seed_bytes = bc.tobytes( d, pad='seed' )[-seed_len:]
|
||||
seed_bytes = bc.tobytes(d, pad='seed')[-seed_len:]
|
||||
|
||||
if self.interactive_input and self.cfg.usr_randchars:
|
||||
from ..ui import keypress_confirm
|
||||
if keypress_confirm( self.cfg, self.user_entropy_prompt ):
|
||||
if keypress_confirm(self.cfg, self.user_entropy_prompt):
|
||||
from ..crypto import Crypto
|
||||
seed_bytes = Crypto(self.cfg).add_user_random(
|
||||
rand_bytes = seed_bytes,
|
||||
desc = 'gathered from your die rolls' )
|
||||
desc = 'gathered from your die rolls')
|
||||
self.desc += ' plus user-supplied entropy'
|
||||
|
||||
self.seed = Seed( self.cfg, seed_bytes )
|
||||
self.seed = Seed(self.cfg, seed_bytes)
|
||||
|
||||
self.check_usr_seed_len()
|
||||
return True
|
||||
|
||||
def _get_data_from_user(self,desc):
|
||||
def _get_data_from_user(self, desc):
|
||||
|
||||
if not self.cfg.stdin_tty:
|
||||
from ..ui import get_data_from_user
|
||||
return get_data_from_user( self.cfg, desc )
|
||||
return get_data_from_user(self.cfg, desc)
|
||||
|
||||
bc = baseconv('b6d')
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ class wallet(wallet):
|
|||
enter the result on the keyboard as a digit. If you make an invalid entry,
|
||||
you'll be prompted to re-enter it.
|
||||
"""
|
||||
msg('\n'+fmt(message.strip()).format(sb=seed_bitlen,nd=nDierolls)+'\n')
|
||||
msg('\n'+fmt(message.strip()).format(sb=seed_bitlen, nd=nDierolls)+'\n')
|
||||
|
||||
CUR_HIDE = '\033[?25l'
|
||||
CUR_SHOW = '\033[?25h'
|
||||
|
|
@ -104,7 +104,7 @@ class wallet(wallet):
|
|||
p = prompt_fs
|
||||
while True:
|
||||
time.sleep(self.cfg.short_disp_timeout)
|
||||
ch = get_char(p.format(n),num_bytes=1)
|
||||
ch = get_char(p.format(n), num_bytes=1)
|
||||
if ch in bc.digits:
|
||||
msg_r(CUR_HIDE + ' OK')
|
||||
return ch
|
||||
|
|
@ -112,7 +112,7 @@ class wallet(wallet):
|
|||
msg_r(invalid_msg)
|
||||
p = clear_line + prompt_fs
|
||||
|
||||
dierolls,n = [],1
|
||||
dierolls, n = [], 1
|
||||
while len(dierolls) < nDierolls:
|
||||
dierolls.append(get_digit(n))
|
||||
n += 1
|
||||
|
|
|
|||
|
|
@ -13,36 +13,36 @@ wallet.enc: encrypted wallet base class
|
|||
"""
|
||||
|
||||
from ..cfg import gc
|
||||
from ..util import msg,make_chksum_8,die
|
||||
from ..util import msg, make_chksum_8, die
|
||||
from .base import wallet
|
||||
|
||||
class wallet(wallet):
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
from ..crypto import Crypto
|
||||
self.crypto = Crypto(self.cfg)
|
||||
super().__init__(*args,**kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _decrypt_retry(self):
|
||||
while True:
|
||||
if self._decrypt():
|
||||
break
|
||||
if self.passwd_file:
|
||||
die(2,'Passphrase from password file, so exiting')
|
||||
die(2, 'Passphrase from password file, so exiting')
|
||||
msg('Trying again...')
|
||||
|
||||
def _get_hash_preset_from_user(self,old_preset,add_desc=''):
|
||||
def _get_hash_preset_from_user(self, old_preset, add_desc=''):
|
||||
prompt = 'Enter {}hash preset for {}{}{},\nor hit ENTER to {} value ({!r}): '.format(
|
||||
('old ' if self.op=='pwchg_old' else 'new ' if self.op=='pwchg_new' else ''),
|
||||
('','new ')[self.op=='new'],
|
||||
('', 'new ')[self.op=='new'],
|
||||
self.desc,
|
||||
('',' '+add_desc)[bool(add_desc)],
|
||||
('accept the default','reuse the old')[self.op=='pwchg_new'],
|
||||
old_preset )
|
||||
return self.crypto.get_hash_preset_from_user( old_preset=old_preset, prompt=prompt )
|
||||
('', ' '+add_desc)[bool(add_desc)],
|
||||
('accept the default', 'reuse the old')[self.op=='pwchg_new'],
|
||||
old_preset)
|
||||
return self.crypto.get_hash_preset_from_user(old_preset=old_preset, prompt=prompt)
|
||||
|
||||
def _get_hash_preset(self,add_desc=''):
|
||||
if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
|
||||
def _get_hash_preset(self, add_desc=''):
|
||||
if hasattr(self, 'ss_in') and hasattr(self.ss_in.ssdata, 'hash_preset'):
|
||||
old_hp = self.ss_in.ssdata.hash_preset
|
||||
if self.cfg.keep_hash_preset:
|
||||
hp = old_hp
|
||||
|
|
@ -51,7 +51,7 @@ class wallet(wallet):
|
|||
hp = self.cfg.hash_preset
|
||||
self.cfg._util.qmsg(f'Using user-configured hash preset {hp!r}')
|
||||
else: # Prompt, using old value as default
|
||||
hp = self._get_hash_preset_from_user( old_preset=old_hp, add_desc=add_desc )
|
||||
hp = self._get_hash_preset_from_user(old_preset=old_hp, add_desc=add_desc)
|
||||
if (not self.cfg.keep_hash_preset) and self.op == 'pwchg_new':
|
||||
self.cfg._util.qmsg('Hash preset {}'.format(
|
||||
'unchanged' if hp == old_hp else f'changed to {hp!r}'))
|
||||
|
|
@ -61,27 +61,27 @@ class wallet(wallet):
|
|||
else:
|
||||
hp = self._get_hash_preset_from_user(
|
||||
old_preset = gc.dfl_hash_preset,
|
||||
add_desc = add_desc )
|
||||
add_desc = add_desc)
|
||||
self.ssdata.hash_preset = hp
|
||||
|
||||
def _get_new_passphrase(self):
|
||||
return self.crypto.get_new_passphrase(
|
||||
data_desc = ('new ' if self.op in ('new','conv') else '') + self.desc,
|
||||
data_desc = ('new ' if self.op in ('new', 'conv') else '') + self.desc,
|
||||
hash_preset = self.ssdata.hash_preset,
|
||||
passwd_file = self.passwd_file,
|
||||
pw_desc = ('new ' if self.op=='pwchg_new' else '') + 'passphrase' )
|
||||
pw_desc = ('new ' if self.op=='pwchg_new' else '') + 'passphrase')
|
||||
|
||||
def _get_passphrase(self,add_desc=''):
|
||||
def _get_passphrase(self, add_desc=''):
|
||||
return self.crypto.get_passphrase(
|
||||
data_desc = self.desc + (f' {add_desc}' if add_desc else ''),
|
||||
passwd_file = self.passwd_file,
|
||||
pw_desc = ('old ' if self.op == 'pwchg_old' else '') + 'passphrase' )
|
||||
pw_desc = ('old ' if self.op == 'pwchg_old' else '') + 'passphrase')
|
||||
|
||||
def _get_first_pw_and_hp_and_encrypt_seed(self):
|
||||
d = self.ssdata
|
||||
self._get_hash_preset()
|
||||
|
||||
if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'passwd'):
|
||||
if hasattr(self, 'ss_in') and hasattr(self.ss_in.ssdata, 'passwd'):
|
||||
old_pw = self.ss_in.ssdata.passwd
|
||||
if self.cfg.keep_passphrase:
|
||||
d.passwd = old_pw
|
||||
|
|
@ -89,12 +89,12 @@ class wallet(wallet):
|
|||
else:
|
||||
d.passwd = self._get_new_passphrase()
|
||||
if self.op == 'pwchg_new':
|
||||
self.cfg._util.qmsg('Passphrase {}'.format( 'unchanged' if d.passwd == old_pw else 'changed' ))
|
||||
self.cfg._util.qmsg('Passphrase {}'.format('unchanged' if d.passwd == old_pw else 'changed'))
|
||||
else:
|
||||
d.passwd = self._get_new_passphrase()
|
||||
|
||||
from hashlib import sha256
|
||||
d.salt = sha256( self.crypto.get_random(128) ).digest()[:self.crypto.salt_len]
|
||||
key = self.crypto.make_key( d.passwd, d.salt, d.hash_preset )
|
||||
d.salt = sha256(self.crypto.get_random(128)).digest()[:self.crypto.salt_len]
|
||||
key = self.crypto.make_key(d.passwd, d.salt, d.hash_preset)
|
||||
d.key_id = make_chksum_8(key)
|
||||
d.enc_seed = self.crypto.encrypt_seed( self.seed.data, key )
|
||||
d.enc_seed = self.crypto.encrypt_seed(self.seed.data, key)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ wallet.incog_base: incognito wallet base class
|
|||
"""
|
||||
|
||||
from ..seed import Seed
|
||||
from ..util import msg,make_chksum_8,die
|
||||
from ..util import msg, make_chksum_8, die
|
||||
from .enc import wallet
|
||||
|
||||
class wallet(wallet):
|
||||
|
|
@ -30,16 +30,16 @@ class wallet(wallet):
|
|||
'decrypt_params': " {} hash preset"
|
||||
}
|
||||
|
||||
def _make_iv_chksum(self,s):
|
||||
def _make_iv_chksum(self, s):
|
||||
from hashlib import sha256
|
||||
return sha256(s).hexdigest()[:8].upper()
|
||||
|
||||
def _get_incog_data_len(self,seed_len):
|
||||
def _get_incog_data_len(self, seed_len):
|
||||
return (
|
||||
self.crypto.aesctr_iv_len
|
||||
+ self.crypto.salt_len
|
||||
+ (0 if self.cfg.old_incog_fmt else self.crypto.hincog_chk_len)
|
||||
+ seed_len//8 )
|
||||
+ seed_len//8)
|
||||
|
||||
def _incog_data_size_chk(self):
|
||||
# valid sizes: 56, 64, 72
|
||||
|
|
@ -55,42 +55,42 @@ class wallet(wallet):
|
|||
msg(f'Valid data size for this seed length: {valid_dlen} bytes')
|
||||
for sl in Seed.lens:
|
||||
if dlen == self._get_incog_data_len(sl):
|
||||
die(1,f'Valid seed length for this data size: {sl} bits')
|
||||
die(1, f'Valid seed length for this data size: {sl} bits')
|
||||
msg(f'This data size ({dlen} bytes) is invalid for all available seed lengths')
|
||||
return False
|
||||
|
||||
def _encrypt (self):
|
||||
self._get_first_pw_and_hp_and_encrypt_seed()
|
||||
if self.cfg.old_incog_fmt:
|
||||
die(1,'Writing old-format incognito wallets is unsupported')
|
||||
die(1, 'Writing old-format incognito wallets is unsupported')
|
||||
d = self.ssdata
|
||||
crypto = self.crypto
|
||||
|
||||
d.iv = crypto.get_random( crypto.aesctr_iv_len )
|
||||
d.iv = crypto.get_random(crypto.aesctr_iv_len)
|
||||
d.iv_id = self._make_iv_chksum(d.iv)
|
||||
msg(f'New Incog Wallet ID: {d.iv_id}')
|
||||
self.cfg._util.qmsg('Make a record of this value')
|
||||
self.cfg._util.vmsg('\n ' + self.msg['record_incog_id'].strip()+'\n')
|
||||
|
||||
d.salt = crypto.get_random( crypto.salt_len )
|
||||
d.salt = crypto.get_random(crypto.salt_len)
|
||||
seed_key = crypto.make_key(
|
||||
passwd = d.passwd,
|
||||
salt = d.salt,
|
||||
hash_preset = d.hash_preset,
|
||||
desc = 'incog wallet key' )
|
||||
desc = 'incog wallet key')
|
||||
|
||||
from hashlib import sha256
|
||||
chk = sha256(self.seed.data).digest()[:8]
|
||||
d.enc_seed = crypto.encrypt_seed(
|
||||
data = chk + self.seed.data,
|
||||
key = seed_key )
|
||||
key = seed_key)
|
||||
|
||||
# IV is used BOTH to initialize counter and to salt password!
|
||||
d.wrapper_key = crypto.make_key(
|
||||
passwd = d.passwd,
|
||||
salt = d.iv,
|
||||
hash_preset = d.hash_preset,
|
||||
desc = 'incog wrapper key' )
|
||||
desc = 'incog wrapper key')
|
||||
|
||||
d.key_id = make_chksum_8(d.wrapper_key)
|
||||
self.cfg._util.vmsg(f'Key ID: {d.key_id}')
|
||||
|
|
@ -103,7 +103,7 @@ class wallet(wallet):
|
|||
data = d.salt + d.enc_seed,
|
||||
key = d.wrapper_key,
|
||||
iv = d.iv,
|
||||
desc = self.desc )
|
||||
desc = self.desc)
|
||||
|
||||
def _filename(self):
|
||||
s = self.seed
|
||||
|
|
@ -114,7 +114,7 @@ class wallet(wallet):
|
|||
d.iv_id,
|
||||
s.bitlen,
|
||||
d.hash_preset,
|
||||
self.ext )
|
||||
self.ext)
|
||||
|
||||
def _deformat(self):
|
||||
|
||||
|
|
@ -131,20 +131,20 @@ class wallet(wallet):
|
|||
|
||||
return True
|
||||
|
||||
def _verify_seed_newfmt(self,data):
|
||||
chk,seed = data[:8],data[8:]
|
||||
def _verify_seed_newfmt(self, data):
|
||||
chk, seed = data[:8], data[8:]
|
||||
from hashlib import sha256
|
||||
if sha256(seed).digest()[:8] == chk:
|
||||
self.cfg._util.qmsg('Passphrase{} are correct'.format( self.msg['decrypt_params'].format('and') ))
|
||||
self.cfg._util.qmsg('Passphrase{} are correct'.format(self.msg['decrypt_params'].format('and')))
|
||||
return seed
|
||||
else:
|
||||
msg('Incorrect passphrase{}'.format( self.msg['decrypt_params'].format('or') ))
|
||||
msg('Incorrect passphrase{}'.format(self.msg['decrypt_params'].format('or')))
|
||||
return False
|
||||
|
||||
def _verify_seed_oldfmt(self,seed):
|
||||
def _verify_seed_oldfmt(self, seed):
|
||||
m = f'Seed ID: {make_chksum_8(seed)}. Is the Seed ID correct?'
|
||||
from ..ui import keypress_confirm
|
||||
if keypress_confirm( self.cfg, m, True ):
|
||||
if keypress_confirm(self.cfg, m, True):
|
||||
return seed
|
||||
else:
|
||||
return False
|
||||
|
|
@ -160,13 +160,13 @@ class wallet(wallet):
|
|||
passwd = d.passwd,
|
||||
salt = d.iv,
|
||||
hash_preset = d.hash_preset,
|
||||
desc = 'wrapper key' )
|
||||
desc = 'wrapper key')
|
||||
|
||||
dd = crypto.decrypt_data(
|
||||
enc_data = d.enc_incog_data,
|
||||
key = wrapper_key,
|
||||
iv = d.iv,
|
||||
desc = 'incog data' )
|
||||
desc = 'incog data')
|
||||
|
||||
d.salt = dd[0:crypto.salt_len]
|
||||
d.enc_seed = dd[crypto.salt_len:]
|
||||
|
|
@ -175,21 +175,21 @@ class wallet(wallet):
|
|||
passwd = d.passwd,
|
||||
salt = d.salt,
|
||||
hash_preset = d.hash_preset,
|
||||
desc = 'main key' )
|
||||
desc = 'main key')
|
||||
|
||||
self.cfg._util.qmsg(f'Key ID: {make_chksum_8(seed_key)}')
|
||||
|
||||
verify_seed_func = getattr( self, '_verify_seed_'+ ('oldfmt' if self.cfg.old_incog_fmt else 'newfmt') )
|
||||
verify_seed_func = getattr(self, '_verify_seed_'+ ('oldfmt' if self.cfg.old_incog_fmt else 'newfmt'))
|
||||
|
||||
seed = verify_seed_func(
|
||||
crypto.decrypt_seed(
|
||||
enc_seed = d.enc_seed,
|
||||
key = seed_key,
|
||||
seed_id = '',
|
||||
key_id = '' ))
|
||||
key_id = ''))
|
||||
|
||||
if seed:
|
||||
self.seed = Seed( self.cfg, seed )
|
||||
self.seed = Seed(self.cfg, seed)
|
||||
msg(f'Seed ID: {self.seed.sid}')
|
||||
return True
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
wallet.incog_hex: hexadecimal incognito wallet class
|
||||
"""
|
||||
|
||||
from ..util2 import pretty_hexdump,decode_pretty_hexdump
|
||||
from ..util2 import pretty_hexdump, decode_pretty_hexdump
|
||||
from .incog_base import wallet
|
||||
|
||||
class wallet(wallet):
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
wallet.incog_hidden: hidden incognito wallet class
|
||||
"""
|
||||
|
||||
import sys,os
|
||||
import sys, os
|
||||
|
||||
from ..seed import Seed
|
||||
from ..util import msg,die,capfirst
|
||||
from ..util import msg, die, capfirst
|
||||
from ..util2 import parse_bytespec
|
||||
from .incog_base import wallet
|
||||
|
||||
|
|
@ -46,21 +46,21 @@ class wallet(wallet):
|
|||
'decrypt_params': ', hash preset, offset {} seed length'
|
||||
}
|
||||
|
||||
def _get_hincog_params(self,wtype):
|
||||
a = getattr(self.cfg,'hidden_incog_'+ wtype +'_params').split(',')
|
||||
return ','.join(a[:-1]),int(a[-1]) # permit comma in filename
|
||||
def _get_hincog_params(self, wtype):
|
||||
a = getattr(self.cfg, 'hidden_incog_'+ wtype +'_params').split(',')
|
||||
return ','.join(a[:-1]), int(a[-1]) # permit comma in filename
|
||||
|
||||
def _check_valid_offset(self,fn,action):
|
||||
def _check_valid_offset(self, fn, action):
|
||||
d = self.ssdata
|
||||
m = ('Input','Destination')[action=='write']
|
||||
m = ('Input', 'Destination')[action=='write']
|
||||
if fn.size < d.hincog_offset + d.target_data_len:
|
||||
die(1,'{a} file {b!r} has length {c}, too short to {d} {e} bytes of data at offset {f}'.format(
|
||||
die(1, '{a} file {b!r} has length {c}, too short to {d} {e} bytes of data at offset {f}'.format(
|
||||
a = m,
|
||||
b = fn.name,
|
||||
c = fn.size,
|
||||
d = action,
|
||||
e = d.target_data_len,
|
||||
f = d.hincog_offset ))
|
||||
f = d.hincog_offset))
|
||||
|
||||
def _get_data(self):
|
||||
d = self.ssdata
|
||||
|
|
@ -70,77 +70,77 @@ class wallet(wallet):
|
|||
|
||||
# Already sanity-checked:
|
||||
d.target_data_len = self._get_incog_data_len(self.cfg.seed_len or Seed.dfl_len)
|
||||
self._check_valid_offset(self.infile,'read')
|
||||
self._check_valid_offset(self.infile, 'read')
|
||||
|
||||
flgs = os.O_RDONLY|os.O_BINARY if sys.platform == 'win32' else os.O_RDONLY
|
||||
fh = os.open(self.infile.name,flgs)
|
||||
os.lseek(fh,int(d.hincog_offset),os.SEEK_SET)
|
||||
self.fmt_data = os.read(fh,d.target_data_len)
|
||||
fh = os.open(self.infile.name, flgs)
|
||||
os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
|
||||
self.fmt_data = os.read(fh, d.target_data_len)
|
||||
os.close(fh)
|
||||
self.cfg._util.qmsg(f'Data read from file {self.infile.name!r} at offset {d.hincog_offset}')
|
||||
|
||||
# overrides method in Wallet
|
||||
def write_to_file(self,**kwargs):
|
||||
def write_to_file(self, **kwargs):
|
||||
d = self.ssdata
|
||||
self._format()
|
||||
self.cfg._util.compare_or_die(
|
||||
val1 = d.target_data_len,
|
||||
desc1 = 'target data length',
|
||||
val2 = len(self.fmt_data),
|
||||
desc2 = 'length of formatted ' + self.desc )
|
||||
desc2 = 'length of formatted ' + self.desc)
|
||||
|
||||
k = ('output','input')[self.op=='pwchg_new']
|
||||
fn,d.hincog_offset = self._get_hincog_params(k)
|
||||
k = ('output', 'input')[self.op=='pwchg_new']
|
||||
fn, d.hincog_offset = self._get_hincog_params(k)
|
||||
|
||||
if self.cfg.outdir and not os.path.dirname(fn):
|
||||
fn = os.path.join(self.cfg.outdir,fn)
|
||||
fn = os.path.join(self.cfg.outdir, fn)
|
||||
|
||||
check_offset = True
|
||||
try:
|
||||
os.stat(fn)
|
||||
except:
|
||||
from ..ui import keypress_confirm,line_input
|
||||
from ..ui import keypress_confirm, line_input
|
||||
if keypress_confirm(
|
||||
self.cfg,
|
||||
f'Requested file {fn!r} does not exist. Create?',
|
||||
default_yes = True ):
|
||||
default_yes = True):
|
||||
min_fsize = d.target_data_len + d.hincog_offset
|
||||
msg('\n ' + self.msg['choose_file_size'].strip().format(min_fsize)+'\n')
|
||||
while True:
|
||||
fsize = parse_bytespec(line_input( self.cfg, 'Enter file size: ' ))
|
||||
fsize = parse_bytespec(line_input(self.cfg, 'Enter file size: '))
|
||||
if fsize >= min_fsize:
|
||||
break
|
||||
msg(f'File size must be an integer no less than {min_fsize}')
|
||||
|
||||
from ..tool.fileutil import tool_cmd
|
||||
tool_cmd(self.cfg).rand2file(fn,str(fsize))
|
||||
tool_cmd(self.cfg).rand2file(fn, str(fsize))
|
||||
check_offset = False
|
||||
else:
|
||||
die(1,'Exiting at user request')
|
||||
die(1, 'Exiting at user request')
|
||||
|
||||
from ..filename import MMGenFile
|
||||
f = MMGenFile(fn,subclass=type(self),write=True)
|
||||
f = MMGenFile(fn, subclass=type(self), write=True)
|
||||
|
||||
self.cfg._util.dmsg('{} data len {}, offset {}'.format(
|
||||
capfirst(self.desc),
|
||||
d.target_data_len,
|
||||
d.hincog_offset ))
|
||||
d.hincog_offset))
|
||||
|
||||
if check_offset:
|
||||
self._check_valid_offset(f,'write')
|
||||
self._check_valid_offset(f, 'write')
|
||||
if not self.cfg.quiet:
|
||||
from ..ui import confirm_or_raise
|
||||
confirm_or_raise(
|
||||
self.cfg,
|
||||
message = '',
|
||||
action = f'alter file {f.name!r}' )
|
||||
action = f'alter file {f.name!r}')
|
||||
|
||||
flgs = os.O_RDWR|os.O_BINARY if sys.platform == 'win32' else os.O_RDWR
|
||||
fh = os.open(f.name,flgs)
|
||||
fh = os.open(f.name, flgs)
|
||||
os.lseek(fh, int(d.hincog_offset), os.SEEK_SET)
|
||||
os.write(fh, self.fmt_data)
|
||||
os.close(fh)
|
||||
msg('{} written to file {!r} at offset {}'.format(
|
||||
capfirst(self.desc),
|
||||
f.name,
|
||||
d.hincog_offset ))
|
||||
d.hincog_offset))
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ wallet.mmgen: MMGen native wallet class
|
|||
import os
|
||||
|
||||
from ..seed import Seed
|
||||
from ..util import msg,make_timestamp,make_chksum_6,split_into_cols,is_chksum_6
|
||||
from ..obj import MMGenWalletLabel,get_obj
|
||||
from ..util import msg, make_timestamp, make_chksum_6, split_into_cols, is_chksum_6
|
||||
from ..obj import MMGenWalletLabel, get_obj
|
||||
from ..baseconv import baseconv
|
||||
|
||||
from .enc import wallet
|
||||
|
|
@ -25,23 +25,23 @@ class wallet(wallet):
|
|||
|
||||
desc = 'MMGen wallet'
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
if self.cfg.label:
|
||||
self.label = MMGenWalletLabel(self.cfg.label)
|
||||
else:
|
||||
self.label = None
|
||||
super().__init__(*args,**kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# logic identical to _get_hash_preset_from_user()
|
||||
def _get_label_from_user(self,old_lbl=''):
|
||||
def _get_label_from_user(self, old_lbl=''):
|
||||
prompt = 'Enter a wallet label, or hit ENTER {}: '.format(
|
||||
'to reuse the label {}'.format(old_lbl.hl2(encl='‘’')) if old_lbl else
|
||||
'for no label' )
|
||||
'for no label')
|
||||
from ..ui import line_input
|
||||
while True:
|
||||
ret = line_input( self.cfg, prompt )
|
||||
ret = line_input(self.cfg, prompt)
|
||||
if ret:
|
||||
lbl = get_obj(MMGenWalletLabel,s=ret)
|
||||
lbl = get_obj(MMGenWalletLabel, s=ret)
|
||||
if lbl:
|
||||
return lbl
|
||||
else:
|
||||
|
|
@ -51,18 +51,18 @@ class wallet(wallet):
|
|||
|
||||
# logic identical to _get_hash_preset()
|
||||
def _get_label(self):
|
||||
if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'label'):
|
||||
if hasattr(self, 'ss_in') and hasattr(self.ss_in.ssdata, 'label'):
|
||||
old_lbl = self.ss_in.ssdata.label
|
||||
if self.cfg.keep_label:
|
||||
lbl = old_lbl
|
||||
self.cfg._util.qmsg('Reusing label {} at user request'.format( lbl.hl2(encl='‘’') ))
|
||||
self.cfg._util.qmsg('Reusing label {} at user request'.format(lbl.hl2(encl='‘’')))
|
||||
elif self.label:
|
||||
lbl = self.label
|
||||
self.cfg._util.qmsg('Using user-configured label {}'.format(lbl.hl2(encl='‘’')))
|
||||
else: # Prompt, using old value as default
|
||||
lbl = self._get_label_from_user(old_lbl)
|
||||
if (not self.cfg.keep_label) and self.op == 'pwchg_new':
|
||||
self.cfg._util.qmsg('Label {}'.format( 'unchanged' if lbl == old_lbl else f'changed to {lbl!r}' ))
|
||||
self.cfg._util.qmsg('Label {}'.format('unchanged' if lbl == old_lbl else f'changed to {lbl!r}'))
|
||||
elif self.label:
|
||||
lbl = self.label
|
||||
self.cfg._util.qmsg('Using user-configured label {}'.format(lbl.hl2(encl='‘’')))
|
||||
|
|
@ -74,28 +74,28 @@ class wallet(wallet):
|
|||
self._get_first_pw_and_hp_and_encrypt_seed()
|
||||
self._get_label()
|
||||
d = self.ssdata
|
||||
d.pw_status = ('NE','E')[len(d.passwd)==0]
|
||||
d.pw_status = ('NE', 'E')[len(d.passwd)==0]
|
||||
d.timestamp = make_timestamp()
|
||||
|
||||
def _format(self):
|
||||
d = self.ssdata
|
||||
s = self.seed
|
||||
bc = baseconv('b58')
|
||||
slt_fmt = bc.frombytes(d.salt,pad='seed',tostr=True)
|
||||
es_fmt = bc.frombytes(d.enc_seed,pad='seed',tostr=True)
|
||||
slt_fmt = bc.frombytes(d.salt, pad='seed', tostr=True)
|
||||
es_fmt = bc.frombytes(d.enc_seed, pad='seed', tostr=True)
|
||||
lines = (
|
||||
d.label,
|
||||
'{} {} {} {} {}'.format( s.sid.lower(), d.key_id.lower(), s.bitlen, d.pw_status, d.timestamp ),
|
||||
'{}: {} {} {}'.format( d.hash_preset, *self.crypto.get_hash_params(d.hash_preset) ),
|
||||
'{} {}'.format( make_chksum_6(slt_fmt), split_into_cols(4,slt_fmt) ),
|
||||
'{} {}'.format( make_chksum_6(es_fmt), split_into_cols(4,es_fmt) )
|
||||
'{} {} {} {} {}'.format(s.sid.lower(), d.key_id.lower(), s.bitlen, d.pw_status, d.timestamp),
|
||||
'{}: {} {} {}'.format(d.hash_preset, *self.crypto.get_hash_params(d.hash_preset)),
|
||||
'{} {}'.format(make_chksum_6(slt_fmt), split_into_cols(4, slt_fmt)),
|
||||
'{} {}'.format(make_chksum_6(es_fmt), split_into_cols(4, es_fmt))
|
||||
)
|
||||
chksum = make_chksum_6(' '.join(lines).encode())
|
||||
self.fmt_data = '\n'.join((chksum,)+lines) + '\n'
|
||||
|
||||
def _deformat(self):
|
||||
|
||||
def check_master_chksum(lines,desc):
|
||||
def check_master_chksum(lines, desc):
|
||||
|
||||
if len(lines) != 6:
|
||||
msg(f'Invalid number of lines ({len(lines)}) in {desc} data')
|
||||
|
|
@ -106,24 +106,24 @@ class wallet(wallet):
|
|||
return False
|
||||
|
||||
chk = make_chksum_6(' '.join(lines[1:]))
|
||||
if not self.cfg._util.compare_chksums(lines[0],'master',chk,'computed',
|
||||
hdr='For wallet master checksum',verbose=True):
|
||||
if not self.cfg._util.compare_chksums(lines[0], 'master', chk, 'computed',
|
||||
hdr='For wallet master checksum', verbose=True):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
lines = self.fmt_data.splitlines()
|
||||
if not check_master_chksum(lines,self.desc):
|
||||
if not check_master_chksum(lines, self.desc):
|
||||
return False
|
||||
|
||||
d = self.ssdata
|
||||
d.label = MMGenWalletLabel(lines[1])
|
||||
|
||||
d1,d2,d3,d4,d5 = lines[2].split()
|
||||
d1, d2, d3, d4, d5 = lines[2].split()
|
||||
d.seed_id = d1.upper()
|
||||
d.key_id = d2.upper()
|
||||
self.check_usr_seed_len(int(d3))
|
||||
d.pw_status,d.timestamp = d4,d5
|
||||
d.pw_status, d.timestamp = d4, d5
|
||||
|
||||
hpdata = lines[3].split()
|
||||
|
||||
|
|
@ -132,14 +132,14 @@ class wallet(wallet):
|
|||
if self.cfg.hash_preset and self.cfg.hash_preset != hp:
|
||||
self.cfg._util.qmsg(f'Warning: ignoring user-requested hash preset {self.cfg.hash_preset!r}')
|
||||
|
||||
hash_params = tuple(map(int,hpdata[1:]))
|
||||
hash_params = tuple(map(int, hpdata[1:]))
|
||||
|
||||
if hash_params != self.crypto.get_hash_params(d.hash_preset):
|
||||
msg(f'Hash parameters {" ".join(hash_params)!r} don’t match hash preset {d.hash_preset!r}')
|
||||
return False
|
||||
|
||||
lmin,_,lmax = sorted(baseconv('b58').seedlen_map_rev) # 22,33,44
|
||||
for i,key in (4,'salt'),(5,'enc_seed'):
|
||||
lmin, _, lmax = sorted(baseconv('b58').seedlen_map_rev) # 22, 33, 44
|
||||
for i, key in (4, 'salt'), (5, 'enc_seed'):
|
||||
l = lines[i].split(' ')
|
||||
chk = l.pop(0)
|
||||
b58_val = ''.join(l)
|
||||
|
|
@ -148,16 +148,20 @@ class wallet(wallet):
|
|||
msg(f'Invalid format for {key} in {self.desc}: {l}')
|
||||
return False
|
||||
|
||||
if not self.cfg._util.compare_chksums(chk,key,
|
||||
make_chksum_6(b58_val),'computed checksum',verbose=True):
|
||||
if not self.cfg._util.compare_chksums(
|
||||
chk,
|
||||
key,
|
||||
make_chksum_6(b58_val),
|
||||
'computed checksum',
|
||||
verbose = True):
|
||||
return False
|
||||
|
||||
val = baseconv('b58').tobytes(b58_val,pad='seed')
|
||||
val = baseconv('b58').tobytes(b58_val, pad='seed')
|
||||
if val is False:
|
||||
msg(f'Invalid base 58 number: {b58_val}')
|
||||
return False
|
||||
|
||||
setattr(d,key,val)
|
||||
setattr(d, key, val)
|
||||
|
||||
return True
|
||||
|
||||
|
|
@ -165,11 +169,11 @@ class wallet(wallet):
|
|||
d = self.ssdata
|
||||
# Needed for multiple transactions with {}-txsign
|
||||
d.passwd = self._get_passphrase(
|
||||
add_desc = os.path.basename(self.infile.name) if self.cfg.quiet else '' )
|
||||
key = self.crypto.make_key( d.passwd, d.salt, d.hash_preset )
|
||||
ret = self.crypto.decrypt_seed( d.enc_seed, key, d.seed_id, d.key_id )
|
||||
add_desc = os.path.basename(self.infile.name) if self.cfg.quiet else '')
|
||||
key = self.crypto.make_key(d.passwd, d.salt, d.hash_preset)
|
||||
ret = self.crypto.decrypt_seed(d.enc_seed, key, d.seed_id, d.key_id)
|
||||
if ret:
|
||||
self.seed = Seed( self.cfg, ret )
|
||||
self.seed = Seed(self.cfg, ret)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
@ -182,4 +186,4 @@ class wallet(wallet):
|
|||
d.key_id,
|
||||
s.bitlen,
|
||||
d.hash_preset,
|
||||
self.ext )
|
||||
self.ext)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@
|
|||
wallet.mmhex: MMGen hexadecimal file wallet class
|
||||
"""
|
||||
|
||||
from ..util import make_chksum_6,split_into_cols
|
||||
from ..util import make_chksum_6, split_into_cols
|
||||
from ..seed import Seed
|
||||
from ..util import msg,is_chksum_6,is_hex_str
|
||||
from ..util import msg, is_chksum_6, is_hex_str
|
||||
from .unenc import wallet
|
||||
|
||||
class wallet(wallet):
|
||||
|
|
@ -25,14 +25,14 @@ class wallet(wallet):
|
|||
def _format(self):
|
||||
h = self.seed.data.hex()
|
||||
self.ssdata.chksum = make_chksum_6(h)
|
||||
self.fmt_data = f'{self.ssdata.chksum} {split_into_cols(4,h)}\n'
|
||||
self.fmt_data = f'{self.ssdata.chksum} {split_into_cols(4, h)}\n'
|
||||
|
||||
def _deformat(self):
|
||||
desc = self.desc
|
||||
d = self.fmt_data.split()
|
||||
try:
|
||||
d[1]
|
||||
chk,hstr = d[0],''.join(d[1:])
|
||||
chk, hstr = d[0], ''.join(d[1:])
|
||||
except:
|
||||
msg(f'{self.fmt_data.strip()!r}: invalid {desc}')
|
||||
return False
|
||||
|
|
@ -51,10 +51,10 @@ class wallet(wallet):
|
|||
|
||||
self.cfg._util.vmsg_r(f'Validating {desc} checksum...')
|
||||
|
||||
if not self.cfg._util.compare_chksums(chk,'file',make_chksum_6(hstr),'computed',verbose=True):
|
||||
if not self.cfg._util.compare_chksums(chk, 'file', make_chksum_6(hstr), 'computed', verbose=True):
|
||||
return False
|
||||
|
||||
self.seed = Seed( self.cfg, bytes.fromhex(hstr) )
|
||||
self.seed = Seed(self.cfg, bytes.fromhex(hstr))
|
||||
self.ssdata.chksum = chk
|
||||
|
||||
self.check_usr_seed_len()
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ class wallet(wallet):
|
|||
def mn_lens(self):
|
||||
return sorted(self.conv_cls(self.wl_id).seedlen_map_rev)
|
||||
|
||||
def _get_data_from_user(self,desc):
|
||||
def _get_data_from_user(self, desc):
|
||||
|
||||
if not self.cfg.stdin_tty:
|
||||
from ..ui import get_data_from_user
|
||||
return get_data_from_user( self.cfg, desc )
|
||||
return get_data_from_user(self.cfg, desc)
|
||||
|
||||
self._print_seed_type()
|
||||
|
||||
|
|
@ -70,10 +70,10 @@ class wallet(wallet):
|
|||
if len(mn) not in self.mn_lens:
|
||||
msg('Invalid mnemonic ({} words). Valid numbers of words: {}'.format(
|
||||
len(mn),
|
||||
', '.join(map(str,self.mn_lens)) ))
|
||||
', '.join(map(str, self.mn_lens))))
|
||||
return False
|
||||
|
||||
for n,w in enumerate(mn,1):
|
||||
for n, w in enumerate(mn, 1):
|
||||
if w not in bc.digits:
|
||||
msg(f'Invalid mnemonic: word #{n} is not in the {self.wl_id.upper()} wordlist')
|
||||
return False
|
||||
|
|
@ -91,7 +91,7 @@ class wallet(wallet):
|
|||
val2 = ' '.join(mn),
|
||||
desc1 = 'recomputed mnemonic',
|
||||
desc2 = 'original mnemonic',
|
||||
e = 'Internal error' )
|
||||
e = 'Internal error')
|
||||
|
||||
self.seed = Seed(self.cfg, seed)
|
||||
self.ssdata.mnemonic = mn
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
wallet.plainhex: plain hexadecimal wallet class
|
||||
"""
|
||||
|
||||
from ..util import msg,is_hex_str_lc
|
||||
from ..util import msg, is_hex_str_lc
|
||||
from ..seed import Seed
|
||||
from .unenc import wallet
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ class wallet(wallet):
|
|||
msg(f'Invalid data length ({len(d)}) in {desc}')
|
||||
return False
|
||||
|
||||
self.seed = Seed( self.cfg, bytes.fromhex(d) )
|
||||
self.seed = Seed(self.cfg, bytes.fromhex(d))
|
||||
|
||||
self.check_usr_seed_len()
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
wallet.seed: seed file wallet class
|
||||
"""
|
||||
|
||||
from ..util import msg,make_chksum_6,split_into_cols,is_chksum_6
|
||||
from ..baseconv import baseconv,is_b58_str
|
||||
from ..util import msg, make_chksum_6, split_into_cols, is_chksum_6
|
||||
from ..baseconv import baseconv, is_b58_str
|
||||
from ..seed import Seed
|
||||
from .unenc import wallet
|
||||
|
||||
|
|
@ -23,12 +23,12 @@ class wallet(wallet):
|
|||
desc = 'seed data'
|
||||
|
||||
def _format(self):
|
||||
b58seed = baseconv('b58').frombytes(self.seed.data,pad='seed',tostr=True)
|
||||
b58seed = baseconv('b58').frombytes(self.seed.data, pad='seed', tostr=True)
|
||||
self.ssdata.chksum = make_chksum_6(b58seed)
|
||||
self.ssdata.b58seed = b58seed
|
||||
self.fmt_data = '{} {}\n'.format(
|
||||
self.ssdata.chksum,
|
||||
split_into_cols(4,b58seed) )
|
||||
split_into_cols(4, b58seed))
|
||||
|
||||
def _deformat(self):
|
||||
desc = self.desc
|
||||
|
|
@ -38,7 +38,7 @@ class wallet(wallet):
|
|||
msg(f'Invalid data length ({len(ld)}) in {desc}')
|
||||
return False
|
||||
|
||||
a,b = ld[0],''.join(ld[1:])
|
||||
a, b = ld[0], ''.join(ld[1:])
|
||||
|
||||
if not is_chksum_6(a):
|
||||
msg(f'{a!r}: invalid checksum format in {desc}')
|
||||
|
|
@ -50,16 +50,16 @@ class wallet(wallet):
|
|||
|
||||
self.cfg._util.vmsg_r(f'Validating {desc} checksum...')
|
||||
|
||||
if not self.cfg._util.compare_chksums(a,'file',make_chksum_6(b),'computed',verbose=True):
|
||||
if not self.cfg._util.compare_chksums(a, 'file', make_chksum_6(b), 'computed', verbose=True):
|
||||
return False
|
||||
|
||||
ret = baseconv('b58').tobytes(b,pad='seed')
|
||||
ret = baseconv('b58').tobytes(b, pad='seed')
|
||||
|
||||
if ret is False:
|
||||
msg(f'Invalid base-58 encoded seed: {b}')
|
||||
return False
|
||||
|
||||
self.seed = Seed( self.cfg, ret )
|
||||
self.seed = Seed(self.cfg, ret)
|
||||
self.ssdata.chksum = a
|
||||
self.ssdata.b58seed = b
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
wallet.unenc: unencrypted wallet base class
|
||||
"""
|
||||
|
||||
from ..color import blue,yellow
|
||||
from ..util import msg,msg_r,capfirst,is_int
|
||||
from ..color import blue, yellow
|
||||
from ..util import msg, msg_r, capfirst, is_int
|
||||
from .base import wallet
|
||||
|
||||
class wallet(wallet):
|
||||
|
|
@ -26,10 +26,7 @@ class wallet(wallet):
|
|||
|
||||
def _filename(self):
|
||||
s = self.seed
|
||||
return '{}[{}].{}'.format(
|
||||
s.fn_stem,
|
||||
s.bitlen,
|
||||
self.ext )
|
||||
return '{}[{}].{}'.format(s.fn_stem, s.bitlen, self.ext)
|
||||
|
||||
def _print_seed_type(self):
|
||||
msg('{} {}'.format(
|
||||
|
|
@ -37,7 +34,7 @@ class wallet(wallet):
|
|||
yellow(self.mn_type)
|
||||
))
|
||||
|
||||
def _choose_seedlen(self,ok_lens):
|
||||
def _choose_seedlen(self, ok_lens):
|
||||
|
||||
from ..term import get_char
|
||||
def choose_len():
|
||||
|
|
@ -46,7 +43,7 @@ class wallet(wallet):
|
|||
r = get_char('\r'+prompt)
|
||||
if is_int(r) and 1 <= int(r) <= len(ok_lens):
|
||||
break
|
||||
msg_r(('\r','\n')[self.cfg.test_suite] + ' '*len(prompt) + '\r')
|
||||
msg_r(('\r', '\n')[self.cfg.test_suite] + ' '*len(prompt) + '\r')
|
||||
return ok_lens[int(r)-1]
|
||||
|
||||
while True:
|
||||
|
|
@ -57,5 +54,5 @@ class wallet(wallet):
|
|||
self.cfg,
|
||||
prompt,
|
||||
default_yes = True,
|
||||
no_nl = not self.cfg.test_suite ):
|
||||
no_nl = not self.cfg.test_suite):
|
||||
return usr_len
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue