from __future__ import annotations import base64 import hashlib import hmac import secrets def hash_password(password: str, salt: str | None = None) -> str: salt_value = salt or secrets.token_hex(16) derived = hashlib.pbkdf2_hmac( "sha256", password.encode("utf-8"), salt_value.encode("utf-8"), 200_000, ) digest = base64.b64encode(derived).decode("utf-8") return f"pbkdf2_sha256${salt_value}${digest}" def verify_password(password: str, password_hash: str) -> bool: algorithm, salt, digest = password_hash.split("$", 2) if algorithm != "pbkdf2_sha256": return False expected = hash_password(password, salt=salt) return hmac.compare_digest(expected, password_hash) def generate_session_token() -> str: return f"iron_{secrets.token_urlsafe(32)}" def hash_session_token(token: str) -> str: return hashlib.sha256(token.encode("utf-8")).hexdigest()