from __future__ import annotations import hashlib import hmac import secrets def hash_password(password: str) -> str: salt = secrets.token_hex(16) digest = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt.encode("utf-8"), 120_000) return f"pbkdf2_sha256${salt}${digest.hex()}" def verify_password(password: str, password_hash: str) -> bool: try: algorithm, salt, digest_hex = password_hash.split("$", 2) except ValueError: return False if algorithm != "pbkdf2_sha256": return False digest = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt.encode("utf-8"), 120_000) return hmac.compare_digest(digest.hex(), digest_hex) def mask_secret_url(url: str) -> str: if "key=" not in url: return url prefix, suffix = url.split("key=", 1) if "&" in suffix: token, tail = suffix.split("&", 1) return f"{prefix}key={token[:2]}***&{tail}" return f"{prefix}key={suffix[:2]}***"