From fefea42b9cfaceebe217afdca4860cb38655df5a Mon Sep 17 00:00:00 2001 From: MMGen Date: Wed, 16 Oct 2019 16:39:43 +0000 Subject: [PATCH] passgen: passwd length sanity checks - forbid attempts to generate passwords with bit length greater than seed --- mmgen/addr.py | 27 ++++++++++++++++++++++++++- test/test_py_d/ts_ref_3seed.py | 11 ++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/mmgen/addr.py b/mmgen/addr.py index 301ceccf..e1de95ab 100755 --- a/mmgen/addr.py +++ b/mmgen/addr.py @@ -835,6 +835,7 @@ Record this checksum: it will be used to verify the password file in the future self.set_pw_len(pw_len) if chk_params_only: return + self.set_pw_len_vs_seed_len(pw_len,seed) self.al_id = AddrListID(seed.sid,MMGenPasswordType('P')) self.data = self.generate(seed,pw_idxs) @@ -882,6 +883,30 @@ Record this checksum: it will be used to verify the password file in the future self.pw_len = int(pw_len) self.chk_pw_len() + def set_pw_len_vs_seed_len(self,pw_len,seed): + pf = self.pw_fmt + if pf == 'hex': + pw_bytes = self.pw_len // 2 + good_pw_len = seed.byte_len * 2 + elif pf in ('b32','b58'): + pw_int = (32 if pf == 'b32' else 58) ** self.pw_len + pw_bytes = pw_int.bit_length() // 8 + good_pw_len = len(baseconv.fromhex('ff'*seed.byte_len,wl_id=pf)) + else: + raise NotImplementedError('{!r}: unknown password format'.format(pf)) + + if pw_bytes > seed.byte_len: + m1 = 'Cannot generate passwords with more entropy than underlying seed! ({} bits)' + m2 = 'Re-run the command with --passwd-len={}' if pf == 'hex' else \ + 'Re-run the command, specifying a password length of {} or less' + die(1,(m1+'\n'+m2).format(len(seed.data) * 8,good_pw_len)) + + if pf == 'hex' and pw_bytes < seed.byte_len: + m1 = 'WARNING: requested {} length has less entropy than underlying seed!' + m2 = 'Is this what you want?' + if not keypress_confirm((m1+'\n'+m2).format(self.pw_info[pf].desc),default_yes=True): + die(1,'Exiting at user request') + def make_passwd(self,hex_sec): assert self.pw_fmt in self.pw_info if self.pw_fmt == 'hex': @@ -894,7 +919,7 @@ Record this checksum: it will be used to verify the password file in the future def check_format(self,pw): if not self.pw_info[self.pw_fmt].chk_func(pw): raise ValueError('Password is not valid {} data'.format(self.pw_info[self.pw_fmt].desc)) - pwlen = len(pw.split()) if self.pw_fmt == 'bip39' else len(pw) + pwlen = len(pw) if pwlen != self.pw_len: raise ValueError('Password has incorrect length ({} != {})'.format(pwlen,self.pw_len)) return True diff --git a/test/test_py_d/ts_ref_3seed.py b/test/test_py_d/ts_ref_3seed.py index d22c07f4..e455fdf7 100755 --- a/test/test_py_d/ts_ref_3seed.py +++ b/test/test_py_d/ts_ref_3seed.py @@ -75,7 +75,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared): 'refpasswdgen_1': 'EB29 DC4F 924B 289F', 'refpasswdgen_half_1':'D310 2593 B5D9 2E88', 'ref_b32passwdgen_1': '37B6 C218 2ABC 7508', - 'ref_hexpasswdgen_1': '523A F547 0E69 8323', + 'ref_hexpasswdgen_1': '8E99 E696 84CE E7D5', 'ref_hexpasswdgen_half_1': '8E99 E696 84CE E7D5', 'refaddrgen_legacy_2': { 'btc': ('8C17 A5FA 0470 6E89','764C 66F9 7502 AAEA'), @@ -112,7 +112,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared): 'refpasswdgen_2': 'ADEA 0083 094D 489A', 'refpasswdgen_half_2':'12B3 4929 9506 76E0', 'ref_b32passwdgen_2': '2A28 C5C7 36EC 217A', - 'ref_hexpasswdgen_2': 'B11C AC6A 1464 608D', + 'ref_hexpasswdgen_2': '88F9 0D48 3A7E 7CC2', 'ref_hexpasswdgen_half_2': '59F3 8F48 861E 1186', 'refaddrgen_legacy_3': { 'btc': ('6FEF 6FB9 7B13 5D91','424E 4326 CFFE 5F51'), @@ -332,9 +332,10 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared): return self.addrgen(wf,pf,check_ref=True,ftype='pass32',id_str='фубар@crypto.org',extra_args=ea) def ref_hexpasswdgen(self,wf,pf): - ea = ['--passwd-fmt=hex'] + pw_len = {'1':32,'2':48,'3':64}[self.test_name[-1]] + ea = ['--passwd-fmt=hex','--passwd-len={}'.format(pw_len)] return self.addrgen(wf,pf,check_ref=True,ftype='passhex',id_str='фубар@crypto.org',extra_args=ea) def ref_hexpasswdgen_half(self,wf,pf): - ea = ['--passwd-fmt=hex','--passwd-len=h'] - return self.addrgen(wf,pf,check_ref=True,ftype='passhex',id_str='фубар@crypto.org',extra_args=ea) + ea = ['--passwd-fmt=hex','--passwd-len=h','--accept-defaults'] + return self.addrgen(wf,pf,check_ref=True,ftype='passhex',id_str='фубар@crypto.org',extra_args=ea,stdout=1)