79 lines
1.9 KiB
Python
79 lines
1.9 KiB
Python
import argon2, os
|
|
|
|
from .misc import time_function_pprint
|
|
|
|
|
|
class PasswordHasher:
|
|
'''
|
|
Argon2 password hasher and validator
|
|
|
|
Attributes:
|
|
config (dict): The settings used for the hasher
|
|
|
|
Methods:
|
|
get_config(key): Get the value of a config options
|
|
set_config(key, value): Set a config option
|
|
hash(password): hash a password and return the digest as a hex string
|
|
verify(hash, password): verify a password and the password hash match
|
|
iteration_test(string, passes, iterations): Time the hashing functionality
|
|
'''
|
|
|
|
aliases = {
|
|
'iterations': 'time_cost',
|
|
'memory': 'memory_cost',
|
|
'threads': 'parallelism'
|
|
}
|
|
|
|
|
|
def __init__(self, iterations=16, memory=100, threads=os.cpu_count(), type=argon2.Type.ID):
|
|
if not argon2:
|
|
raise ValueError('password hashing disabled')
|
|
|
|
self.config = {
|
|
'time_cost': iterations,
|
|
'memory_cost': memory * 1024,
|
|
'parallelism': threads,
|
|
'encoding': 'utf-8',
|
|
'type': type,
|
|
}
|
|
|
|
self.hasher = argon2.PasswordHasher(**self.config)
|
|
|
|
|
|
def get_config(self, key):
|
|
key = self.aliases.get(key, key)
|
|
|
|
value = self.config[key]
|
|
return value / 1024 if key == 'memory_cost' else value
|
|
|
|
|
|
def set_config(self, key, value):
|
|
key = self.aliases.get(key, key)
|
|
self.config[key] = value * 1024 if key == 'memory_cost' else value
|
|
self.hasher = argon2.PasswordHasher(**self.config)
|
|
|
|
|
|
def hash(self, password: str):
|
|
return self.hasher.hash(password)
|
|
|
|
|
|
def verify(self, passhash: str, password: str):
|
|
try:
|
|
return self.hasher.verify(passhash, password)
|
|
|
|
except argon2.exceptions.VerifyMismatchError:
|
|
return False
|
|
|
|
|
|
def iteration_test(self, string='hecking heck', passes=3, iterations=[8,16,24,32,40,48,56,64]):
|
|
original_iter = self.get_config('iterations')
|
|
|
|
for iteration in iterations:
|
|
self.set_config('iterations', iteration)
|
|
print('\nTesting hash iterations:', iteration)
|
|
|
|
time_function_pprint(self.verify, self.hash(string), string, passes=passes)
|
|
|
|
self.set_config('iterations', original_iter)
|
|
|