# 密码与密码短语 — 强随机，在你的浏览器里生成

在这里生成，由你自己的浏览器生成，不发往任何地方。什么都不保存，也没有历史记录。

> 生成一个强随机密码，或者用页面自带的 7776 个词的词表生成一条 diceware 密码短语。由浏览器自身的加密随机数生成，不发往任何地方，也不保存。免费，不用注册。

这是一个浏览器交互工具，地址是 https://abox.tools/zh/password-generator/。文件在运行该浏览器的设备上处理。主动分享和可选联网功能都在页面上说明。下文是它的文字说明；使用工具请打开该地址。

## 你的密码和密码短语**在浏览器里处理**，无须上传处理。

每一个字符都来自 `crypto.getRandomValues`，也就是浏览器自带的加密随机数，每一个词都来自这个文件夹里的 `src/wordlist.js`。`src/` 里没有 `fetch`，没有 `XMLHttpRequest`，也没有 `sendBeacon`，所以在这里生成的密码没有任何路径能到我们这儿，也到不了别人那儿。这里也不保存，刷新一下页面，它给你看过的密码就全没了。

- ✗ 不上传
- ✗ 不用账号
- ✗ 不保存
- ✓ 离线可用
- ✓ 源码公开

## 怎样生成一个强密码，还不让任何网站看到

1. **先选密码还是密码短语。** 密码是一串随机字符：存起来短，敲起来麻烦，正好适合那几百个由密码管理器替你填的账号。密码短语是从词表里随机抽出来的一串词：长一些，但记得住、念得出，这正是那几个必须你自己从脑子里敲出来的秘密所需要的，比如密码管理器自己的密码、笔记本电脑的密码、手机的恢复码。
2. **定长度，或者定词数。** 这才是那个要紧的设置，其余的大多不是。值得保护的东西，20 个字符或者六个词是个合理的下限；那个能把其他所有密码都重置掉的账号，就从这里往上加。下面的读数会跟着你拖动一起变，所以多一个字符换来什么，你当场就能看见。
3. **把注册表单会较劲的规则打开。** “每类至少一个”、末尾一个数字、一个哪个网站都收的短名单里的符号。这些都不会让密码更强，第一个甚至让它稍微弱了一点，而这一点页面已经替你减掉了。但要不来回生成六个就通过注册表单，靠的就是它们。
4. **看数字，别看颜色。** 比特数是从生成这串字符的设置里数出来的：字符集有多大，抽了多少次，就这些。这是一次真正的测量，跟注册页上那根条不一样。那根条只能给眼前的字符打分，没有办法知道这些字符是你选的还是生成器选的。
5. **走之前先复制，先放好。** 这里没有历史记录，也没有办法再要回来，刷新页面它就没了。先粘进密码管理器，再粘进注册表单，让需要记住它的那一头先拿到手，中间出什么岔子都不怕。
6. **要一批就一次生成一批。** 最下面那个滑块一次最多生成一百个，还能存成纯文本文件，内容就是页面从你屏幕上已有的东西写出来的。批量开账号或者发初始口令时好用，等它们进了更合适的地方，这个文件就该删掉：硬盘上一个装满密码的文件，仍然是一个装满密码的文件。

## 说得更细的版本

[用在线密码生成器安全吗？](https://abox.tools/zh/guides/is-it-safe-to-use-an-online-password-generator/): 这份疑心是对的，值得认真对待：浏览器的随机数从哪儿来，一个生成页面可能错在哪儿，以及哪些检查能看出眼前这个页面留没留它造出来的东西。

## 工具箱里还有

- [JSON 格式化](https://abox.tools/zh/json-formatter/): JSON、XML、HTML、CSS 和 YAML，格式化或转换。没有一个字被贴进别人的服务器。
- [YAML 转 JSON](https://abox.tools/zh/yaml-to-json/): 两个方向都有，而且会告诉你各自的代价。这些都不会粘进别人的服务器。
- [XML 格式化](https://abox.tools/zh/xml-formatter/): 排开了好读的 XML，压平了好发的 XML，还有两个方向的 JSON 转换。这些都不会粘进别人的服务器。
- [文本比对](https://abox.tools/zh/text-diff/): 两段文本进来，每处差异都被标出来，逐行、逐词。没有一个字被贴进别人的服务器。

## 常见问题

### 密码会被发到什么地方，或者被保存下来吗？

密码在这个浏览器里生成，工具代码不上传密码，也不保存密码历史。复制或保存由你选择。共享页面框架可以保留本地偏好和临时语言切换设置，但不包含生成的密码输出。CSP 限制目的地，不能证明已允许请求的内容。请读代码并检查操作的流量。

### 随机数是从哪儿来的？

来自 `crypto.getRandomValues`，浏览器为密码学用途提供的随机数，由你自己操作系统的熵池播种并不断重新播种。浏览器取 TLS 密钥材料用的也是同一个来源。这个工具里任何地方都没有用 `Math.random`，这个区分不是抠字眼：`Math.random` 是一个很快的算术随机数，它的整个内部状态能从连续几个输出里还原出来，建立在它上面的密码生成器产生的密码只是看起来随机，任何见过其中一个的人都能把其余的全部列举出来。

### 浏览器里生成的密码，和装在电脑上的程序生成的一样好吗？

就随机数而言是一样的，两边都是操作系统的同一个来源，只是走的门不同。不同的是屋子里还有谁。浏览器标签页是和你的扩展一起运行的，一个有权限读页面的扩展也能读这一页。这对任何网页上的生成器都成立，包括这一个，也正是“手边有密码管理器时就用它自带的生成器”这条建议的诚实理由：算术是一样的，只是那个进程旁边站的人少。这个页面是给你手边没有它的时候用的。

### 密码还是密码短语，到底该用哪个？

凡是密码管理器替你敲的，都用密码，因为你根本不会去看它，而长度在那里是白送的。那几件必须你自己从脑子里敲出来、或者念给别人听的，用密码短语：管理器的主密码、磁盘加密的密钥、一台你远程配置的设备。长词表里六个词是 77 比特，比十二个字符的随机密码还强，而且凌晨四点也能一次输对，这一点差得不是一星半点。

### 密码该有多长？

全字符集下 20 个字符大约是 130 比特，早就过了还需要担心长度的那个点。16 个也很够。12 个是任何你不想丢的东西的下限，而且是下限，不是目标。再短，你就是在赌那个网站把它妥善存了起来，而过去二十年的泄露通知劝你别赌。长度胜过这个页面上任何别的设置：多一个字符，比任何关于必须包含哪些字符的规则都管用。

### 密码短语该用几个词？

长词表里六个词，如果它守着别的密码就七个。那张著名的四个词的图是 2011 年画的，值 51 比特，今天已经在一次认真的离线攻击的射程之内。五个词是 64，六个词是 77，超过了攻击者会为一个普通账号花的代价。长词表里每多一个词就多 12.9 比特，而且只有词在往上加，连字符和大写字母都不加。

### 什么是“比特”，这个页面为什么要数它？

一个比特就是翻一倍。60 比特的意思是，这个页面本来可能产生的、概率相同的结果有 2^60 种，所以就算有人完全清楚它是怎么工作的，也还是有这么多要试。这是*过程*的性质，不是这串字符的性质：页面能把它说准，是因为选的人就是它，它知道自己选了多少次。这就是它和注册表单上那根彩色条的区别，那根条只是读了字符然后猜。在那根条上，`correct horse battery staple` 评分很差，实际值 44 比特；`P@ssw0rd!` 评分很好，实际几乎一文不值。

### 为什么“必须包含一个符号”反而让密码变弱？

因为规则只能拿走可能性。要求每一类至少出现一个字符，就把所有恰好没抽到的密码全排除掉了，而可能的密码这个集合越小，要搜的范围也越小。影响不大，常见长度下大约半个比特，但它是真实存在的，而这个页面把它减掉了，没有去报那个对自己更好看的数。而且是精确算出来的：数的是这条规则真正允许的密码，而不是它排除掉的。

### 这是哪个词表，攻击者能下载到它要紧吗？

是电子前哨基金会（EFF）的 diceware 词表，原样打包进来：长的 7776 个词，短的 1296 个。它们本来就是为这件事做的：没有冒犯性的词，没有同音词，没有连起来会变成第三个词的组合，短表里也没有哪个词是另一个词的开头。至于词表是公开的，不要紧：这里给出的强度本来就假定攻击者手里有这份表，正在读这个页面的源码，还知道你用的每一项设置。他唯一不知道的，是每一次抽中的是 7776 个里的哪一个。正是这个假定，让这个数字值得信。

### 密码短语不就是等着被字典攻击吗？

按这种方式选词就不是。字典攻击对付的是*人*想出来的短语，因为人挑的词彼此搭调、顺序讲得通，而且来自自己每天用的那几千个词。这个页面是从一份固定的词表里，一个词一个词独立地、均匀地抽，完全不管结果读起来顺不顺，所以它通常读起来并不顺。一个知道词表也知道词数的攻击者，面前仍然是 7776 的词数次方。

### 离开页面之后还能把密码找回来吗？

找不回来，而且是故意的。任何地方都没记下来，所以没有什么可找的：没有历史面板，没有“最近生成”列表，也没有缓存。一个能把上周二的密码翻给你看的生成器，就是一个把它存下来了的生成器，而存在你够得着的地方，也就是存在别的东西够得着的地方。离开之前先复制到密码管理器里。

### 复制到剪贴板安全吗？

这是常见的那一类风险，知道它比担心它有用。剪贴板和所有以你身份运行的程序共享，通常会留到你下一次复制，有些配置下还会在设备之间同步。所以该粘的地方立刻粘，粘完再随便复制点别的，这是好习惯；但这不构成改用手敲一个更弱密码的理由。这个页面读不到你的剪贴板，它只能往里写，而且只在你按下按钮的时候写。

### 同一个能在多个地方用吗？

不能，而这是这个页面上唯一一条压过其他所有建议的建议。几乎每一个被盗的账号，用的都是先在别处对过的密码：某个网站被攻破，名单被公开，同样的邮箱配同样的密码被拿到各处去试。一个网站一个密码，能把一次泄露变成一个账号而不是全部，这才是值得用密码管理器的理由，而不是它里面某一个密码有多强。

### 免费吗？要注册账号吗？

免费，没有账号，不用登录，没有试用期，生成多少个都不限。网站靠广告养着，而广告拿不到关于这个页面生成的东西的任何信息，长度和强度都拿不到。

### 离线能用吗？

能。把页面加载一次，然后断开网络，它照样生成密码。随机数来自你自己的设备，词表本来就在页面里。这也是证明它既没在取什么、也没在发什么的最简单办法：一个要向服务器要数字的生成器，在你拔线的那一刻就会停下来。

## 这条隐私承诺怎么核实

- **处理在这个浏览器里完成。** 它在这个页面里，由这个页面，从你自己的操作系统交给浏览器的随机数中抽出来。生成它不需要去取任何东西，生成完也不会上报任何东西。`Content-Security-Policy` 里写着这个页面允许连接的每一个地址，没有一个是我们的。这里没有一个可以收集生成出来的密码的落点，就算有，代码里也没有把它送过去的那一行。
- **这里没有任何东西会去取东西。** `src/` 里没有 `fetch`，没有 `XMLHttpRequest`，也没有 `sendBeacon`。词表不是下载来的，它就是 `src/wordlist.js`，跟页面其他部分一起从这个源下发，你可以打开来看。
- **随机数是浏览器的，而且是对的那一种。** `crypto.getRandomValues` 是浏览器为密钥和令牌提供的随机数，由操作系统播种，并且不断重新播种。`Math.random` 在这个文件夹里一次都没有出现过，出现了才是真正的缺陷：它的内部状态能从几个输出里还原出来，谁看过它产生的一个密码，就能算出它以后会产生的每一个。
- **什么都不保存，所以没有历史记录要清。** 没有 localStorage，没有 sessionStorage，没有 Cookie，没有 URL 参数，也没有浏览器会主动提出记住的 `<input>`。屏幕上的东西只活在这个页面内存里的一个数组中，关掉标签页就是全部的清理。这里生成的东西，只有你带走的那些副本。
- **谷歌加载了什么，又拿不到什么。** 广告和统计脚本来自谷歌，捐赠按钮来自 Buy Me a Coffee。它们谁都拿不到这个页面生成的任何一个字符，也拿不到长度、强度，以及是用哪些设置生成的。每一行抽取字符或词的代码都从这个源下发，都在仓库里。
- **它离线可用。** 断开网络，这个工具一点没变，因为它里面从来就没有过一步联网。这是最简单的证明：一个要向服务器要随机数的生成器，在你拔线的那一刻就会停下来。

**你可以自己核对。**上面这些不用你信。这个页面是仓库里的模板和配置生成出来的，构建脚本你能读，也能自己跑一遍，跑出来的结果就提交在 `dist` 分支上。拿实际发给你的内容，跟你自己从源码构建出来的结果对一遍就知道了： https://github.com/A-Box-of-Tools/website

最值得先读的几个文件：`config/site.toml` 里是 Content-Security-Policy，`src/random.js` 是这个页面和它生成的每一个密码之间的那四十行，它只有一个输入，就是浏览器自己的随机数；`src/generate.js` 是设置怎么变成一串字符；`src/strength.js` 是那个数字背后的算术，它是在数，不是在猜。
