feat: 5.1-3 Создать модуль app/core/passwords.py
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
from argon2 import PasswordHasher
|
||||
from argon2.exceptions import InvalidHashError, VerifyMismatchError
|
||||
from argon2.low_level import Type
|
||||
from zxcvbn import zxcvbn
|
||||
|
||||
from app.config import settings
|
||||
|
||||
|
||||
class WeakPasswordError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
_hasher = PasswordHasher(
|
||||
time_cost=3,
|
||||
memory_cost=65536,
|
||||
parallelism=4,
|
||||
hash_len=32,
|
||||
salt_len=16,
|
||||
type=Type.ID,
|
||||
)
|
||||
|
||||
|
||||
def _peppered(password: str) -> str:
|
||||
return password + settings.password_pepper
|
||||
|
||||
|
||||
# возвращает хэш Argon2id от password + pepper;
|
||||
def hash_password(password: str) -> str:
|
||||
return _hasher.hash(_peppered(password))
|
||||
|
||||
|
||||
# проверяет соответствие
|
||||
def verify_password(password: str, hashed: str) -> bool:
|
||||
try:
|
||||
return _hasher.verify(hashed, _peppered(password))
|
||||
except (VerifyMismatchError, InvalidHashError):
|
||||
return False
|
||||
|
||||
|
||||
# проверяет политику
|
||||
def validate_policy(password: str, user_inputs: list[str] | None = None) -> None:
|
||||
# длина не меньше settings.password_min_length;
|
||||
if len(password) < settings.password_min_length:
|
||||
raise WeakPasswordError(
|
||||
f"Password must be >= {settings.password_min_length} chars"
|
||||
)
|
||||
result = zxcvbn(password, user_inputs=user_inputs or [])
|
||||
# оценка стойкости через zxcvbn должна быть не ниже 3 (по шкале 0–4);
|
||||
if result["score"] < 3:
|
||||
raise WeakPasswordError("Password is too weak")
|
||||
Reference in New Issue
Block a user