import uuid import hmac import hashlib from . import config def encrypt_phone(phone): return hmac.new( config.PHONE_HMAC_KEY.encode("utf-8"), phone.encode("utf-8"), hashlib.sha256, ).hexdigest() def create_session_token(): """生成写入 auth_sessions 的会话 token(长度适合 token VARCHAR(64))。""" return uuid.uuid4().hex + uuid.uuid4().hex[:16] # ── 密码哈希(手机号+密码登录用,2026-09-22 新增)───────────────────── # 统一用纯 SHA-256:hashlib.sha256(p.encode()).hexdigest(), # 与遗留鉴权代码 routes/auth_api.py / routes/auth_app.py 的 hash_pwd() 完全一致。 # 刻意不引入 bcrypt / passlib / PBKDF2,也不加盐(保持与存量数据格式一致)。 # 存储格式:64 位十六进制 hex 串。 def hash_password(password): """把明文密码变成可入库的哈希串(纯 SHA-256 hex,无盐)。""" if not password: raise ValueError("password 不能为空") return hashlib.sha256(password.encode()).hexdigest() def verify_password(password, stored): """校验明文密码是否匹配存储串(恒时比较,防时序侧信道)。 ⚠️ stored 为 None / 空串一律返回 False,**绝不把异常抛给调用方**。 典型场景:006 迁移还没执行时 SELECT * 取不到 password_hash 列,这里是 None。 """ if not password or not stored: return False return hmac.compare_digest( hashlib.sha256(password.encode()).hexdigest(), stored, )