add_user_random(): minor cleanups

This commit is contained in:
The MMGen Project 2020-06-01 09:09:45 +00:00
commit 1f7cfafd96
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 42 additions and 40 deletions

View file

@ -25,27 +25,6 @@ from cryptography.hazmat.backends import default_backend
from hashlib import sha256
from .common import *
crmsg = {
'usr_rand_notice': """
Now we're going to gather some additional input from the keyboard to
further randomize the {d} we've already gathered.
An encryption key will be created from this input, and the {d}
will be encrypted using the key. The resulting data is guaranteed to be at
least as random as the original {d}, so even if you type very
predictably no harm will be done.
However, to gain the maximum benefit, try making your input as random as
possible. Type slowly and choose your symbols carefully. Try to use both
upper and lowercase as well as punctuation and numerals. The timings between
your keystrokes will also be used as a source of entropy, so be as
unpredictable as possible in your timing as well.
Please type {r} symbols on your keyboard. What you type will not be displayed
on the screen.
"""
}
def sha256_rounds(s,n):
for i in range(n):
s = sha256(s).digest()
@ -152,53 +131,74 @@ def make_key(passwd,salt,hash_preset,desc='encryption key',from_what='passphrase
dmsg('Key: {}'.format(key.hex()))
return key
def _get_random_data_from_user(uchars,desc,test_suite=False):
m = 'Enter {r} random symbols' if opt.quiet or test_suite else crmsg['usr_rand_notice']
msg(m.format(r=uchars,d=desc))
def _get_random_data_from_user(uchars,desc):
info1 = f"""
Now we're going to gather some additional input from the keyboard to further
randomize the random data {desc}.
An encryption key will be created from this input, and the random data will
be encrypted using the key. The resulting data is guaranteed to be at least
as random as the original random data, so even if you type very predictably
no harm will be done.
However, to gain the maximum benefit, try making your input as random as
possible. Type slowly and choose your symbols carefully. Try to use both
upper and lowercase letters as well as punctuation and numerals. The timings
between your keystrokes will also be used as a source of entropy, so be as
random as possible in your timing as well.
"""
info2 = f"""
Please type {uchars} symbols on your keyboard. What you type will not be displayed
on the screen.
"""
msg(f'Enter {uchars} random symbols' if opt.quiet else
'\n{}\n{}'.format( fmt(info1,indent=' '), fmt(info2) ))
prompt = 'You may begin typing. {} symbols left: '
import time
from .term import get_char_raw
key_data,time_data = '',[]
key_data = ''
time_data = []
for i in range(uchars):
key_data += get_char_raw('\r'+prompt.format(uchars-i))
time_data.append(time.time())
msg_r('\r' if opt.quiet else "\rThank you. That's enough.{}\n\n".format(' '*18))
msg_r( '\r' if opt.quiet else f"\rThank you. That's enough.{' '*18}\n\n" )
time_data = ['{:.22f}'.format(t).rstrip('0') for t in time_data]
avg_prec = sum(len(t.split('.')[1]) for t in time_data) // len(time_data)
if avg_prec < g.min_time_precision:
m = 'WARNING: Avg. time precision of only {} decimal points. User entropy quality is degraded!'
ymsg(m.format(avg_prec))
ymsg(f'WARNING: Avg. time precision of only {avg_prec} decimal points. User entropy quality is degraded!')
ret = key_data + '\n' + '\n'.join(time_data)
if g.debug:
msg('USER ENTROPY (user input + keystroke timings):\n{}'.format(ret))
msg(f'USER ENTROPY (user input + keystroke timings):\n{ret}')
if not test_suite:
my_raw_input('User random data successfully acquired. Press ENTER to continue: ')
my_raw_input('User random data successfully acquired. Press ENTER to continue: ')
return ret.encode()
def get_random(length):
return add_user_random(os.urandom(length),'OS random data')
return add_user_random(
rand_bytes = os.urandom(length),
desc = 'generated by your operating system' )
def add_user_random(rand_bytes,desc):
assert type(rand_bytes) == bytes, (
"{!r}: invalid type for 'rand_bytes'".format(type(rand_bytes).__name__) )
assert type(rand_bytes) == bytes, 'add_user_random_chk1'
if opt.usr_randchars:
if not g.user_entropy:
g.user_entropy = \
sha256(_get_random_data_from_user(opt.usr_randchars,desc)).digest()
g.user_entropy = sha256(_get_random_data_from_user(opt.usr_randchars,desc)).digest()
urand_desc = 'user-supplied entropy'
else:
urand_desc = 'saved user-supplied entropy'
key = make_key(g.user_entropy,b'','2',from_what=urand_desc,verbose=True)
msg('Encrypting {} with key'.format(desc))
msg(f'Encrypting random data {desc} with key')
return encrypt_data(rand_bytes,key,desc=desc,verify=False)
else:
return rand_bytes

View file

@ -565,7 +565,9 @@ class DieRollSeedFile(WalletUnenc):
if self.interactive_input and opt.usr_randchars:
if keypress_confirm(self.user_entropy_prompt):
seed_bytes = add_user_random(seed_bytes,'die roll data')
seed_bytes = add_user_random(
rand_bytes = seed_bytes,
desc = 'gathered from your die rolls' )
self.desc += ' plus user-supplied entropy'
self.seed = Seed(seed_bytes)

View file

@ -533,7 +533,7 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
t.usr_rand(self.usr_rand_chars)
if ocls.__name__.startswith('Incog'):
m = 'Encrypting OS random data with key'
m = 'Encrypting random data generated by your operating system with key'
t.expect(m)
t.expect(m)
incog_id = t.expect_getend('New Incog Wallet ID: ')

View file

@ -208,7 +208,7 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
t.usr_rand(self.usr_rand_chars)
if wcls in (IncogWallet,IncogWalletHex,IncogWalletHidden):
for i in (1,2,3):
t.expect('Encrypting OS random data with key')
t.expect('Encrypting random data generated by your operating system with key')
if wcls == IncogWalletHidden:
t.hincog_create(hincog_bytes)
if out_fmt == 'w':