Files
fastapi_server/app/common/security/password_hasher.py

41 lines
1.1 KiB
Python

import base64
import hashlib
import hmac
import secrets
ALGORITHM = "pbkdf2_sha256"
ITERATIONS = 390_000
def _b64encode(raw: bytes) -> str:
return base64.urlsafe_b64encode(raw).decode("ascii").rstrip("=")
def _b64decode(value: str) -> bytes:
padding = "=" * (-len(value) % 4)
return base64.urlsafe_b64decode(value + padding)
def hash_password(password: str, iterations: int = ITERATIONS) -> str:
salt = secrets.token_bytes(16)
digest = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, iterations)
return f"{ALGORITHM}${iterations}${_b64encode(salt)}${_b64encode(digest)}"
def verify_password(password: str, stored_hash: str) -> bool:
try:
algorithm, iterations, salt, expected = stored_hash.split("$", 3)
except ValueError:
return hmac.compare_digest(password, stored_hash)
if algorithm != ALGORITHM:
return False
digest = hashlib.pbkdf2_hmac(
"sha256",
password.encode("utf-8"),
_b64decode(salt),
int(iterations),
)
return hmac.compare_digest(_b64encode(digest), expected)