用户表 password 字段是 32 位小写十六进制,测试同事拿常见密码字典跑了一遍,两百个账号里解出一百四十多个原文,最慢的一个花了三分钟。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

from werkzeug.security import generate_password_hash
h = generate_password_hash(pwd, method='pbkdf2:sha256', salt_length=16)
print(len(h), h[:20])

MD5 本身是快速摘要,设计目标就是快,一张显卡每秒能算几十亿次。不加盐还让相同密码得到相同哈希,彩虹表直接查表就行。这类哈希一旦库被拖走,等同于存了明文。这一点先确认清楚,后面就不用反复试。

「密码哈希 MD5」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。

具体做法是,换成 bcrypt 或 argon2id 这类慢哈希 成本参数按机器实测调;每个密码单独生成盐 盐和哈希一起存;老数据在用户下次登录时按新算法重算 不要一次性全量转;登录接口加失败计数和延迟。

改完照着核一遍,新增账号的哈希长度过百 同一密码两次生成结果不同 老账号登录后字段自动换成新格式。

作者 9823189