密码安全的规则已经变了
你在 2010 年学到的密码安全知识基本全是错的。强制特殊字符、每 90 天轮换一次、给 P@ssw0rd! 打高分的"强度计"——这些做法在实践中反而产生更弱的密码。NIST 在更新后的指南(SP 800-63B,2024 年修订)中明确建议不要使用复杂度规则。微软、Google 和英国的 NCSC 也跟进了。研究结论很清楚:复杂度要求导致可预测的模式,而单纯的长度要求在真实世界中产生更好的安全性。
老规则为什么失败了?当你强制用户在 8 个字符中包含大写、小写、数字和符号时,他们不会生成随机字符串。他们会写 "Password1!" 或 "Summer2024$" 或者他们家狗的名字加个大写字母和感叹号。攻击者知道这一点。每个破解字典都包含这些模式。2023 年对 5 亿条泄露密码的分析发现,83% 满足"复杂"要求的密码遵循不到 20 种可预测模式。
新共识:一个 16 字符的小写短语如 "correct horse battery staple" 比 "Tr0ub4dor&3" 有更高的熵值,而且更容易记住。长度是最重要的单一因素,因为它指数级增加搜索空间。每多一个字符,可能性就乘以字符集大小(小写字母是 26,所有可打印 ASCII 是 95)。
密码熵值到底怎么算
熵值用比特数衡量密码的不可预测性。一个从 N 个可能字符中随机选取、长度为 L 的密码,熵值 = L × log2(N) 比特。一个 8 字符密码使用全部 95 个可打印 ASCII 字符,熵值是 8 × 6.57 = 52.6 比特。一个 16 字符纯小写密码,熵值是 16 × 4.7 = 75.2 比特。更长的密码虽然字符集更小,但破解难度天文级地高于短密码。
但有个前提:熵值计算假设密码是真正随机的。"password123456" 有 14 个字符来自 36 字符集,理论上有 72.4 比特熵值。实际上它的有效熵值接近零,因为它在每个破解字典里都有。熵值只衡量对暴力破解的强度,不衡量对字典攻击的强度。这就是为什么我们的密码生成器工具使用密码学安全的随机数——人类选择的密码几乎永远达不到理论熵值。
到底需要多少熵值?面对离线攻击(攻击者拿到了你的哈希密码,可以无限次尝试),你需要足够的熵值来耗尽他们的硬件。一台现代 GPU 矿机每秒能尝试 1000 亿次 MD5 哈希。按这个速度:40 比特熵值 11 秒就破了。50 比特需要 3 小时。60 比特需要 133 天。70 比特需要 374 年。80 比特需要 38.3 万年。重要账户瞄准 70+ 比特。
面对在线攻击(有频率限制的登录表单),即使 30 比特熵值也够了——前提是服务在 10 次失败后锁定账户。真正的威胁是数据库泄露后的离线破解。这就是为什么哈希算法和密码强度同样重要——bcrypt cost factor 12 能把那 1000 亿次/秒降到每 GPU 约 5000 次/秒。
NIST 800-63B 到底建议了什么
NIST 数字身份指南(SP 800-63B,第 5.1.1 节)是政府和企业密码安全的金标准。去掉官僚语言后它说的是:最少 8 个字符(建议允许最多 64 个)。不要复杂度规则(不强制大写/符号)。不要定期轮换,除非有证据表明已被泄露。对照泄露数据库筛查密码。允许在密码字段中粘贴。
"不轮换"这条让很多人意外。NIST 的理由是:强制轮换导致用户做最小改动(Summer2024 → Fall2024 → Winter2025),攻击者能预测这些变化。如果密码足够强且未被泄露,换密码不增加安全性。只在以下情况换密码:怀疑被泄露、服务报告未授权访问、或者你在某个被攻破的网站上重用了这个密码。
对照泄露数据库筛查意味着检查新密码是否出现在 Have I Been Pwned 的 9 亿多条泄露密码列表中。k-anonymity API 让你不用发送完整密码就能检查——你发送 SHA-1 哈希的前 5 个字符,拿回所有匹配的哈希在本地比对。如果密码出现在泄露中,无论熵值多高都拒绝它。
NIST 没说但我要说的一点:用密码管理器。为每个服务拥有唯一的高熵密码的唯一方法就是不去记它们。1Password、Bitwarden 或 KeePass 生成并存储随机密码。你的一个主密码(用长短语)保护其他所有密码。2026 年,这不是可选项——这是基线。
密码是怎么被破解的(攻击方法)
暴力破解:尝试每一种可能的组合。对一个使用全部 95 个可打印 ASCII 字符的 8 字符密码(6.6 千万亿种组合),一块 RTX 4090 以每秒 1640 亿次的速度破解 MD5 哈希,11 小时搞定。对 bcrypt(cost 12),同一块 GPU 每秒只能算约 70 次哈希,暴力破解需要 3 万亿年。哈希算法是你最后一道防线。
字典攻击:尝试常见密码、单词、名字和已知模式。RockYou 泄露事件(2009 年,3200 万条密码)显示 "123456" 被 29 万个账户使用。现代字典包含每次重大泄露中的密码、常见替换(a→@、e→3、o→0)和键盘模式(qwerty、zxcvbn)。带规则的字典攻击(追加数字、首字母大写)能在几分钟内破解 60-70% 的人类选择的密码。
撞库攻击:拿一个网站泄露的邮箱/密码对去其他服务试。这之所以有效是因为 65% 的人在多个网站重用密码(Google/Harris Poll,2019 年)。2020 年 Zoom 撞库攻击用不相关泄露中的密码攻破了 50 万个账户。这就是为什么每个服务用唯一密码比密码强度本身更重要。
彩虹表:预计算的哈希到密码查找表。一个覆盖所有 8 字符字母数字密码的 MD5 彩虹表大约 460 GB。这就是加盐存在的原因——在哈希前给每个密码加一个随机值,让预计算表失效。任何现代哈希算法(bcrypt、scrypt、Argon2)都默认包含加盐。如果你还在用不加盐的 MD5 或 SHA-256 存密码,那是在犯错。
密码存储:正确的哈希方式
永远不要明文存储密码。永远不要加密存储(加密是可逆的——如果服务器被攻破,密钥也跟着暴露)。永远用专门设计的密码哈希函数来哈希。2026 年的正确选择是:Argon2id(2015 年密码哈希竞赛冠军)、bcrypt(1999 年以来久经考验)或 scrypt(内存密集型,擅长防 GPU 攻击)。
为什么不用 SHA-256?因为 SHA-256 设计目标就是快。一块 GPU 每秒能算 100 亿次 SHA-256 哈希。密码哈希函数故意设计得很慢——bcrypt cost factor 12 在现代 CPU 上每次哈希约 250ms。这个慢就是重点。它让暴力破解对攻击者来说计算代价高昂,同时对合法用户几乎无感(每次登录只哈希一次)。
Argon2id 2026 年推荐参数:最少 64 MB 内存、3 次迭代、4 个并行线程。这些参数强制攻击者每次猜测使用 64 MB RAM,让基于 GPU 的攻击不切实际(GPU 每个核心的内存有限)。根据你的服务器容量向上调整——目标是在你的硬件上每次哈希约 250-500ms。我们的 hash-generator 工具展示了不同算法和参数如何影响计算时间。
迁移路径:如果你目前在用 bcrypt,不用急着迁移。bcrypt cost 12+ 仍然安全。如果你在用 MD5 或 SHA-256(不管有没有盐),立即迁移。标准做法:用户下次登录时,用旧哈希验证,然后用 Argon2id 重新哈希并存储新哈希。永远不再登录的用户保留旧哈希——接受这一点,或者强制密码重置。
多因素认证(真正的安全层)
一个不太舒服的事实:即使完美的密码安全实践也无法防御钓鱼。如果用户把 128 比特熵值的密码输入了一个假登录页面,密码就泄露了。多因素认证(MFA)是对抗凭据窃取的唯一防线。Google 报告称添加基于短信的 2FA 阻止了 100% 的自动化机器人攻击和 96% 的批量钓鱼攻击。
MFA 从弱到强的层级:短信验证码(容易被 SIM 卡劫持——T-Mobile 2021 年泄露了 7600 万条记录)、TOTP 应用(Google Authenticator、Authy——能防远程攻击但防不了实时钓鱼)、推送通知(Duo、Microsoft Authenticator——容易被 MFA 疲劳攻击,攻击者不停发推送直到用户点同意)、硬件密钥(YubiKey、Google Titan——抗钓鱼,因为它们验证域名)。
FIDO2/WebAuthn 通行密钥是未来方向。它们使用绑定到特定域名的公钥密码学,让钓鱼在数学上不可能。私钥永远不离开你的设备。Apple、Google 和 Microsoft 从 2024 年起都支持通行密钥。普及的问题在于:用户需要主动设置,而且不是所有服务都支持。目前的实用建议是 TOTP + 硬件密钥作为备份。
给实现 MFA 的开发者:永远不要让管理员账户的 MFA 是可选的。任何更改安全设置(邮箱、密码、MFA 本身)的操作都要求 MFA。备份码要哈希存储(它们等同于密码)。对 MFA 尝试做频率限制,防止暴力破解 6 位 TOTP 码(只有 100 万种可能,而且 30 秒内有效)。
真正有效的密码策略
基于 NIST 800-63B 和真实泄露数据,2026 年好的密码策略长这样:最少 12 个字符(NIST 说 8,但 12 即使哈希算法较弱也能提供有意义的暴力破解抵抗力)。最多 64+ 个字符(永远不要限制密码长度——bcrypt 在 72 字节处截断,但那是算法的事,不是你 UI 的事)。不要复杂度规则。不要轮换计划。屏蔽前 10 万条泄露密码。
给用户展示什么:基于实际熵值估算的强度计(Dropbox 的 zxcvbn 库很优秀——它考虑了字典词、键盘模式和常见替换)。显示"弱/中/强"并附具体反馈:"这个密码出现在数据泄露中"或"再加 4 个字符会显著增强安全性"。不要只显示一个没有解释的彩色条。
不要做什么:不要禁止在密码字段中粘贴(这惩罚的是密码管理器用户——安全实践最好的那群人)。不要限制字符集(允许 Unicode——有些用户想用母语设置密码)。不要把"密码要求"显示为用户用最小努力就能满足的清单。不要用明文邮件发送密码(用有时间限制的重置链接)。
企业环境:在注册时和登录时都实施泄露密码筛查(密码会随时间被泄露)。记录失败的认证尝试并对异常告警(来自不同 IP 的 10 次失败尝试针对同一账户 = 撞库攻击)。考虑基于风险的认证——新设备或异常位置的登录要求 MFA,但用户日常使用的笔记本不需要。
关于密码安全的残酷现实
没有任何密码策略能修复根本问题:人类不擅长随机性,却擅长走捷径。普通用户有 100 多个在线账户,大多数都在重用密码。密码管理器解决了这个问题,但普通用户的采用率只有约 30%(开发者群体更高)。在无密码认证(通行密钥、生物识别)普及之前,我们只能把密码当作必要之恶来对待。
最大的风险不是弱密码——是泄露后的密码重用。Collection #1 泄露(2019 年)包含 7.73 亿个唯一的邮箱/密码对。如果你的用户在其他服务的密码出现在这些列表中,你网站上再多的复杂度要求也没用。这就是为什么泄露筛查(Have I Been Pwned 集成)和 MFA 比密码强度规则更重要。
给个人的实用建议:用密码管理器(Bitwarden 免费且开源)。为每个网站生成 20+ 字符的随机密码。用一个好记的短语(4-5 个随机词)作为主密码。所有支持 MFA 的地方都开启,优先选 TOTP 应用而非短信。定期检查 haveibeenpwned.com。接受一个事实:服务被攻破时你需要重置密码——这发生在每个人身上。
给开发者的建议:用 Argon2id 或 bcrypt 哈希。实施泄露筛查。敏感操作要求 MFA。不要发明自己的密码规则——遵循 NIST 800-63B。还有,拜托别再明文存密码了。2026 年没有任何借口。每个框架都有久经考验的认证库。用它。