密码该用哪个哈希:MD5、SHA-256 与 bcrypt 的分工
「MD5 不安全」这句话半对:它在抗碰撞上确实破了,但用在非安全场景(缓存键、去重)依然合适。
真正危险的是用 MD5/SHA-256 存密码——它们太快,快就是弱点。
先说结论
密码用 argon2id 或 bcrypt,完整性用 SHA-256,身份认证用 HMAC。
- 密码存储必须慢哈希 + 每用户盐
- SHA-256 适合校验,不适合存密码
- HMAC 用于消息认证,不要用 hash(key+msg)
- 不要自己设计算法
漏洞是怎么产生的
哈希函数的速度决定了暴力破解的成本。SHA-256 每秒能算上亿次,bcrypt 只能算几千次——后者才是密码该用的。
加盐解决的是「彩虹表」与「相同密码相同哈希」,不解决「弱密码」。
修复与验证
修复不是改一行代码,而是四件事一起做:
- 盘点现有存储:是否有 MD5/SHA1 存密码
- 迁移到 bcrypt(cost 10-12)或 argon2id
- 登录成功时透明升级旧哈希
- 校验场景用 SHA-256,不用于密码
- 消息认证用 HMAC-SHA256,不用拼接哈希
攻击面与检测点
按影响面排序,先修影响最大的:
| 场景 | 算法 | 原因 |
|---|---|---|
| 密码存储 | argon2id/bcrypt | 慢,抗暴力 |
| 文件校验 | SHA-256 | 快且抗碰撞 |
| 消息认证 | HMAC-SHA256 | 带密钥 |
| 缓存键 | MD5/xxhash | 速度优先 |

几个容易踩的坑
下面这些是最常见的错误做法:
- 用 MD5 存密码:GPU 秒破
- 全局固定盐:等于没加盐
- 自己实现加密逻辑:几乎一定有漏洞
- 把哈希当加密:不可逆不代表安全
写在最后
选算法的第一步是明确「防谁、防多久」,而不是「哪个更新」。
安全不是一次加固,是持续的假设:假设输入不可信、假设边界会破、假设有人会看错。
评论 (3)
修复清单比漏洞描述有用多了,很多文章只讲怎么打不讲怎么防。
白名单那条永远是最有效的,正则黑名单迟早绕过。
建议再补一条:把这类检查加到 CI 里,靠人记必然漏。
发表评论