import os import base64 import hashlib import secrets ALGORITHM = "pbkdf2_sha256" def crypt(password: str, salt: bytes=None, iterations=260000) -> str: if salt is None: salt = os.urandom(16) hashed = hashlib.pbkdf2_hmac( 'sha256', bytes(password, 'utf-8'), salt, iterations ) return '$'.join([ ALGORITHM, str(iterations), str(base64.b64encode(salt), 'ascii'), str(base64.b64encode(hashed), 'ascii') ]) def compare(password: str, crypted: str) -> bool: parts = crypted.split('$', 4) if len(parts) != 4: return False algorithm, iterations, salt, hashed = parts if algorithm != ALGORITHM: return False new_crypted = crypt(password, base64.b64decode(salt), int(iterations)) return secrets.compare_digest(crypted, new_crypted)