Files
X-Financial/server/src/app/core/security.py

43 lines
1.2 KiB
Python
Raw Normal View History

from __future__ import annotations
import hashlib
import secrets
from base64 import urlsafe_b64decode, urlsafe_b64encode
PBKDF2_ALGORITHM = "sha256"
PBKDF2_ITERATIONS = 120_000
SALT_BYTES = 16
def hash_password(password: str) -> str:
salt = secrets.token_bytes(SALT_BYTES)
digest = hashlib.pbkdf2_hmac(
PBKDF2_ALGORITHM,
password.encode("utf-8"),
salt,
PBKDF2_ITERATIONS,
)
encoded_salt = urlsafe_b64encode(salt).decode("utf-8")
encoded_digest = urlsafe_b64encode(digest).decode("utf-8")
return f"pbkdf2_{PBKDF2_ALGORITHM}${PBKDF2_ITERATIONS}${encoded_salt}${encoded_digest}"
def verify_password(password: str, password_hash: str) -> bool:
try:
scheme, iterations, encoded_salt, encoded_digest = password_hash.split("$", 3)
except ValueError:
return False
if scheme != f"pbkdf2_{PBKDF2_ALGORITHM}":
return False
salt = urlsafe_b64decode(encoded_salt.encode("utf-8"))
expected_digest = urlsafe_b64decode(encoded_digest.encode("utf-8"))
computed_digest = hashlib.pbkdf2_hmac(
PBKDF2_ALGORITHM,
password.encode("utf-8"),
salt,
int(iterations),
)
return secrets.compare_digest(computed_digest, expected_digest)