Three-pane webmail client. - Backend: FastAPI + async SQLAlchemy + arq worker (Postgres/Redis), IMAP/SMTP sync, threading, search, drafts/outbox with undo, attachments, 2FA. - Frontend: React 18 + Vite + TypeScript + TanStack Query + Tailwind; three-pane UI with rich-text composer, light/dark themes, resizable panels. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
35 lines
1.0 KiB
Python
35 lines
1.0 KiB
Python
"""Argon2id password hashing (SPEC §6.1, §10.1).
|
|
|
|
Params are fixed: ``time_cost=3``, ``memory_cost=64 MiB``, ``parallelism=4``.
|
|
No other password hashing is permitted anywhere (SPEC §10.1).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from argon2 import PasswordHasher
|
|
from argon2.exceptions import VerificationError, VerifyMismatchError
|
|
|
|
_hasher = PasswordHasher(
|
|
time_cost=3,
|
|
memory_cost=64 * 1024, # KiB -> 64 MiB
|
|
parallelism=4,
|
|
)
|
|
|
|
|
|
def hash_password(password: str) -> str:
|
|
"""Return an argon2id hash for ``password``."""
|
|
return _hasher.hash(password)
|
|
|
|
|
|
def verify_password(password_hash: str, password: str) -> bool:
|
|
"""Constant-time verify ``password`` against ``password_hash``."""
|
|
try:
|
|
return _hasher.verify(password_hash, password)
|
|
except (VerifyMismatchError, VerificationError):
|
|
return False
|
|
|
|
|
|
def needs_rehash(password_hash: str) -> bool:
|
|
"""Return True if ``password_hash`` was made with outdated parameters."""
|
|
return _hasher.check_needs_rehash(password_hash)
|