Browse Source

crypto.py:get_*passphrase(),get_hash_preset*(): merge with duplicating code in wallet.py

The MMGen Project 3 years ago
parent
commit
ccb4894583
5 changed files with 79 additions and 97 deletions
  1. 57 34
      mmgen/crypto.py
  2. 15 56
      mmgen/wallet.py
  3. 4 4
      test/misc/get_passphrase.py
  4. 2 2
      test/test_py_d/ts_input.py
  5. 1 1
      test/test_py_d/ts_main.py

+ 57 - 34
mmgen/crypto.py

@@ -215,78 +215,101 @@ def add_user_random(rand_bytes,desc):
 	else:
 	else:
 		return rand_bytes
 		return rand_bytes
 
 
-def get_hash_preset_from_user(hp=g.dfl_hash_preset,desc='data'):
+def get_hash_preset_from_user(
+		hash_preset = g.dfl_hash_preset,
+		data_desc = 'data',
+		prompt = None ):
+
+	prompt = prompt or (
+		f'Enter hash preset for {data_desc},\n' +
+		f'or hit ENTER to accept the default value ({hash_preset!r}): ' )
+
 	while True:
 	while True:
-		ret = line_input(
-			f'Enter hash preset for {desc},\n' +
-			f'or hit ENTER to accept the default value ({hp!r}): ' )
+		ret = line_input(prompt)
 		if ret:
 		if ret:
 			if ret in g.hash_presets:
 			if ret in g.hash_presets:
 				return ret
 				return ret
 			else:
 			else:
-				msg(f'Invalid input.  Valid choices are {", ".join(g.hash_presets)}')
-				continue
+				msg('Invalid input.  Valid choices are {}'.format(', '.join(g.hash_presets)))
 		else:
 		else:
-			return hp
-
-def get_new_passphrase(desc,passchg=False):
-	pw_desc = f"{'new ' if passchg else ''}passphrase for {desc}"
-	if opt.passwd_file:
+			return hash_preset
+
+def get_new_passphrase(data_desc,hash_preset,passwd_file,pw_desc='passphrase'):
+	message = f"""
+			You must choose a passphrase to encrypt your {data_desc} with.
+			A key will be generated from your passphrase using a hash preset of '{hash_preset}'.
+			Please note that no strength checking of passphrases is performed.
+			For an empty passphrase, just hit ENTER twice.
+		"""
+	if passwd_file:
 		from .fileutil import get_words_from_file
 		from .fileutil import get_words_from_file
-		pw = ' '.join(get_words_from_file(opt.passwd_file,pw_desc))
-	elif opt.echo_passphrase:
-		pw = ' '.join(get_words_from_user(f'Enter {pw_desc}: '))
+		pw = ' '.join(get_words_from_file(
+			infile = passwd_file,
+			desc = f'{pw_desc} for {data_desc}',
+			quiet = pwfile_reuse_warning(passwd_file).warning_shown ))
 	else:
 	else:
-		for i in range(g.passwd_max_tries):
-			pw = ' '.join(get_words_from_user(f'Enter {pw_desc}: '))
-			pw_chk = ' '.join(get_words_from_user('Repeat passphrase: '))
-			dmsg(f'Passphrases: [{pw}] [{pw_chk}]')
-			if pw == pw_chk:
-				vmsg('Passphrases match'); break
-			else: msg('Passphrases do not match.  Try again.')
+		qmsg('\n'+fmt(message,indent='  '))
+		if opt.echo_passphrase:
+			pw = ' '.join(get_words_from_user(f'Enter {pw_desc} for {data_desc}: '))
 		else:
 		else:
-			die(2,f'User failed to duplicate passphrase in {g.passwd_max_tries} attempts')
+			for i in range(g.passwd_max_tries):
+				pw = ' '.join(get_words_from_user(f'Enter {pw_desc} for {data_desc}: '))
+				pw_chk = ' '.join(get_words_from_user(f'Repeat {pw_desc}: '))
+				dmsg(f'Passphrases: [{pw}] [{pw_chk}]')
+				if pw == pw_chk:
+					vmsg('Passphrases match')
+					break
+				else:
+					msg('Passphrases do not match.  Try again.')
+			else:
+				die(2,f'User failed to duplicate passphrase in {g.passwd_max_tries} attempts')
 
 
 	if pw == '':
 	if pw == '':
 		qmsg('WARNING: Empty passphrase')
 		qmsg('WARNING: Empty passphrase')
 
 
 	return pw
 	return pw
 
 
-def get_passphrase(desc,passchg=False):
-	pw_desc = f"{'old ' if passchg else ''}passphrase for {desc}"
-	if opt.passwd_file:
+def get_passphrase(data_desc,passwd_file,pw_desc='passphrase'):
+	if passwd_file:
 		from .fileutil import get_words_from_file
 		from .fileutil import get_words_from_file
-		pwfile_reuse_warning(opt.passwd_file)
-		return ' '.join(get_words_from_file(opt.passwd_file,pw_desc))
+		return ' '.join(get_words_from_file(
+			infile = passwd_file,
+			desc = f'{pw_desc} for {data_desc}',
+			quiet = pwfile_reuse_warning(passwd_file).warning_shown ))
 	else:
 	else:
-		return ' '.join(get_words_from_user(f'Enter {pw_desc}: '))
+		return ' '.join(get_words_from_user(f'Enter {pw_desc} for {data_desc}: '))
 
 
 mmenc_salt_len = 32
 mmenc_salt_len = 32
 mmenc_nonce_len = 32
 mmenc_nonce_len = 32
 
 
-def mmgen_encrypt(data,desc='data',hash_preset=''):
+def mmgen_encrypt(data,desc='data',hash_preset=None):
 	salt  = get_random(mmenc_salt_len)
 	salt  = get_random(mmenc_salt_len)
 	iv    = get_random(g.aesctr_iv_len)
 	iv    = get_random(g.aesctr_iv_len)
 	nonce = get_random(mmenc_nonce_len)
 	nonce = get_random(mmenc_nonce_len)
-	hp    = hash_preset or opt.hash_preset or get_hash_preset_from_user('3',desc)
+	hp    = hash_preset or opt.hash_preset or get_hash_preset_from_user(data_desc=desc)
 	m     = ('user-requested','default')[hp=='3']
 	m     = ('user-requested','default')[hp=='3']
 	vmsg(f'Encrypting {desc}')
 	vmsg(f'Encrypting {desc}')
 	qmsg(f'Using {m} hash preset of {hp!r}')
 	qmsg(f'Using {m} hash preset of {hp!r}')
-	passwd = get_new_passphrase(desc)
+	passwd = get_new_passphrase(
+		data_desc = desc,
+		hash_preset = hp,
+		passwd_file = opt.passwd_file )
 	key    = make_key(passwd,salt,hp)
 	key    = make_key(passwd,salt,hp)
 	enc_d  = encrypt_data( sha256(nonce+data).digest() + nonce + data, key, iv, desc=desc )
 	enc_d  = encrypt_data( sha256(nonce+data).digest() + nonce + data, key, iv, desc=desc )
 	return salt+iv+enc_d
 	return salt+iv+enc_d
 
 
-def mmgen_decrypt(data,desc='data',hash_preset=''):
+def mmgen_decrypt(data,desc='data',hash_preset=None):
 	vmsg(f'Preparing to decrypt {desc}')
 	vmsg(f'Preparing to decrypt {desc}')
 	dstart = mmenc_salt_len + g.aesctr_iv_len
 	dstart = mmenc_salt_len + g.aesctr_iv_len
 	salt   = data[:mmenc_salt_len]
 	salt   = data[:mmenc_salt_len]
 	iv     = data[mmenc_salt_len:dstart]
 	iv     = data[mmenc_salt_len:dstart]
 	enc_d  = data[dstart:]
 	enc_d  = data[dstart:]
-	hp     = hash_preset or opt.hash_preset or get_hash_preset_from_user('3',desc)
+	hp     = hash_preset or opt.hash_preset or get_hash_preset_from_user(data_desc=desc)
 	m  = ('user-requested','default')[hp=='3']
 	m  = ('user-requested','default')[hp=='3']
 	qmsg(f'Using {m} hash preset of {hp!r}')
 	qmsg(f'Using {m} hash preset of {hp!r}')
-	passwd = get_passphrase(desc)
+	passwd = get_passphrase(
+		data_desc = desc,
+		passwd_file = opt.passwd_file )
 	key    = make_key(passwd,salt,hp)
 	key    = make_key(passwd,salt,hp)
 	dec_d  = decrypt_data( enc_d, key, iv, desc )
 	dec_d  = decrypt_data( enc_d, key, iv, desc )
 	sha256_len = 32
 	sha256_len = 32

+ 15 - 56
mmgen/wallet.py

@@ -298,15 +298,8 @@ class WalletEnc(Wallet):
 			('',' '+add_desc)[bool(add_desc)],
 			('',' '+add_desc)[bool(add_desc)],
 			('accept the default','reuse the old')[self.op=='pwchg_new'],
 			('accept the default','reuse the old')[self.op=='pwchg_new'],
 			hp )
 			hp )
-		while True:
-			ret = line_input(prompt)
-			if ret:
-				if ret in g.hash_presets:
-					return ret
-				else:
-					msg('Invalid input.  Valid choices are {}'.format(', '.join(g.hash_presets)))
-			else:
-				return hp
+		from .crypto import get_hash_preset_from_user
+		return get_hash_preset_from_user( hash_preset=hp, prompt=prompt )
 
 
 	def _get_hash_preset(self,add_desc=''):
 	def _get_hash_preset(self,add_desc=''):
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
 		if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
@@ -329,54 +322,20 @@ class WalletEnc(Wallet):
 		self.ssdata.hash_preset = hp
 		self.ssdata.hash_preset = hp
 
 
 	def _get_new_passphrase(self):
 	def _get_new_passphrase(self):
-		desc = '{}passphrase for {}{}'.format(
-				('','new ')[self.op=='pwchg_new'],
-				('','new ')[self.op in ('new','conv')],
-				self.desc
-			)
-		if self.passwd_file:
-			from .fileutil import get_words_from_file
-			pw = ' '.join(get_words_from_file(
-				self.passwd_file,
-				desc,
-				quiet = pwfile_reuse_warning(self.passwd_file).warning_shown ))
-		else:
-			qmsg('\n'+fmt(self.msg['choose_passphrase'].format(self.desc,self.ssdata.hash_preset),indent='  '))
-			if opt.echo_passphrase:
-				pw = ' '.join(get_words_from_user(f'Enter {desc}: '))
-			else:
-				for i in range(g.passwd_max_tries):
-					pw = ' '.join(get_words_from_user(f'Enter {desc}: '))
-					pw_chk = ' '.join(get_words_from_user('Repeat passphrase: '))
-					dmsg(f'Passphrases: [{pw}] [{pw_chk}]')
-					if pw == pw_chk:
-						vmsg('Passphrases match')
-						break
-					else:
-						msg('Passphrases do not match.  Try again.')
-				else:
-					die(2,f'User failed to duplicate passphrase in {g.passwd_max_tries} attempts')
-
-		if pw == '':
-			qmsg('WARNING: Empty passphrase')
-		self.ssdata.passwd = pw
-		return pw
+		from .crypto import get_new_passphrase
+		self.ssdata.passwd = get_new_passphrase(
+			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' )
+		return self.ssdata.passwd
 
 
 	def _get_passphrase(self,add_desc=''):
 	def _get_passphrase(self,add_desc=''):
-		desc = '{}passphrase for {}{}'.format(
-			('','old ')[self.op=='pwchg_old'],
-			self.desc,
-			('',' '+add_desc)[bool(add_desc)]
-		)
-		if self.passwd_file:
-			from .fileutil import get_words_from_file
-			ret = ' '.join(get_words_from_file(
-				self.passwd_file,
-				desc,
-				quiet = pwfile_reuse_warning(self.passwd_file).warning_shown ))
-		else:
-			ret = ' '.join(get_words_from_user(f'Enter {desc}: '))
-		self.ssdata.passwd = ret
+		from .crypto import get_passphrase
+		self.ssdata.passwd = 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' )
 
 
 	def _get_first_pw_and_hp_and_encrypt_seed(self):
 	def _get_first_pw_and_hp_and_encrypt_seed(self):
 		d = self.ssdata
 		d = self.ssdata
@@ -826,7 +785,7 @@ class MMGenWallet(WalletEnc):
 		d.hash_preset = hp = hpdata[0][:-1]  # a string!
 		d.hash_preset = hp = hpdata[0][:-1]  # a string!
 		qmsg(f'Hash preset of wallet: {hp!r}')
 		qmsg(f'Hash preset of wallet: {hp!r}')
 		if opt.hash_preset and opt.hash_preset != hp:
 		if opt.hash_preset and opt.hash_preset != hp:
-			qmsg('Warning: ignoring user-requested hash preset {opt.hash_preset}')
+			qmsg(f'Warning: ignoring user-requested hash preset {opt.hash_preset!r}')
 
 
 		hash_params = tuple(map(int,hpdata[1:]))
 		hash_params = tuple(map(int,hpdata[1:]))
 
 

+ 4 - 4
test/misc/get_passphrase.py

@@ -27,16 +27,16 @@ from mmgen.wallet import Wallet
 def crypto():
 def crypto():
 	desc = 'test data'
 	desc = 'test data'
 
 
-	pw = get_new_passphrase(desc=desc)
+	pw = get_new_passphrase(data_desc=desc,hash_preset=g.dfl_hash_preset,passwd_file=None)
 	msg(f'==> got new passphrase: [{pw}]\n')
 	msg(f'==> got new passphrase: [{pw}]\n')
 
 
-	pw = get_passphrase(desc=desc)
+	pw = get_passphrase(data_desc=desc,passwd_file=None)
 	msg(f'==> got passphrase: [{pw}]\n')
 	msg(f'==> got passphrase: [{pw}]\n')
 
 
-	hp = get_hash_preset_from_user(desc=desc)
+	hp = get_hash_preset_from_user(data_desc=desc)
 	msg(f'==> got hash preset: [{hp}]')
 	msg(f'==> got hash preset: [{hp}]')
 
 
-	hp = get_hash_preset_from_user(desc=desc)
+	hp = get_hash_preset_from_user(data_desc=desc)
 	msg(f'==> got hash preset: [{hp}]')
 	msg(f'==> got hash preset: [{hp}]')
 
 
 def seed():
 def seed():

+ 2 - 2
test/test_py_d/ts_input.py

@@ -76,7 +76,7 @@ class TestSuiteInput(TestSuiteBase):
 		t.expect('unchanged')
 		t.expect('unchanged')
 
 
 		t.expect('new passphrase.*: ','pass1\n',regex=True)
 		t.expect('new passphrase.*: ','pass1\n',regex=True)
-		t.expect('peat passphrase: ','pass1\n')
+		t.expect('peat new passphrase: ','pass1\n')
 		t.expect('unchanged')
 		t.expect('unchanged')
 
 
 		t.expect('reuse the label .*: ','\n',regex=True)
 		t.expect('reuse the label .*: ','\n',regex=True)
@@ -90,7 +90,7 @@ class TestSuiteInput(TestSuiteBase):
 		t.expect(' changed to')
 		t.expect(' changed to')
 
 
 		t.expect('new passphrase.*: ','pass2\n',regex=True)
 		t.expect('new passphrase.*: ','pass2\n',regex=True)
-		t.expect('peat passphrase: ','pass2\n')
+		t.expect('peat new passphrase: ','pass2\n')
 		t.expect(' changed')
 		t.expect(' changed')
 
 
 		t.expect('reuse the label .*: ','lbl2\n',regex=True)
 		t.expect('reuse the label .*: ','lbl2\n',regex=True)

+ 1 - 1
test/test_py_d/ts_main.py

@@ -300,7 +300,7 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 		t.passphrase(wcls.desc,self.cfgs['1']['wpasswd'],pwtype='old')
 		t.passphrase(wcls.desc,self.cfgs['1']['wpasswd'],pwtype='old')
 		t.expect_getend('Hash preset changed to ')
 		t.expect_getend('Hash preset changed to ')
 		t.passphrase(wcls.desc,self.wpasswd,pwtype='new') # reuse passphrase?
 		t.passphrase(wcls.desc,self.wpasswd,pwtype='new') # reuse passphrase?
-		t.expect('Repeat passphrase: ',self.wpasswd+'\n')
+		t.expect('Repeat new passphrase: ',self.wpasswd+'\n')
 		t.usr_rand(self.usr_rand_chars)
 		t.usr_rand(self.usr_rand_chars)
 		if label_action == 'user':
 		if label_action == 'user':
 			t.expect('Enter a wallet label.*: ','Interactive Label (UTF-8) α\n',regex=True)
 			t.expect('Enter a wallet label.*: ','Interactive Label (UTF-8) α\n',regex=True)