globalvars.py: move crypto constants to crypto.py
This commit is contained in:
parent
246e500891
commit
0ef7de1886
8 changed files with 86 additions and 77 deletions
|
|
@ -44,6 +44,32 @@ from .util import (
|
|||
)
|
||||
|
||||
mmenc_ext = 'mmenc'
|
||||
scramble_hash_rounds = 10
|
||||
|
||||
salt_len = 16
|
||||
aesctr_iv_len = 16
|
||||
aesctr_dfl_iv = int.to_bytes(1,aesctr_iv_len,'big')
|
||||
hincog_chk_len = 8
|
||||
|
||||
# Scrypt params: 'id_num': [N, r, p] (N is an exponent of two)
|
||||
# NB: hashlib.scrypt in Python (>=v3.6) supports max N value of 14. This means that
|
||||
# for hash presets > 3 the standalone scrypt library must be used!
|
||||
_hp = namedtuple('scrypt_preset',['N','r','p'])
|
||||
hash_presets = {
|
||||
'1': _hp(12, 8, 1),
|
||||
'2': _hp(13, 8, 4),
|
||||
'3': _hp(14, 8, 8),
|
||||
'4': _hp(15, 8, 12),
|
||||
'5': _hp(16, 8, 16),
|
||||
'6': _hp(17, 8, 20),
|
||||
'7': _hp(18, 8, 24),
|
||||
}
|
||||
|
||||
def get_hash_params(hash_preset):
|
||||
if hash_preset in hash_presets:
|
||||
return hash_presets[hash_preset] # N,r,p
|
||||
else: # Shouldn't be here
|
||||
die(3,f"{hash_preset}: invalid 'hash_preset' value")
|
||||
|
||||
def sha256_rounds(s,n):
|
||||
for i in range(n):
|
||||
|
|
@ -55,7 +81,7 @@ def scramble_seed(seed,scramble_key):
|
|||
step1 = hmac.digest(seed,scramble_key,'sha256')
|
||||
if g.debug:
|
||||
msg(f'Seed: {seed.hex()!r}\nScramble key: {scramble_key}\nScrambled seed: {step1.hex()}\n')
|
||||
return sha256_rounds(step1,g.scramble_hash_rounds)
|
||||
return sha256_rounds( step1, scramble_hash_rounds )
|
||||
|
||||
def encrypt_seed(seed,key):
|
||||
return encrypt_data(seed,key,desc='seed')
|
||||
|
|
@ -88,7 +114,7 @@ def decrypt_seed(enc_seed,key,seed_id,key_id):
|
|||
dmsg(f'Decrypted seed: {dec_seed.hex()}')
|
||||
return dec_seed
|
||||
|
||||
def encrypt_data(data,key,iv=g.aesctr_dfl_iv,desc='data',verify=True):
|
||||
def encrypt_data(data,key,iv=aesctr_dfl_iv,desc='data',verify=True):
|
||||
vmsg(f'Encrypting {desc}')
|
||||
c = Cipher(algorithms.AES(key),modes.CTR(iv),backend=default_backend())
|
||||
encryptor = c.encryptor()
|
||||
|
|
@ -105,7 +131,7 @@ def encrypt_data(data,key,iv=g.aesctr_dfl_iv,desc='data',verify=True):
|
|||
|
||||
return enc_data
|
||||
|
||||
def decrypt_data(enc_data,key,iv=g.aesctr_dfl_iv,desc='data'):
|
||||
def decrypt_data(enc_data,key,iv=aesctr_dfl_iv,desc='data'):
|
||||
vmsg_r(f'Decrypting {desc} with key...')
|
||||
c = Cipher(algorithms.AES(key),modes.CTR(iv),backend=default_backend())
|
||||
encryptor = c.encryptor()
|
||||
|
|
@ -245,10 +271,10 @@ def get_hash_preset_from_user(
|
|||
while True:
|
||||
ret = line_input(prompt)
|
||||
if ret:
|
||||
if ret in g.hash_presets:
|
||||
if ret in hash_presets:
|
||||
return ret
|
||||
else:
|
||||
msg('Invalid input. Valid choices are {}'.format(', '.join(g.hash_presets)))
|
||||
msg('Invalid input. Valid choices are {}'.format(', '.join(hash_presets)))
|
||||
else:
|
||||
return hash_preset
|
||||
|
||||
|
|
@ -302,7 +328,7 @@ mmenc_nonce_len = 32
|
|||
|
||||
def mmgen_encrypt(data,desc='data',hash_preset=None):
|
||||
salt = get_random(mmenc_salt_len)
|
||||
iv = get_random(g.aesctr_iv_len)
|
||||
iv = get_random(aesctr_iv_len)
|
||||
nonce = get_random(mmenc_nonce_len)
|
||||
hp = hash_preset or opt.hash_preset or get_hash_preset_from_user(data_desc=desc)
|
||||
m = ('user-requested','default')[hp=='3']
|
||||
|
|
@ -318,7 +344,7 @@ def mmgen_encrypt(data,desc='data',hash_preset=None):
|
|||
|
||||
def mmgen_decrypt(data,desc='data',hash_preset=None):
|
||||
vmsg(f'Preparing to decrypt {desc}')
|
||||
dstart = mmenc_salt_len + g.aesctr_iv_len
|
||||
dstart = mmenc_salt_len + aesctr_iv_len
|
||||
salt = data[:mmenc_salt_len]
|
||||
iv = data[mmenc_salt_len:dstart]
|
||||
enc_d = data[dstart:]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
13.1.dev007
|
||||
13.1.dev008
|
||||
|
|
|
|||
|
|
@ -301,27 +301,7 @@ class GlobalContext(Lockable):
|
|||
max_urandchars = 80
|
||||
min_urandchars = 10
|
||||
|
||||
scramble_hash_rounds = 10
|
||||
|
||||
salt_len = 16
|
||||
aesctr_iv_len = 16
|
||||
aesctr_dfl_iv = int.to_bytes(1,aesctr_iv_len,'big')
|
||||
hincog_chk_len = 8
|
||||
|
||||
force_standalone_scrypt_module = False
|
||||
# Scrypt params: 'id_num': [N, r, p] (N is an exponent of two)
|
||||
# NB: hashlib.scrypt in Python (>=v3.6) supports max N value of 14. This means that
|
||||
# for hash presets > 3 the standalone scrypt library must be used!
|
||||
_hp = namedtuple('scrypt_preset',['N','r','p'])
|
||||
hash_presets = {
|
||||
'1': _hp(12, 8, 1),
|
||||
'2': _hp(13, 8, 4),
|
||||
'3': _hp(14, 8, 8),
|
||||
'4': _hp(15, 8, 12),
|
||||
'5': _hp(16, 8, 16),
|
||||
'6': _hp(17, 8, 20),
|
||||
'7': _hp(18, 8, 24),
|
||||
}
|
||||
|
||||
if os.getenv('MMGEN_TEST_SUITE'):
|
||||
err_disp_timeout = 0.1
|
||||
|
|
|
|||
|
|
@ -84,10 +84,11 @@ def die_on_incompatible_opts(incompat_list):
|
|||
def _show_hash_presets():
|
||||
fs = ' {:<7} {:<6} {:<3} {}'
|
||||
from .util import msg
|
||||
from .crypto import hash_presets
|
||||
msg('Available parameters for scrypt.hash():')
|
||||
msg(fs.format('Preset','N','r','p'))
|
||||
for i in sorted(g.hash_presets.keys()):
|
||||
msg(fs.format(i,*g.hash_presets[i]))
|
||||
for i in sorted(hash_presets.keys()):
|
||||
msg(fs.format(i,*hash_presets[i]))
|
||||
msg('N = memory usage (power of two), p = iterations (rounds)')
|
||||
sys.exit(0)
|
||||
|
||||
|
|
@ -554,17 +555,19 @@ def check_usr_opts(usr_opts): # Raises an exception if any check fails
|
|||
opt_is_in_list(int(val),Seed.lens,desc)
|
||||
|
||||
def chk_hash_preset(key,val,desc):
|
||||
opt_is_in_list(val,list(g.hash_presets.keys()),desc)
|
||||
from .crypto import hash_presets
|
||||
opt_is_in_list(val,list(hash_presets.keys()),desc)
|
||||
|
||||
def chk_brain_params(key,val,desc):
|
||||
from .seed import Seed
|
||||
from .crypto import hash_presets
|
||||
a = val.split(',')
|
||||
if len(a) != 2:
|
||||
opt_display(key,val)
|
||||
raise UserOptError('Option requires two comma-separated arguments')
|
||||
opt_is_int(a[0],'seed length '+desc)
|
||||
opt_is_in_list(int(a[0]),Seed.lens,'seed length '+desc)
|
||||
opt_is_in_list(a[1],list(g.hash_presets.keys()),'hash preset '+desc)
|
||||
opt_is_in_list(a[1],list(hash_presets.keys()),'hash preset '+desc)
|
||||
|
||||
def chk_usr_randchars(key,val,desc):
|
||||
if val == 0:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ tool.py: Routines for the 'mmgen-tool' utility
|
|||
from .common import *
|
||||
from .protocol import hash160
|
||||
from .fileutil import get_seed_file,get_data_from_file,write_data_to_file
|
||||
from .crypto import get_random
|
||||
from .crypto import get_random,aesctr_iv_len,mmgen_encrypt,mmgen_decrypt,mmenc_ext
|
||||
from .key import PrivKey
|
||||
from .subseed import SubSeedList
|
||||
from .seedsplit import MasterShareIdx
|
||||
|
|
@ -730,7 +730,6 @@ class MMGenToolCmdFileCrypt(MMGenToolCmds):
|
|||
def encrypt(self,infile:str,outfile='',hash_preset=''):
|
||||
"encrypt a file"
|
||||
data = get_data_from_file(infile,'data for encryption',binary=True)
|
||||
from .crypto import mmgen_encrypt,mmenc_ext
|
||||
enc_d = mmgen_encrypt(data,'data',hash_preset)
|
||||
if not outfile:
|
||||
outfile = f'{os.path.basename(infile)}.{mmenc_ext}'
|
||||
|
|
@ -740,7 +739,6 @@ class MMGenToolCmdFileCrypt(MMGenToolCmds):
|
|||
def decrypt(self,infile:str,outfile='',hash_preset=''):
|
||||
"decrypt a file"
|
||||
enc_d = get_data_from_file(infile,'encrypted data',binary=True)
|
||||
from .crypto import mmgen_decrypt,mmenc_ext
|
||||
while True:
|
||||
dec_d = mmgen_decrypt(enc_d,'data',hash_preset)
|
||||
if dec_d: break
|
||||
|
|
@ -757,7 +755,7 @@ class MMGenToolCmdFileUtil(MMGenToolCmds):
|
|||
|
||||
def find_incog_data(self,filename:str,incog_id:str,keep_searching=False):
|
||||
"Use an Incog ID to find hidden incognito wallet data"
|
||||
ivsize,bsize,mod = g.aesctr_iv_len,4096,4096*8
|
||||
ivsize,bsize,mod = ( aesctr_iv_len, 4096, 4096*8 )
|
||||
n,carry = 0,b' '*ivsize
|
||||
flgs = os.O_RDONLY|os.O_BINARY if g.platform == 'win' else os.O_RDONLY
|
||||
f = os.open(filename,flgs)
|
||||
|
|
@ -792,7 +790,7 @@ class MMGenToolCmdFileUtil(MMGenToolCmds):
|
|||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
def encrypt_worker(wid):
|
||||
ctr_init_val = os.urandom(g.aesctr_iv_len)
|
||||
ctr_init_val = os.urandom( aesctr_iv_len )
|
||||
c = Cipher(algorithms.AES(key),modes.CTR(ctr_init_val),backend=default_backend())
|
||||
encryptor = c.encryptor()
|
||||
while True:
|
||||
|
|
|
|||
|
|
@ -417,12 +417,6 @@ def strip_comment(line):
|
|||
def strip_comments(lines):
|
||||
return [m for m in [strip_comment(l) for l in lines] if m != '']
|
||||
|
||||
def get_hash_params(hash_preset):
|
||||
if hash_preset in g.hash_presets:
|
||||
return g.hash_presets[hash_preset] # N,r,p
|
||||
else: # Shouldn't be here
|
||||
die(3,f"{hash_preset}: invalid 'hash_preset' value")
|
||||
|
||||
def compare_chksums(chk1,desc1,chk2,desc2,hdr='',die_on_fail=False,verbose=False):
|
||||
|
||||
if not chk1 == chk2:
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ import os
|
|||
|
||||
from .common import *
|
||||
from .obj import *
|
||||
from .crypto import *
|
||||
from .baseconv import *
|
||||
from .seed import Seed
|
||||
import mmgen.crypto as crypto
|
||||
|
||||
def check_usr_seed_len(seed_len):
|
||||
if opt.seed_len and opt.seed_len != seed_len:
|
||||
|
|
@ -298,8 +298,7 @@ class WalletEnc(Wallet):
|
|||
('',' '+add_desc)[bool(add_desc)],
|
||||
('accept the default','reuse the old')[self.op=='pwchg_new'],
|
||||
hp )
|
||||
from .crypto import get_hash_preset_from_user
|
||||
return get_hash_preset_from_user( hash_preset=hp, prompt=prompt )
|
||||
return crypto.get_hash_preset_from_user( hash_preset=hp, prompt=prompt )
|
||||
|
||||
def _get_hash_preset(self,add_desc=''):
|
||||
if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
|
||||
|
|
@ -322,8 +321,7 @@ class WalletEnc(Wallet):
|
|||
self.ssdata.hash_preset = hp
|
||||
|
||||
def _get_new_passphrase(self):
|
||||
from .crypto import get_new_passphrase
|
||||
self.ssdata.passwd = get_new_passphrase(
|
||||
self.ssdata.passwd = crypto.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,
|
||||
|
|
@ -331,8 +329,7 @@ class WalletEnc(Wallet):
|
|||
return self.ssdata.passwd
|
||||
|
||||
def _get_passphrase(self,add_desc=''):
|
||||
from .crypto import get_passphrase
|
||||
self.ssdata.passwd = get_passphrase(
|
||||
self.ssdata.passwd = 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' )
|
||||
|
|
@ -353,10 +350,10 @@ class WalletEnc(Wallet):
|
|||
else:
|
||||
self._get_new_passphrase()
|
||||
|
||||
d.salt = sha256(get_random(128)).digest()[:g.salt_len]
|
||||
key = make_key(d.passwd, d.salt, d.hash_preset)
|
||||
d.salt = sha256( crypto.get_random(128) ).digest()[:crypto.salt_len]
|
||||
key = crypto.make_key( d.passwd, d.salt, d.hash_preset )
|
||||
d.key_id = make_chksum_8(key)
|
||||
d.enc_seed = encrypt_seed(self.seed.data,key)
|
||||
d.enc_seed = crypto.encrypt_seed( self.seed.data, key )
|
||||
|
||||
class Mnemonic(WalletUnenc):
|
||||
|
||||
|
|
@ -536,7 +533,7 @@ 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 = crypto.add_user_random(
|
||||
rand_bytes = seed_bytes,
|
||||
desc = 'gathered from your die rolls' )
|
||||
self.desc += ' plus user-supplied entropy'
|
||||
|
|
@ -741,7 +738,7 @@ class MMGenWallet(WalletEnc):
|
|||
lines = (
|
||||
d.label,
|
||||
'{} {} {} {} {}'.format( s.sid.lower(), d.key_id.lower(), s.bitlen, d.pw_status, d.timestamp ),
|
||||
'{}: {} {} {}'.format( d.hash_preset, *get_hash_params(d.hash_preset) ),
|
||||
'{}: {} {} {}'.format( d.hash_preset, *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) )
|
||||
)
|
||||
|
|
@ -789,7 +786,7 @@ class MMGenWallet(WalletEnc):
|
|||
|
||||
hash_params = tuple(map(int,hpdata[1:]))
|
||||
|
||||
if hash_params != get_hash_params(d.hash_preset):
|
||||
if hash_params != 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
|
||||
|
||||
|
|
@ -821,8 +818,8 @@ class MMGenWallet(WalletEnc):
|
|||
# Needed for multiple transactions with {}-txsign
|
||||
self._get_passphrase(
|
||||
add_desc = os.path.basename(self.infile.name) if opt.quiet else '' )
|
||||
key = make_key(d.passwd, d.salt, d.hash_preset)
|
||||
ret = decrypt_seed(d.enc_seed, key, d.seed_id, d.key_id)
|
||||
key = crypto.make_key( d.passwd, d.salt, d.hash_preset )
|
||||
ret = crypto.decrypt_seed( d.enc_seed, key, d.seed_id, d.key_id )
|
||||
if ret:
|
||||
self.seed = Seed(ret)
|
||||
return True
|
||||
|
|
@ -872,7 +869,7 @@ class Brainwallet(WalletEnc):
|
|||
bw_seed_len = opt.seed_len or Seed.dfl_len
|
||||
qmsg_r('Hashing brainwallet data. Please wait...')
|
||||
# Use buflen arg of scrypt.hash() to get seed of desired length
|
||||
seed = scrypt_hash_passphrase(
|
||||
seed = crypto.scrypt_hash_passphrase(
|
||||
self.brainpasswd.encode(),
|
||||
b'',
|
||||
d.hash_preset,
|
||||
|
|
@ -914,8 +911,11 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
def _make_iv_chksum(self,s): return sha256(s).hexdigest()[:8].upper()
|
||||
|
||||
def _get_incog_data_len(self,seed_len):
|
||||
e = (g.hincog_chk_len,0)[bool(opt.old_incog_fmt)]
|
||||
return g.aesctr_iv_len + g.salt_len + e + seed_len//8
|
||||
return (
|
||||
crypto.aesctr_iv_len
|
||||
+ crypto.salt_len
|
||||
+ (0 if opt.old_incog_fmt else crypto.hincog_chk_len)
|
||||
+ seed_len//8 )
|
||||
|
||||
def _incog_data_size_chk(self):
|
||||
# valid sizes: 56, 64, 72
|
||||
|
|
@ -941,25 +941,33 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
die(1,'Writing old-format incog wallets is unsupported')
|
||||
d = self.ssdata
|
||||
# IV is used BOTH to initialize counter and to salt password!
|
||||
d.iv = get_random(g.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}')
|
||||
qmsg('Make a record of this value')
|
||||
vmsg(self.msg['record_incog_id'])
|
||||
|
||||
d.salt = get_random(g.salt_len)
|
||||
key = make_key(d.passwd, d.salt, d.hash_preset, 'incog wallet key')
|
||||
d.salt = crypto.get_random( crypto.salt_len )
|
||||
key = crypto.make_key( d.passwd, d.salt, d.hash_preset, 'incog wallet key' )
|
||||
chk = sha256(self.seed.data).digest()[:8]
|
||||
d.enc_seed = encrypt_data(chk+self.seed.data, key, g.aesctr_dfl_iv, 'seed')
|
||||
d.enc_seed = crypto.encrypt_data(
|
||||
chk + self.seed.data,
|
||||
key,
|
||||
crypto.aesctr_dfl_iv,
|
||||
'seed' )
|
||||
|
||||
d.wrapper_key = make_key(d.passwd, d.iv, d.hash_preset, 'incog wrapper key')
|
||||
d.wrapper_key = crypto.make_key( d.passwd, d.iv, d.hash_preset, 'incog wrapper key' )
|
||||
d.key_id = make_chksum_8(d.wrapper_key)
|
||||
vmsg(f'Key ID: {d.key_id}')
|
||||
d.target_data_len = self._get_incog_data_len(self.seed.bitlen)
|
||||
|
||||
def _format(self):
|
||||
d = self.ssdata
|
||||
self.fmt_data = d.iv + encrypt_data(d.salt+d.enc_seed, d.wrapper_key, d.iv, self.desc)
|
||||
self.fmt_data = d.iv + crypto.encrypt_data(
|
||||
d.salt + d.enc_seed,
|
||||
d.wrapper_key,
|
||||
d.iv,
|
||||
self.desc )
|
||||
|
||||
def _filename(self):
|
||||
s = self.seed
|
||||
|
|
@ -979,9 +987,9 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
return False
|
||||
|
||||
d = self.ssdata
|
||||
d.iv = self.fmt_data[0:g.aesctr_iv_len]
|
||||
d.iv = self.fmt_data[0:crypto.aesctr_iv_len]
|
||||
d.incog_id = self._make_iv_chksum(d.iv)
|
||||
d.enc_incog_data = self.fmt_data[g.aesctr_iv_len:]
|
||||
d.enc_incog_data = self.fmt_data[crypto.aesctr_iv_len:]
|
||||
msg(f'Incog Wallet ID: {d.incog_id}')
|
||||
qmsg('Check this value against your records')
|
||||
vmsg(self.msg['check_incog_id'])
|
||||
|
|
@ -1010,19 +1018,19 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
self._get_passphrase(add_desc=d.incog_id)
|
||||
|
||||
# IV is used BOTH to initialize counter and to salt password!
|
||||
key = make_key(d.passwd, d.iv, d.hash_preset, 'wrapper key')
|
||||
dd = decrypt_data(d.enc_incog_data, key, d.iv, 'incog data')
|
||||
key = crypto.make_key( d.passwd, d.iv, d.hash_preset, 'wrapper key' )
|
||||
dd = crypto.decrypt_data( d.enc_incog_data, key, d.iv, 'incog data' )
|
||||
|
||||
d.salt = dd[0:g.salt_len]
|
||||
d.enc_seed = dd[g.salt_len:]
|
||||
d.salt = dd[0:crypto.salt_len]
|
||||
d.enc_seed = dd[crypto.salt_len:]
|
||||
|
||||
key = make_key(d.passwd, d.salt, d.hash_preset, 'main key')
|
||||
key = crypto.make_key( d.passwd, d.salt, d.hash_preset, 'main key' )
|
||||
qmsg(f'Key ID: {make_chksum_8(key)}')
|
||||
|
||||
verify_seed = getattr(self,'_verify_seed_'+
|
||||
('newfmt','oldfmt')[bool(opt.old_incog_fmt)])
|
||||
|
||||
seed = verify_seed(decrypt_seed(d.enc_seed, key, '', ''))
|
||||
seed = verify_seed( crypto.decrypt_seed(d.enc_seed, key, '', '') )
|
||||
|
||||
if seed:
|
||||
self.seed = Seed(seed)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class unit_test(object):
|
|||
|
||||
msg_r('Testing password hashing...')
|
||||
qmsg('')
|
||||
from mmgen.crypto import scrypt_hash_passphrase
|
||||
from mmgen.crypto import scrypt_hash_passphrase,hash_presets
|
||||
|
||||
salt = bytes.fromhex('f00f' * 16)
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ class unit_test(object):
|
|||
if opt.quiet:
|
||||
omsg_r('.')
|
||||
else:
|
||||
msg_r(f'\n {hp!r:3}: {g.hash_presets[hp]!r:12} ')
|
||||
msg_r(f'\n {hp!r:3}: {hash_presets[hp]!r:12} ')
|
||||
st = time.time()
|
||||
ret = scrypt_hash_passphrase(pw,salt,hp).hex()
|
||||
t = time.time() - st
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue