mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 04:51:57 +00:00
41 lines
1.2 KiB
Python
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
|