密码需要强到什么程度
对于一个你不愿意丢掉的账户,请使用至少 16 个字符的随机生成密码,或者至少 5 个随机挑选的单词组成的口令短语,并且只在一个网站上使用它。那相当于 65 到 95 位的熵,远远超出暴力破解的能力,而“只在一个网站上使用”这一点比强度本身更要紧。下面是这些数字背后的道理。
以比特计的熵
熵衡量的是这个密码是从多少种等可能的可能性中抽出来的,以 2 的幂来表示。40 位的熵意味着 2^40 种可能性之一,大约一万亿种,而每多一位就让猜中它的工作量翻倍。公式是“比特数 = 长度 x log2(字符集大小)”,所以小写字母每个值 4.7 位,字母加数字每个值 5.95 位,全部可打印 ASCII 每个值 6.57 位,而从一份 7776 词的词表里取的一个单词值 12.9 位:
| 密码 | 熵 |
|---|---|
| 8 个小写字母 | 38 位 |
| 12 个字母和数字 | 71 位 |
| 12 个字符,完整 ASCII | 79 位 |
| 16 个字母和数字 | 95 位 |
| 5 个随机单词 | 65 位 |
| 6 个随机单词 | 78 位 |
只有当密码确实来自一个真正的随机过程时,这套算术才成立。Tr0ub4dor&3 是从 95 个字符的集合里取的 11 个字符,公式给它算出 72 位,但它其实是一个做了可预测替换的词典单词,破解工具会远远更早地够到它。熵描述的是生成器,不是那个字符串。
这些比特能换来什么
猜测速度取决于网站是怎么存储密码的。面对一个带速率限制的在线登录表单,攻击者每小时只能试几次。面对一个被盗的数据库,则取决于散列算法:像 MD5 或 SHA-1 这样的快速算法,在消费级显卡上能以极高的速率尝试,而 bcrypt 或 Argon2 这类专为密码设计的散列算法要慢上好几个数量级。
下面是最坏的情况,假设是一个不加盐的快速散列,每秒一百亿次猜测。它展示的是这条曲线弯得有多陡,而不是一次实测:
| 熵 | 穷尽整个空间所需时间 |
|---|---|
| 40 位 | 大约两分钟 |
| 50 位 | 大约一天 |
| 60 位 | 几年 |
| 70 位 | 几千年 |
| 80 位 | 数百万年 |
平均而言攻击者在这个时间的一半时就会成功。实用的读法是:低于 50 位对离线攻击没什么价值,60 到 70 位对多数场景够用,80 位以上则会一直宽裕。
长度胜过符号堆砌
拿一个由字母和数字组成的 12 字符密码(71 位)。加上标点,把字符集从 62 个扩到 95 个,你得到 79 位。而改成再多加两个字母或数字,你得到 83 位。每多一个字符,搜索空间就乘上整个字母表,而扩大字母表只给你已有的每个字符增加大约 0.6 位。长度赢,而且一直赢。
组成规则(“必须包含一个大写字母、一个数字和一个符号”)把人们逼进了一小撮固定的模式:大写字母放开头,数字和感叹号放结尾。破解工具最先尝试的就是这些变换。这是 NIST 的数字身份指南从组成规则和强制定期更换转向长度要求、并转向比对已泄露密码列表的原因之一。
重复使用才是真正的风险
几乎没有人的账户是被暴力破解攻破的。真实发生的是撞库:某个薄弱的网站被攻破,邮箱和密码的组合被公开,自动化工具再拿每一组去试其他几百个服务。如果你在邮箱上用的密码和那个被攻破的论坛一样,它的强度就无关紧要了。它是被交出去的,不是被猜到的。
钓鱼的原理一样:一个 30 个字符的密码,被输进一个足以乱真的假登录页,价值和 password1 完全相同。所以,按重要性排序:
- 每个网站用不同的密码。
- 对任何重要的东西启用双因素认证,首先是你的邮箱,因为它是其他一切的重置途径。
- 长度足够,让离线破解毫无希望。
口令短语
口令短语是从一份词表里随机挑出的若干单词,例如 harvest-cobalt-mural-drift-plinth。按每个词 12.9 位算,五个词是 65 位,六个词是 78 位。
有两个条件让它成立。这些单词必须是随机选出来的,用骰子或者软件,而不是由你挑。而且强度来自单词的数量,不来自分隔符,也不来自把某个字母改成大写:一句歌词或者一句引言几乎没有熵,因为它是从一个很小的“人们会说的话”的池子里抽出来的。
对于少数几个你要凭记忆输入的密码,口令短语最有价值:设备登录密码、密码管理器的主密码、磁盘加密密码。
密码管理器的位置
密码管理器把“发明并记住 200 个不重复的密码”变成了“记住一句长口令短语”。它会生成高熵字符串,并在正确的域名上替你填入,这钝化了钓鱼攻击,因为它不会在一个看起来相像的地址上自动填充。
它把风险集中到了一处,这是一个真实存在的反对意见,但它仍然是更划算的交易:一个由长口令短语加第二因素守着的密码库,胜过一个在几十个质量不明的网站间共用的密码。
关于散列的一点说明
散列是登录的另一半。一个建得好的服务会用一种刻意做慢的算法存储加盐散列,绝不存密码本身,这样泄露之后不会立刻得到明文。SHA-256 这类通用散列算法就是为快而生的,这让它们非常适合做文件校验和,却是存储密码的糟糕选择。把你自己的密码散列一下来“让它更强”什么也做不到:结果的不可猜测程度,只等同于输入的不可猜测程度。