🔐

密码强度与哈希安全选型

加密与生成发布于 2026-10-09·阅读约 8 分钟

一、场景:给新系统设计账号模块

任何要存密码的系统都绕不开两个问题:密码策略定多严?哈希算法选哪个?这两个问题都有大量过时资料在流传(MD5 存密码至今仍在面试题里出现)。这篇指南用本站工具做几个小实验,建立正确的直觉。

二、实验一:哈希是单向的,且对输入极敏感

打开 哈希工具,做三组对照:

  • 输入 password 与 password (末尾多一个空格),MD5 / SHA-256 结果完全不同——哈希不是"压缩",输入任何一点变化都会雪崩式改变输出;
  • 同一输入的 MD5 永远相同——所以哈希可以当"指纹"用于完整性校验,但也意味着相同密码的哈希值相同(下文详述后果);
  • 把同一文本分别算 MD5 与 SHA-256,输出长度固定为 32 / 64 个十六进制字符——输出长度与输入长度无关。

三、实验二:为什么 MD5 不能存密码

MD5 的致命伤是"太快 + 已被破解"。快,意味着暴力破解每秒可尝试数十亿次;"破解"指 2004 年起学界已能构造碰撞——两个不同输入产生相同 MD5。在 MD5 工具 里算一个常用弱密码(如 123456)的 MD5,把结果拿到搜索引擎搜一下:大概率能直接查到原文——彩虹表早已收录了海量常见密码的 MD5。

结论:MD5 仅适用于非安全场景的完整性校验(如文件去重、缓存 key),涉及口令存储一律禁用。

四、正确的密码存储方案

  • 慢哈希算法:bcrypt / scrypt / Argon2,设计目标就是"慢",让暴力破解成本高到不可行。框架默认方案(如 Laravel 的 bcrypt、Django 的 PBKDF2)通常已经正确;
  • 加盐:每个用户随机 salt,拼接后再哈希。相同密码因盐不同而哈希不同,彩虹表失效。salt 不需要保密,与哈希值一起存储即可;
  • 前端不需要也不应该做哈希:HTTPS 已保证传输安全,前端哈希反而让"密码"变成"哈希值即密码"。登录表单要做的是防 XSS 与限制提交频率。

五、HMAC:带密钥的哈希

当你需要"只有持有密钥的双方才能验证"的场景(如 API 签名、webhook 校验),用 哈希工具 的 HMAC 模式:输入文本 + 密钥,生成 HMAC-SHA256。它和普通哈希的区别:没有密钥的攻击者即使知道算法也无法伪造合法签名。前后端约定的接口签名、支付回调校验都是典型用途。

六、密码强度:长度优于复杂度

打开 密码生成器,对比两类密码:

  • P@ssw0rd!:看似复杂,实则键盘模式变体,字典攻击秒破——复杂度规则(大小写+符号)已经被 NIST 新指南降级;
  • 16 位随机密码(工具默认 16 位含大小写数字符号):熵值约 100 bit,按当前算力暴力破解以万年计。

给用户的建议按优先级:① 用密码管理器 + 每站独立随机密码;② 实在要手记,用四个不相关单词拼接(长度带来熵);③ 系统侧只设最小长度(建议 12+),不要强制定期换密码(会诱发弱模式如 password1 → password2)。

七、常见问题

  • 文件 MD5 对不上:确认两次下载完整(对比文件大小),下载工具的"秒传 / 增量"逻辑可能改变了文件;MD5 工具支持直接拖文件计算,避免复制文本引入换行差异;
  • SHA-1 还能用吗:2017 年 Google 公布了实际碰撞攻击(SHAttered),证书签名等安全场景早已淘汰;非安全校验场景仍可用但建议直接上 SHA-256;
  • 哈希值能反查吗:不能"算"回来,但弱密码的常见哈希可被查表命中。这也是"密码要随机且够长"的根本原因。

八、小结

记住三句话:口令存储用 bcrypt / Argon2 加盐,接口签名用 HMAC-SHA256,MD5 只做非安全校验。密码策略向"长度"倾斜而不是"花哨符号"。工具在手,这些结论都可以自己动手验证一遍。

本篇涉及的工具

继续阅读