Become a sponsor

说明
采用 bcrypt 双重加盐方案存储密码,源码位于 src/core/password.py。工作因子 12(约 250ms),在安全性和性能之间取得平衡。
密码存储采用「外部随机盐 + bcrypt 内部盐」双重加盐方案:
用户密码 + 外部盐 → bcrypt.hashpw → 存储哈希值import secrets
BCRYPT_ROUNDS = 12 # 工作因子,约250ms
def generate_salt(length: int = 10) -> str:
"""生成随机盐值"""
return secrets.token_urlsafe(length)[:length]import bcrypt
def encrypt_password(password: str, salt: str) -> str:
"""使用 bcrypt 加密密码(外部 salt 双重加盐)"""
combined = (password + salt).encode('utf-8')
hashed = bcrypt.hashpw(combined, bcrypt.gensalt(rounds=BCRYPT_ROUNDS))
return hashed.decode('utf-8')def verify_password(password: str, salt: str, hashed: str) -> bool:
"""验证密码是否正确"""
combined = (password + salt).encode('utf-8')
return bcrypt.checkpw(combined, hashed.encode('utf-8'))BCRYPT_ROUNDS = 12 表示 bcrypt 的工作因子为 12,即需要 2^12 = 4096 次迭代。值越大计算越慢越安全,12 是当前推荐值(约 250ms)。
温馨提示
bcrypt 的工作因子决定了加密速度。增加 1 会使计算时间翻倍。建议保持默认值 12,在安全性和性能之间取得平衡。
用户表中密码相关字段:
| 字段 | 说明 |
|---|---|
password | bcrypt 哈希后的密码 |
salt | 外部随机盐值 |
from core.password import generate_salt, encrypt_password
salt = generate_salt()
hashed = encrypt_password("mypassword", salt)
# 将 hashed 和 salt 存入数据库登录验证位于 src/modules/auth/service.py,bcrypt 为 CPU 密集操作,使用 asyncio.to_thread 放入线程池避免阻塞事件循环:
from core.password import verify_password
# 从数据库获取用户记录
user = get_user_by_username(username)
# bcrypt 为 CPU 密集操作,放入线程池
password_ok = await asyncio.to_thread(
password.verify_password, data.password, user.salt or '', user.password or ''
)
if password_ok:
# 密码正确
...# 验证旧密码
if not verify_password(old_password, user.salt, user.password):
return R.failed("原密码错误")
# 生成新盐值并加密
new_salt = generate_salt()
new_hashed = encrypt_password(new_password, new_salt)
# 更新数据库1. 双重加盐:外部随机盐 + bcrypt 内部盐,即使两个用户使用相同密码,存储的哈希值也不同
2. 抗彩虹表:bcrypt 自带盐值,无法预计算彩虹表
3. 抗暴力破解:工作因子 12 使每次验证约 250ms,大幅增加暴力破解成本
4. 自适应性:工作因子可随硬件提升而增加密码工具采用 bcrypt 双重加盐方案,外部盐值由 secrets.token_urlsafe() 生成,bcrypt 内部盐自动处理。工作因子 12 在安全性和性能之间取得平衡,有效抵御彩虹表和暴力破解攻击。