Files
cert/certgen/auth.py
T

50 lines
1.6 KiB
Python

"""Аутентификация: хеширование паролей, проверка, сессии, валидация."""
from __future__ import annotations
import hashlib
import hmac
import re
import secrets
PBKDF2_ITERATIONS = 200_000
EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
MIN_PASSWORD = 8
def hash_password(password: str, iterations: int = PBKDF2_ITERATIONS) -> str:
salt = secrets.token_bytes(16)
dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, iterations)
return f"pbkdf2_sha256${iterations}${salt.hex()}${dk.hex()}"
def verify_password(password: str, stored: str | None) -> bool:
if not stored:
return False
try:
algo, iters, salt_hex, digest = stored.split("$")
if algo != "pbkdf2_sha256":
return False
dk = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"),
bytes.fromhex(salt_hex), int(iters))
return hmac.compare_digest(dk.hex(), digest)
except (ValueError, AttributeError):
return False
def new_token() -> str:
return secrets.token_urlsafe(32)
def valid_email(email: str) -> bool:
email = (email or "").strip()
return bool(EMAIL_RE.match(email)) and len(email) <= 254
def validate_registration(email: str, password: str) -> str | None:
"""Вернуть текст ошибки или None, если всё хорошо."""
if not valid_email(email):
return "Некорректный email"
if len(password or "") < MIN_PASSWORD:
return f"Пароль должен быть не короче {MIN_PASSWORD} символов"
return None