什么是密码短语,适合用在哪里
像 "Xk7#mQ2!" 这样的随机字符串很难猜,但也很难记;而像 "password1!" 这样好记的字符串,早就在攻击者的字典里了。 密码短语的做法是把随机抽取的多个单词连在一起(例如 river-castle-thunder-violin),同时兼顾两者。它的强度只取决于三件事:单词表有多大、抽了几个词、是不是真的随机抽取。 如果你按自己的喜好挑出读起来顺口的单词,随机性就没有了,本页的计算也就不再成立。 它最适合需要凭记忆输入的场合:密码管理器的主密码、磁盘加密口令、电脑本机登录。
熵值是怎么算出来的
熵(单位:比特)可以理解为:即使攻击者完全知道生成方式,要确定你的秘密仍需回答多少个"是/否"问题。从N个选项中均匀抽取一个,得到 log2(N) 比特;每多独立抽取一次,就累加同样的量。 本生成器的单词表有100个英文单词,所以每个词贡献 log2(100) = 6.64 比特。经典Diceware的单词表有 7,776 个词(掷5次骰子),每词约 12.92 比特。 这正是本工具与真正Diceware的区别:词数相同时,本工具的强度大约只有Diceware的一半。因此页面允许最多选12个词,并且结果旁边显示的熵值始终按实际单词表大小计算。 另外,追加1位随机数字只增加 log2(10) = 3.32 比特,给很短的短语末尾加个数字帮助有限。
不同单词数的强度表(构建时计算)
| 单词数 | 可能的组合数 | 熵值(比特) | 平均耗时(每秒100亿次) | 平均耗时(每秒1万次) | 对照:7,776词表的比特数 |
|---|---|---|---|---|---|
| 3 | 1.00 × 10^6 | 19.9 | 不到1秒 | 50.0秒 | 38.8 |
| 4 | 1.00 × 10^8 | 26.6 | 不到1秒 | 1.4小时 | 51.7 |
| 5 | 1.00 × 10^10 | 33.2 | 不到1秒 | 5.8天 | 64.6 |
| 6 | 1.00 × 10^12 | 39.9 | 50.0秒 | 1.6年 | 77.5 |
| 8 | 1.00 × 10^16 | 53.2 | 5.8天 | 15,855年 | 103.4 |
| 10 | 1.00 × 10^20 | 66.4 | 159年 | 1.6 × 10^8年 | 129.2 |
| 12 | 1.00 × 10^24 | 79.7 | 1.6 × 10^6年 | 1.6 × 10^12年 | 155.1 |
耗时按"平均试到一半组合就能命中"这一简单假设估算,每秒猜测次数是假设值而非实测。每秒100亿次对应的是:密码文件泄露后,在本地对快速哈希做离线暴力破解;每秒1万次更接近限制尝试次数的在线服务。 实际速度取决于服务端如何保存密码(bcrypt、Argon2这类刻意变慢的哈希会让速度降低几个数量级)、攻击者的硬件以及账号锁定策略。请把这张表当作比较方案的尺子,而不是承诺。
两个验算过的例子
例1:4个单词。 从100个词中抽4个,共 100^4 = 1亿种,约 26.6 比特。平均猜5000万次即可命中,在每秒100亿次的离线攻击下只需不到1秒。 "4个随机单词就够了"这条流行建议是针对7,776词表的(4个词约 51.7 比特),换成小词表就不再成立,所以这里默认选8个词而不是4个。
例2:8个单词。 100^8 = 10^16 种,约 53.2 比特。按表,快速离线攻击平均需要5.8天,受限的在线场景约15,855年。 如果主密码还要抵御离线攻击,建议用10个词(66.4 比特)到12个词(79.7 比特)。以上数字都用Node按同一公式 n × log2(100) 重新算过,与构建时的表一致。
单词如何抽取,以及你的数据去向
每个单词的序号都来自 crypto.getRandomValues,即浏览器内置的加密级随机数发生器;不使用可能被预测、也不是为保密用途设计的 Math.random()。 如果把32位随机数直接对100取余,由于 2^32 不是100的整数倍,排在前面的单词会有极其微小的概率优势。脚本因此采用拒绝采样:超过"不大于2^32的100的最大倍数"的随机值直接丢弃并重抽,使每个单词的概率完全相同。 同一个词可能出现多次,这是正常的:允许重复(有放回抽取)才能让上表的计算精确成立。
脚本中没有任何网络请求、存储调用或日志输出,短语只存在于页面上,刷新或关闭页面即消失。如果浏览器不支持 crypto.getRandomValues,工具会拒绝生成,而不是退回到较弱的随机数。 但它防不住你自己的环境:屏幕共享、旁人偷看、恶意浏览器扩展,或会保留历史的剪贴板工具。复制后请先粘贴到目的地,再复制一段无关内容把它覆盖掉。
常见错误与局限
不满意就重抽。 反复生成几十次再挑最好记的一个,等于悄悄缩小了搜索空间。请直接用第一次的结果,或者干脆多加一个词。手工改单词。 把拗口的词换掉,会让那个位置失去随机性;把 a 换成 @、o 换成 0 这类替换几乎没有增益,因为攻击者最先试的就是它们。到处复用同一个短语。 只要其中一个网站泄露,其他账号全部暴露。重要账号请各用不同的短语,其余交给密码管理器。并不适合所有输入框。 单词是英文小写。有些网站限制长度、拒绝空格或要求大写和符号,这时可以换分隔符,或用密码生成器生成一段较短的随机字符串。本工具只生成英文单词,不生成中文短语。
如何使用生成结果
对于新的主密码,比较现实的做法是:生成后在纸上抄一次,接下来几天对着纸输入,直到手指记住,然后销毁纸条。如果分隔符总让你输错,统一用连字符。 想对已有密码做个粗略评估,可以用密码强度检测器,它按长度和字符类型估算,并不知道你的短语来自单词表。 作为量级参考:从94个可打印ASCII字符中完全随机抽取的8位密码约52.4比特,12位约78.7比特;本工具的8个词(53.2比特)和12个词(79.7比特)分别与之相当。
常见问题
单词数量选多少合适?
100词的单词表每个词约6.64比特。对限制登录尝试次数的普通账号,6到8个词(约40到53比特)可作为下限;对可能遭到离线攻击的密码管理器主密码或磁盘加密,建议10到12个词(约66到80比特)。
为什么默认是8个词而不是4个?
因为单词表很小。从100个词中抽4个只有约26.6比特,离线攻击一秒钟都用不到。"4个词"的经验法则是针对7,776词表的。
生成的密码短语会被保存或上传吗?
不会。脚本在浏览器内运行,没有网络请求和存储,刷新页面后短语就消失。不过复制后它会留在剪贴板里,在共用设备上请事后覆盖。
加数字或大写字母会更安全吗?
一位随机数字只增加约3.3比特;习惯性地把首字母大写几乎没有作用,因为攻击者很早就会尝试这种变化。真正可靠的办法是再多抽一个词,每个词增加6.64比特。
这和Diceware是一回事吗?
思路相同:把随机选出的单词连起来。区别在于Diceware用7,776词的单词表和真实骰子,而本工具用100词的单词表和浏览器的加密级随机数。每个词的强度约为一半,需要靠更多的词数来弥补。