2020-03-12 16:59:55 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
#
|
|
|
|
|
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
2022-01-04 19:51:22 +00:00
|
|
|
# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
|
2020-03-12 16:59:55 +00:00
|
|
|
#
|
|
|
|
|
# Project source code repository: https://github.com/mmgen/mmgen
|
|
|
|
|
# Licensed according to the terms of GPL Version 3. See LICENSE for details.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
ts_input.py: user input tests for the MMGen test.py test suite
|
|
|
|
|
"""
|
|
|
|
|
|
2022-10-29 20:10:24 +00:00
|
|
|
import time
|
|
|
|
|
|
2020-03-16 10:45:00 +00:00
|
|
|
from ..include.common import *
|
|
|
|
|
from .ts_base import *
|
|
|
|
|
from .input import *
|
2022-02-08 13:03:32 +00:00
|
|
|
from mmgen.wallet import get_wallet_cls
|
2020-03-12 16:59:55 +00:00
|
|
|
|
|
|
|
|
class TestSuiteInput(TestSuiteBase):
|
|
|
|
|
'user input'
|
|
|
|
|
networks = ('btc',)
|
2022-10-29 20:10:23 +00:00
|
|
|
tmpdir_nums = [1]
|
2020-06-03 12:29:50 +00:00
|
|
|
color = True
|
2022-10-29 20:10:23 +00:00
|
|
|
cmd_group_in = (
|
2022-10-29 20:10:24 +00:00
|
|
|
('subgroup.char', []),
|
|
|
|
|
('subgroup.line', []),
|
2022-10-29 20:10:23 +00:00
|
|
|
('subgroup.password', []),
|
|
|
|
|
('subgroup.misc', []),
|
|
|
|
|
('subgroup.wallet', []),
|
|
|
|
|
('subgroup.mnemonic', []),
|
|
|
|
|
('subgroup.dieroll', []),
|
2020-03-12 16:59:55 +00:00
|
|
|
)
|
2022-10-29 20:10:23 +00:00
|
|
|
cmd_subgroups = {
|
2022-10-29 20:10:24 +00:00
|
|
|
'char': (
|
|
|
|
|
'get_char() function',
|
|
|
|
|
('get_char1', 'get_char()'),
|
|
|
|
|
('get_char2', 'get_char() [multiple characters]'),
|
|
|
|
|
('get_char3', 'get_char() [no prompt]'),
|
|
|
|
|
('get_char4', 'get_char() [utf8]'),
|
|
|
|
|
('get_char_term1', 'get_char() [term, utf8]'),
|
|
|
|
|
('get_char_term2', 'get_char() [term, multiple characters]'),
|
|
|
|
|
('get_char_term3', 'get_char() [term, prehold_protect=False]'),
|
|
|
|
|
('get_char_term4', 'get_char() [term, immed_chars="xyz"]'),
|
|
|
|
|
),
|
|
|
|
|
'line': (
|
|
|
|
|
'line_input() function',
|
|
|
|
|
('line_input', 'line_input()'),
|
|
|
|
|
('line_input_term1', 'line_input() [term]'),
|
|
|
|
|
('line_input_term2', 'line_input() [term, no hold protect]'),
|
|
|
|
|
('line_input_insert', 'line_input() [inserted text]'),
|
|
|
|
|
('line_input_insert_term1', 'line_input() [inserted text, term]'),
|
|
|
|
|
('line_input_insert_term2', 'line_input() [inserted text, term, no hold protect]'),
|
|
|
|
|
('line_input_edit_term', 'line_input() [inserted + edited text, term, utf8]'),
|
|
|
|
|
('line_input_erase_term', 'line_input() [inserted + erased text, term]'),
|
|
|
|
|
),
|
2022-10-29 20:10:23 +00:00
|
|
|
'password': (
|
|
|
|
|
'password entry via line_input()',
|
|
|
|
|
('password_entry_noecho', 'utf8 password entry'),
|
2022-10-29 20:10:24 +00:00
|
|
|
('password_entry_noecho_term', 'utf8 password entry [term]'),
|
2022-10-29 20:10:23 +00:00
|
|
|
('password_entry_echo', 'utf8 password entry (echoed)'),
|
2022-10-29 20:10:24 +00:00
|
|
|
('password_entry_echo_term', 'utf8 password entry (echoed) [term]'),
|
2022-10-29 20:10:23 +00:00
|
|
|
),
|
|
|
|
|
'misc': (
|
|
|
|
|
'miscellaneous user-level UI functions',
|
|
|
|
|
('get_seed_from_stdin', 'reading seed phrase from STDIN'),
|
|
|
|
|
),
|
|
|
|
|
'wallet': (
|
|
|
|
|
'hash preset, password and label entry',
|
|
|
|
|
('get_passphrase_ui', 'hash preset, password and label (wallet.py)'),
|
|
|
|
|
('get_passphrase_cmdline', 'hash preset, password and label (wallet.py - from cmdline)'),
|
|
|
|
|
('get_passphrase_crypto', 'hash preset, password and label (crypto.py)'),
|
|
|
|
|
),
|
|
|
|
|
'mnemonic': (
|
|
|
|
|
'mnemonic entry',
|
|
|
|
|
('mnemonic_entry_mmgen', 'stealth mnemonic entry (mmgen)'),
|
|
|
|
|
('mnemonic_entry_mmgen_minimal', 'stealth mnemonic entry (mmgen - minimal entry mode)'),
|
|
|
|
|
('mnemonic_entry_bip39', 'stealth mnemonic entry (bip39)'),
|
|
|
|
|
('mnemonic_entry_bip39_short', 'stealth mnemonic entry (bip39 - short entry mode)'),
|
|
|
|
|
('mn2hex_interactive_mmgen', 'mn2hex_interactive (mmgen)'),
|
|
|
|
|
('mn2hex_interactive_mmgen_fixed','mn2hex_interactive (mmgen - fixed (10-letter) entry mode)'),
|
|
|
|
|
('mn2hex_interactive_bip39', 'mn2hex_interactive (bip39)'),
|
|
|
|
|
('mn2hex_interactive_bip39_short','mn2hex_interactive (bip39 - short entry mode (+pad entry))'),
|
|
|
|
|
('mn2hex_interactive_bip39_fixed','mn2hex_interactive (bip39 - fixed (4-letter) entry mode)'),
|
|
|
|
|
('mn2hex_interactive_xmr', 'mn2hex_interactive (xmrseed)'),
|
|
|
|
|
('mn2hex_interactive_xmr_short', 'mn2hex_interactive (xmrseed - short entry mode)'),
|
|
|
|
|
),
|
|
|
|
|
'dieroll': (
|
|
|
|
|
'dieroll entry',
|
|
|
|
|
('dieroll_entry', 'dieroll entry (base6d)'),
|
|
|
|
|
('dieroll_entry_usrrand', 'dieroll entry (base6d) with added user entropy'),
|
|
|
|
|
)
|
|
|
|
|
}
|
2020-03-12 16:59:55 +00:00
|
|
|
|
2022-02-03 20:40:41 +00:00
|
|
|
def get_seed_from_stdin(self):
|
|
|
|
|
self.spawn('',msg_only=True)
|
|
|
|
|
from subprocess import run,PIPE
|
2022-05-03 21:01:05 +00:00
|
|
|
cmd = ['python3','cmds/mmgen-walletconv','--in-fmt=words','--out-fmt=bip39','--outdir=test/trash']
|
2022-02-03 20:40:41 +00:00
|
|
|
mn = sample_mn['mmgen']['mn']
|
|
|
|
|
os.environ['MMGEN_TEST_SUITE'] = ''
|
|
|
|
|
cp = run( cmd, input=mn.encode(), stdout=PIPE, stderr=PIPE )
|
2022-05-03 21:01:05 +00:00
|
|
|
from mmgen.color import set_vt100
|
|
|
|
|
set_vt100()
|
2022-02-03 20:40:41 +00:00
|
|
|
os.environ['MMGEN_TEST_SUITE'] = '1'
|
|
|
|
|
assert b'written to file' in cp.stderr, "test 'get_seed_from_stdin' failed"
|
|
|
|
|
imsg(cp.stderr.decode().strip())
|
|
|
|
|
return 'ok'
|
|
|
|
|
|
2020-05-30 17:49:22 +00:00
|
|
|
def get_passphrase_ui(self):
|
|
|
|
|
t = self.spawn('test/misc/get_passphrase.py',['--usr-randchars=0','seed'],cmd_dir='.')
|
|
|
|
|
|
|
|
|
|
# 1 - new wallet, default hp,label;empty pw
|
|
|
|
|
t.expect('accept the default.*: ','\n',regex=True)
|
|
|
|
|
|
|
|
|
|
# bad repeat
|
|
|
|
|
t.expect('new MMGen wallet: ','pass1\n')
|
|
|
|
|
t.expect('peat passphrase: ','pass2\n')
|
|
|
|
|
|
|
|
|
|
# good repeat
|
|
|
|
|
t.expect('new MMGen wallet: ','\n')
|
|
|
|
|
t.expect('peat passphrase: ','\n')
|
|
|
|
|
t.expect('mpty pass')
|
|
|
|
|
|
|
|
|
|
t.expect('no label: ','\n')
|
|
|
|
|
|
|
|
|
|
t.expect('[][3][No Label]')
|
|
|
|
|
|
|
|
|
|
# 2 - new wallet, user-selected hp,pw,label
|
|
|
|
|
t.expect('accept the default.*: ', '1\n', regex=True)
|
|
|
|
|
|
|
|
|
|
t.expect('new MMGen wallet: ','pass1\n')
|
|
|
|
|
t.expect('peat passphrase: ','pass1\n')
|
|
|
|
|
|
|
|
|
|
t.expect('no label: ','lbl1\n')
|
|
|
|
|
|
|
|
|
|
t.expect('[pass1][1][lbl1]')
|
|
|
|
|
|
|
|
|
|
# 3 - passchg, nothing changes
|
|
|
|
|
t.expect('new hash preset')
|
|
|
|
|
t.expect('reuse the old value.*: ','\n',regex=True)
|
|
|
|
|
t.expect('unchanged')
|
|
|
|
|
|
|
|
|
|
t.expect('new passphrase.*: ','pass1\n',regex=True)
|
2022-01-22 14:26:14 +00:00
|
|
|
t.expect('peat new passphrase: ','pass1\n')
|
2020-05-30 17:49:22 +00:00
|
|
|
t.expect('unchanged')
|
|
|
|
|
|
|
|
|
|
t.expect('reuse the label .*: ','\n',regex=True)
|
|
|
|
|
t.expect('unchanged')
|
|
|
|
|
|
|
|
|
|
t.expect('[pass1][1][lbl1]')
|
|
|
|
|
|
|
|
|
|
# 4 - passchg, everything changes
|
|
|
|
|
t.expect('new hash preset')
|
|
|
|
|
t.expect('reuse the old value.*: ','2\n',regex=True)
|
|
|
|
|
t.expect(' changed to')
|
|
|
|
|
|
|
|
|
|
t.expect('new passphrase.*: ','pass2\n',regex=True)
|
2022-01-22 14:26:14 +00:00
|
|
|
t.expect('peat new passphrase: ','pass2\n')
|
2020-05-30 17:49:22 +00:00
|
|
|
t.expect(' changed')
|
|
|
|
|
|
|
|
|
|
t.expect('reuse the label .*: ','lbl2\n',regex=True)
|
|
|
|
|
t.expect(' changed to')
|
|
|
|
|
t.expect('[pass2][2][lbl2]')
|
|
|
|
|
|
|
|
|
|
# 5 - wallet from file
|
|
|
|
|
t.expect('from file')
|
|
|
|
|
|
|
|
|
|
# bad passphrase
|
|
|
|
|
t.expect('passphrase for MMGen wallet: ','bad\n')
|
|
|
|
|
t.expect('Trying again')
|
|
|
|
|
|
|
|
|
|
# good passphrase
|
|
|
|
|
t.expect('passphrase for MMGen wallet: ','reference password\n')
|
|
|
|
|
t.expect('[reference password][1][No Label]')
|
|
|
|
|
|
|
|
|
|
return t
|
|
|
|
|
|
|
|
|
|
def get_passphrase_cmdline(self):
|
2022-01-06 20:24:21 +00:00
|
|
|
with open('test/trash/pwfile','w') as fp:
|
|
|
|
|
fp.write('reference password\n')
|
2020-05-30 17:49:22 +00:00
|
|
|
t = self.spawn('test/misc/get_passphrase.py', [
|
|
|
|
|
'--usr-randchars=0',
|
|
|
|
|
'--label=MyLabel',
|
|
|
|
|
'--passwd-file=test/trash/pwfile',
|
|
|
|
|
'--hash-preset=1',
|
|
|
|
|
'seed' ],
|
|
|
|
|
cmd_dir = '.' )
|
|
|
|
|
for foo in range(4):
|
|
|
|
|
t.expect('[reference password][1][MyLabel]')
|
2022-02-05 13:32:55 +00:00
|
|
|
|
2020-05-30 17:49:22 +00:00
|
|
|
return t
|
|
|
|
|
|
|
|
|
|
def get_passphrase_crypto(self):
|
|
|
|
|
t = self.spawn('test/misc/get_passphrase.py',['--usr-randchars=0','crypto'],cmd_dir='.')
|
|
|
|
|
|
|
|
|
|
# new passwd
|
|
|
|
|
t.expect('passphrase for .*: ', 'x\n', regex=True)
|
|
|
|
|
t.expect('peat passphrase: ', '\n')
|
|
|
|
|
t.expect('passphrase for .*: ', 'pass1\n', regex=True)
|
|
|
|
|
t.expect('peat passphrase: ', 'pass1\n')
|
|
|
|
|
t.expect('[pass1]')
|
|
|
|
|
|
|
|
|
|
# existing passwd
|
|
|
|
|
t.expect('passphrase for .*: ', 'pass2\n', regex=True)
|
|
|
|
|
t.expect('[pass2]')
|
|
|
|
|
|
|
|
|
|
# hash preset
|
|
|
|
|
t.expect('accept the default .*: ', '0\n', regex=True)
|
|
|
|
|
t.expect('nvalid')
|
|
|
|
|
t.expect('accept the default .*: ', '8\n', regex=True)
|
|
|
|
|
t.expect('nvalid')
|
|
|
|
|
t.expect('accept the default .*: ', '7\n', regex=True)
|
|
|
|
|
t.expect('[7]')
|
|
|
|
|
|
|
|
|
|
# hash preset (default)
|
|
|
|
|
t.expect('accept the default .*: ', '\n', regex=True)
|
|
|
|
|
t.expect(f'[{g.dfl_hash_preset}]')
|
|
|
|
|
|
|
|
|
|
return t
|
|
|
|
|
|
2022-10-29 20:10:24 +00:00
|
|
|
def _input_func(self,func_name,arg_dfls,func_args,text,expect,term):
|
|
|
|
|
func_args = {k:v for k,v in zip(arg_dfls.keys(),func_args)}
|
|
|
|
|
t = self.spawn(
|
|
|
|
|
'test/misc/input_func.py',
|
|
|
|
|
[func_name,repr(func_args)],
|
|
|
|
|
cmd_dir='.',
|
|
|
|
|
pexpect_spawn=term )
|
|
|
|
|
imsg('Parameters:')
|
|
|
|
|
imsg(' terminal: {}'.format(term))
|
|
|
|
|
imsg(' sending: {!r}'.format(text))
|
|
|
|
|
imsg(' expecting: {!r}'.format(expect))
|
|
|
|
|
imsg('\nFunction args:')
|
|
|
|
|
for k,v in func_args.items():
|
|
|
|
|
imsg(' {:14} {!r}'.format(k+':',v))
|
|
|
|
|
imsg_r('\nScript output: ')
|
|
|
|
|
prompt_add = (func_args['insert_txt'] if term else '') if func_name == 'line_input' else ''
|
|
|
|
|
t.expect( func_args['prompt'] + prompt_add, text )
|
|
|
|
|
ret = t.expect_getend(' ==> ')
|
|
|
|
|
assert ret == repr(expect), f'Text mismatch! {ret} != {repr(expect)}'
|
|
|
|
|
return t
|
|
|
|
|
|
|
|
|
|
def _get_char(self,func_args,text,expect,term):
|
|
|
|
|
arg_dfls = {
|
|
|
|
|
'prompt': '',
|
|
|
|
|
'immed_chars': '',
|
|
|
|
|
'prehold_protect': True,
|
|
|
|
|
'num_bytes': 5,
|
|
|
|
|
}
|
|
|
|
|
return self._input_func('get_char',arg_dfls,func_args,text,expect,term)
|
|
|
|
|
|
|
|
|
|
def _line_input(self,func_args,text,expect,term):
|
|
|
|
|
arg_dfls = {
|
|
|
|
|
'prompt': '', # positional
|
|
|
|
|
'echo': True,
|
|
|
|
|
'insert_txt': '',
|
|
|
|
|
'hold_protect': True,
|
|
|
|
|
}
|
|
|
|
|
return self._input_func('line_input',arg_dfls,func_args,text+'\n',expect,term)
|
|
|
|
|
|
|
|
|
|
def get_char1(self):
|
|
|
|
|
return self._get_char(['prompt> ','',True,5],'x','x',False)
|
|
|
|
|
|
|
|
|
|
def get_char2(self):
|
|
|
|
|
return self._get_char(['prompt> ','',True,5],'xxxxx','xxxxx',False)
|
|
|
|
|
|
|
|
|
|
def get_char3(self):
|
|
|
|
|
return self._get_char(['','',True,5],'x','x',False)
|
|
|
|
|
|
|
|
|
|
def get_char4(self):
|
|
|
|
|
return self._get_char(['prompt> ','',True,2],'α','α',False) # UTF-8, must get 2 bytes
|
|
|
|
|
|
|
|
|
|
def get_char_term1(self):
|
|
|
|
|
return self._get_char(['prompt> ','',True,2],'β','β',True) # UTF-8, must get 2 bytes
|
|
|
|
|
|
|
|
|
|
def get_char_term2(self):
|
|
|
|
|
return self._get_char(['prompt> ','',True,5],'xxxxx','xxxxx',True)
|
|
|
|
|
|
|
|
|
|
def get_char_term3(self):
|
|
|
|
|
return self._get_char(['','',False,5],'x','x',True)
|
|
|
|
|
|
|
|
|
|
def get_char_term4(self):
|
|
|
|
|
return self._get_char(['prompt> ','xyz',False,5],'x','x',True)
|
|
|
|
|
|
|
|
|
|
def line_input(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'',True],'foo','foo',False)
|
|
|
|
|
|
|
|
|
|
def line_input_term1(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'',True],'foo','foo',True)
|
|
|
|
|
|
|
|
|
|
def line_input_term2(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'',False],'foo','foo',True)
|
|
|
|
|
|
|
|
|
|
def line_input_insert(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'inserted text',True],'foo','foo',False)
|
|
|
|
|
|
|
|
|
|
def line_input_insert_term1(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'foo',True],'bar','foobar',True)
|
|
|
|
|
|
|
|
|
|
def line_input_insert_term2(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'foo',False],'bar','foobar',True)
|
|
|
|
|
|
|
|
|
|
def line_input_edit_term(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'φυφυ',True],'\b\bβαρ','φυβαρ',True)
|
|
|
|
|
|
|
|
|
|
def line_input_erase_term(self):
|
|
|
|
|
return self._line_input(['prompt> ',True,'foobarbaz',True],Ctrl_U+'foobar','foobar',True)
|
|
|
|
|
|
2022-10-29 20:10:23 +00:00
|
|
|
def _password_entry(self,prompt,opts=[],term=False):
|
2022-10-29 20:10:24 +00:00
|
|
|
t = self.spawn( 'test/misc/input_func.py', opts + ['passphrase'], cmd_dir='.', pexpect_spawn=term )
|
2022-10-29 20:10:23 +00:00
|
|
|
imsg('Terminal: {}'.format(term))
|
2020-03-12 16:59:55 +00:00
|
|
|
pw = 'abc-α'
|
2021-10-07 13:12:10 +00:00
|
|
|
t.expect(prompt,pw+'\n')
|
2020-03-12 16:59:55 +00:00
|
|
|
ret = t.expect_getend('Entered: ')
|
2021-09-29 21:17:57 +00:00
|
|
|
assert ret == pw, f'Password mismatch! {ret} != {pw}'
|
2020-03-12 16:59:55 +00:00
|
|
|
return t
|
|
|
|
|
|
2022-10-29 20:10:23 +00:00
|
|
|
# TODO: has this been fixed?
|
|
|
|
|
winskip_msg = """
|
|
|
|
|
getpass() doesn't work with pexpect.popen_spawn on MSYS2!
|
|
|
|
|
Perform the following test by hand with non-ASCII password abc-α
|
|
|
|
|
or another password in your native alphabet:
|
|
|
|
|
|
|
|
|
|
test/misc/input_func.py{} passphrase
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def password_entry_noecho(self,term=False):
|
|
|
|
|
return self._password_entry('Enter passphrase: ',term=term)
|
|
|
|
|
|
2022-10-29 20:10:24 +00:00
|
|
|
def password_entry_noecho_term(self):
|
|
|
|
|
if self.skip_for_win():
|
|
|
|
|
return ('skip_warn','\n' + fmt(self.winskip_msg.format(''),strip_char='\t'))
|
|
|
|
|
return self.password_entry_noecho(term=True)
|
|
|
|
|
|
2022-10-29 20:10:23 +00:00
|
|
|
def password_entry_echo(self,term=False):
|
|
|
|
|
return self._password_entry('Enter passphrase (echoed): ',['--echo-passphrase'],term=term)
|
2020-03-12 16:59:55 +00:00
|
|
|
|
2022-10-29 20:10:24 +00:00
|
|
|
def password_entry_echo_term(self):
|
|
|
|
|
if self.skip_for_win():
|
|
|
|
|
return ('skip_warn','\n' + fmt(self.winskip_msg.format(' --echo-passphrase'),strip_char='\t'))
|
|
|
|
|
return self.password_entry_echo(term=True)
|
|
|
|
|
|
2020-06-03 14:09:21 +00:00
|
|
|
def _mn2hex(self,fmt,entry_mode='full',mn=None,pad_entry=False,enter_for_dfl=False):
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
mn = mn or sample_mn[fmt]['mn'].split()
|
|
|
|
|
t = self.spawn('mmgen-tool',['mn2hex_interactive','fmt='+fmt,'mn_len=12','print_mn=1'])
|
|
|
|
|
from mmgen.mn_entry import mn_entry
|
|
|
|
|
mne = mn_entry(fmt,entry_mode)
|
2020-06-03 14:09:21 +00:00
|
|
|
t.expect(
|
|
|
|
|
'Type a number.*: ',
|
|
|
|
|
('\n' if enter_for_dfl else str(mne.entry_modes.index(entry_mode)+1)),
|
|
|
|
|
regex = True )
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
t.expect('Using (.+) entry mode',regex=True)
|
2020-06-03 12:29:50 +00:00
|
|
|
mode = strip_ansi_escapes(t.p.match.group(1)).lower()
|
2021-09-29 21:17:57 +00:00
|
|
|
assert mode == mne.em.name.lower(), f'{mode} != {mne.em.name.lower()}'
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
stealth_mnemonic_entry(t,mne,mn,entry_mode=entry_mode,pad_entry=pad_entry)
|
|
|
|
|
t.expect(sample_mn[fmt]['hex'])
|
|
|
|
|
return t
|
|
|
|
|
|
|
|
|
|
def _user_seed_entry(self,fmt,usr_rand=False,out_fmt=None,entry_mode='full',mn=None):
|
2022-02-08 13:03:32 +00:00
|
|
|
wcls = get_wallet_cls(fmt_code=fmt)
|
2021-09-29 21:17:57 +00:00
|
|
|
wf = os.path.join(ref_dir,f'FE3C6545.{wcls.ext}')
|
2022-02-08 13:03:32 +00:00
|
|
|
if wcls.base_type == 'mnemonic':
|
2020-03-12 16:59:55 +00:00
|
|
|
mn = mn or read_from_file(wf).strip().split()
|
2022-02-08 13:03:32 +00:00
|
|
|
elif wcls.type == 'dieroll':
|
2021-09-05 18:40:43 +00:00
|
|
|
mn = mn or list(remove_whitespace(read_from_file(wf)))
|
2020-03-12 16:59:55 +00:00
|
|
|
for idx,val in ((5,'x'),(18,'0'),(30,'7'),(44,'9')):
|
|
|
|
|
mn.insert(idx,val)
|
|
|
|
|
t = self.spawn('mmgen-walletconv',['-r10','-S','-i',fmt,'-o',out_fmt or fmt])
|
2022-02-08 13:03:32 +00:00
|
|
|
t.expect(f'{capfirst(wcls.base_type or wcls.type)} type:.*{wcls.mn_type}',regex=True)
|
2020-03-12 16:59:55 +00:00
|
|
|
t.expect(wcls.choose_seedlen_prompt,'1')
|
|
|
|
|
t.expect('(Y/n): ','y')
|
2022-02-08 13:03:32 +00:00
|
|
|
if wcls.base_type == 'mnemonic':
|
2020-06-03 14:09:21 +00:00
|
|
|
t.expect('Type a number.*: ','6',regex=True)
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
t.expect('invalid')
|
|
|
|
|
from mmgen.mn_entry import mn_entry
|
|
|
|
|
mne = mn_entry(fmt,entry_mode)
|
2020-06-03 14:09:21 +00:00
|
|
|
t.expect('Type a number.*: ',str(mne.entry_modes.index(entry_mode)+1),regex=True)
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
t.expect('Using (.+) entry mode',regex=True)
|
2020-06-03 12:29:50 +00:00
|
|
|
mode = strip_ansi_escapes(t.p.match.group(1)).lower()
|
2021-09-29 21:17:57 +00:00
|
|
|
assert mode == mne.em.name.lower(), f'{mode} != {mne.em.name.lower()}'
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
stealth_mnemonic_entry(t,mne,mn,entry_mode=entry_mode)
|
2022-02-08 13:03:32 +00:00
|
|
|
elif wcls.type == 'dieroll':
|
2020-03-12 16:59:55 +00:00
|
|
|
user_dieroll_entry(t,mn)
|
|
|
|
|
if usr_rand:
|
|
|
|
|
t.expect(wcls.user_entropy_prompt,'y')
|
|
|
|
|
t.usr_rand(10)
|
|
|
|
|
else:
|
|
|
|
|
t.expect(wcls.user_entropy_prompt,'n')
|
|
|
|
|
if not usr_rand:
|
|
|
|
|
sid_chk = 'FE3C6545'
|
2021-09-29 21:17:57 +00:00
|
|
|
sid = t.expect_getend(f'Valid {wcls.desc} for Seed ID ')
|
2020-06-03 12:29:50 +00:00
|
|
|
sid = strip_ansi_escapes(sid.split(',')[0])
|
2021-09-29 21:17:57 +00:00
|
|
|
assert sid == sid_chk, f'Seed ID mismatch! {sid} != {sid_chk}'
|
2020-03-12 16:59:55 +00:00
|
|
|
t.expect('to confirm: ','YES\n')
|
|
|
|
|
return t
|
|
|
|
|
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
def mnemonic_entry_mmgen_minimal(self):
|
|
|
|
|
from mmgen.mn_entry import mn_entry
|
|
|
|
|
# erase_chars: '\b\x7f'
|
|
|
|
|
m = mn_entry('mmgen','minimal')
|
|
|
|
|
np = 2
|
|
|
|
|
mn = (
|
|
|
|
|
'z',
|
|
|
|
|
'aa',
|
|
|
|
|
'1d2ud',
|
|
|
|
|
'fo{}ot{}#'.format('1' * np, '2' * (m.em.pad_max - np)), # substring of 'football'
|
|
|
|
|
'des1p)%erate\n', # substring of 'desperately'
|
|
|
|
|
'#t!(ie',
|
|
|
|
|
'!)sto8o',
|
|
|
|
|
'the123m8!%s',
|
|
|
|
|
'349t(5)rip',
|
|
|
|
|
'di\b\bdesce',
|
|
|
|
|
'cea',
|
|
|
|
|
'bu\x7f\x7fsuic',
|
|
|
|
|
'app\bpl',
|
|
|
|
|
'wd',
|
|
|
|
|
'busy')
|
|
|
|
|
return self._user_seed_entry('words',entry_mode='minimal',mn=mn)
|
2020-03-12 16:59:55 +00:00
|
|
|
def mnemonic_entry_mmgen(self): return self._user_seed_entry('words',entry_mode='full')
|
|
|
|
|
def mnemonic_entry_bip39(self): return self._user_seed_entry('bip39',entry_mode='full')
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
def mnemonic_entry_bip39_short(self): return self._user_seed_entry('bip39',entry_mode='short')
|
|
|
|
|
|
|
|
|
|
def mn2hex_interactive_mmgen(self): return self._mn2hex('mmgen',entry_mode='full')
|
|
|
|
|
def mn2hex_interactive_mmgen_fixed(self): return self._mn2hex('mmgen',entry_mode='fixed')
|
|
|
|
|
def mn2hex_interactive_bip39(self): return self._mn2hex('bip39',entry_mode='full')
|
|
|
|
|
def mn2hex_interactive_bip39_short(self): return self._mn2hex('bip39',entry_mode='short',pad_entry=True)
|
2020-06-03 14:09:21 +00:00
|
|
|
def mn2hex_interactive_bip39_fixed(self): return self._mn2hex('bip39',entry_mode='fixed',enter_for_dfl=True)
|
new mnemonic entry modes, new 'mn2hex_interactive' tool command
Auto-completion functionality for seed phrase entry provides real benefit to the
user, reducing the number of keystrokes required and permitting quick re-entry
of mistyped words. In addition, unifying the number of keystrokes among words
improves security against acoustic side-channel attacks. To this end, three
new interactive mnemonic entry modes are introduced by this patch.
Each entry mode is optimized for a particular wordlist. The “short” mode, for
example, takes advantage of the fact that each word in the Monero wordlist is
uniquely identifiable by its first three letters. For MMGen’s default Electrum
wordlist, which lacks this unique substring property, the “minimal” mode was
developed to reduce keystrokes to a minimum while retaining the option of
obfuscating entry with pad characters.
Users who prefer not to use auto-completion may specify the “full” mode, which
emulates the previous default behavior.
Overview of the key entry modes:
- 'full' (all wordlists): words are typed in full and entered with the ENTER
or SPACE key, or by exceeding the pad character limit (see below).
- 'short' (BIP39, Monero): words are entered automatically once user types
UNIQ_SS_LEN (see below) valid word letters. 3-letter words in the BIP39
wordlist must be entered with the ENTER or SPACE key, or by exceeding the
pad character limit.
- 'fixed' (BIP39, Electrum): words are entered automatically once user types
UNIQ_SS_LEN characters in total. Words shorter than UNIQ_SS_LEN must be
padded to fit. Thus the total number of characters entered is the same for
all words.
- 'minimal' (Electrum): words are entered automatically once user types the
minimum number of characters required to uniquely identify a word (varies
from word to word). Words that are substrings of other words in the wordlist
must be entered with the ENTER or SPACE key, or by exceeding the pad
character limit. This is the only mode that checks user input letter by
letter.
Pad character limits by mode:
-----------------------------
short: 16
minimal: 16
full: longest_word - word_len
fixed: uniq_ss_len - word_len
Wordlist parameters:
--------------------
Parameter Electrum BIP39 XMRSEED
--------- -------- ----- -------
uniq_ss_len: 10 4 3
shortest_word: 3 3 4
longest word: 12 8 12
optimum mode: minimal fixed short
Default modes for each wordlist may be configured in 'mmgen.cfg' via the
'mnemonic_entry_modes' option.
Usage / testing:
$ mmgen-walletconv -i words
$ mmgen-walletconv -i bip39
$ mmgen-tool mn2hex_interactive fmt=mmgen mn_len=12 print_mn=1
$ mmgen-tool mn2hex_interactive fmt=bip39
$ mmgen-tool mn2hex_interactive fmt=xmrseed
$ test/unit_tests.py mn_entry
$ test/test.py -e input
2020-03-12 17:12:43 +00:00
|
|
|
def mn2hex_interactive_xmr(self): return self._mn2hex('xmrseed',entry_mode='full')
|
|
|
|
|
def mn2hex_interactive_xmr_short(self): return self._mn2hex('xmrseed',entry_mode='short')
|
2020-03-12 16:59:55 +00:00
|
|
|
|
|
|
|
|
def dieroll_entry(self): return self._user_seed_entry('dieroll')
|
|
|
|
|
def dieroll_entry_usrrand(self): return self._user_seed_entry('dieroll',usr_rand=True,out_fmt='bip39')
|