Files
AgentLab/backend/app/auth/passwords.py
T

41 lines
1.2 KiB
Python

"""本地账号的口令:hashlib.scrypt,不加依赖。存成 scrypt$n$r$p$盐$摘要,参数随值存下,以后调参老口令照样认得。"""
from __future__ import annotations
import base64
import hashlib
import hmac
import secrets
_N, _R, _P = 2**14, 8, 1
_DKLEN = 32
MIN_LENGTH = 8
def _b64(data: bytes) -> str:
return base64.b64encode(data).decode()
def hash_password(password: str) -> str:
salt = secrets.token_bytes(16)
digest = hashlib.scrypt(password.encode(), salt=salt, n=_N, r=_R, p=_P, dklen=_DKLEN)
return f"scrypt${_N}${_R}${_P}${_b64(salt)}${_b64(digest)}"
def verify_password(password: str, stored: str | None) -> bool:
if not stored or not stored.startswith("scrypt$"):
return False
try:
_, n, r, p, salt, digest = stored.split("$")
want = base64.b64decode(digest)
got = hashlib.scrypt(password.encode(), salt=base64.b64decode(salt), n=int(n), r=int(r), p=int(p),
dklen=len(want))
except (ValueError, TypeError):
return False
return hmac.compare_digest(got, want)
def password_problem(password: str | None) -> str | None:
if not password or len(password) < MIN_LENGTH:
return f"密码至少 {MIN_LENGTH} 位"
return None