使用方法
- 在「密码长度」填 20(示例值),允许 8~128 的整数;在「生成数量」填 5(示例值),允许 1~50 条。
- 字符类型默认四类全勾:大写字母、小写字母、数字、常用符号。某个网站不收符号时,取消勾选「常用符号」即可,不必自己删。
- 保持「排除易混淆字符」勾选,工具会把
0 O o 1 I l这 6 个字符从字符池里剔除,后续人工抄写不容易看错。 - 个别站点要求必须出现
~、·这类特殊符号时,把它们填进「自定义附加字符」,最多 50 个字符,会原样拼进字符池。 - 点「生成安全密码」(或在长度、数量输入框里直接按 Enter),结果区出现 5 条密码;点「复制全部」一次带走,或点「下载 .txt」存成文本文件。
这个密码生成器能解决什么问题
一是批量初始化:给一批设备、一批测试账号设置初始口令时,一次生成 50 条互不相同的结果,逐条分配即可,不用手工编造再逐个核对。
二是绕开网站的组成校验:很多站点注册时会检查「必须同时包含大写字母、小写字母和数字」,纯随机抽字符经常抽不出数字而被退回。本工具先按你勾选的每一类各抽一个字符,再补足到指定长度,所以生成结果天然满足组成要求,不用反复重抽。
三是给人工转录兜底:需要把密码抄到纸上、贴到设备铭牌或读给同事时,排除易混淆字符后,O 与 0、l 与 1、I 不再同时出现,抄错概率明显下降。
四是生成一次性短串:接口 token、临时口令、设备配对码这类一次性用途,直接用「自定义附加字符 + 短长度」生成即可,用完即弃。
本页不做这些事:不保管密码(不写入浏览器存储,也不发送到服务器)、不给已有密码打分、不检查密码是否出现在历史数据泄露库里。要评估一条现有密码被猜中的难易,请用页面底部的「密码力量检测」;想反算一条密码的字符池与信息量,请用「密码熵值计算器」。
生成原理:加密随机数、拒绝采样与 68 位字符池
这个密码生成器的随机来源只有一行代码:crypto.getRandomValues(new Uint32Array(1))。它是浏览器内置的加密随机数接口(W3C Web Cryptography API 定义),并不引入任何第三方随机库,所以你拿到的每一位都来自操作系统熵池,而不是 Math.random() 那种可预测的伪随机序列。
关键一步是拒绝采样。拿到一个 32 位无符号整数后,不能直接写 n % 68 去取字符下标——因为 232 = 4294967296 不能被 68 整除,余数 0~51 会比余数 52~67 多出现一次,分布出现微小但真实的偏斜。工具的实际做法是先算接受上限 Math.floor(4294967296 / 68) * 68 = 4294967244,随机数落在 4294967244~4294967295 这 52 个取值上就丢弃重抽。丢弃比例约 0.0000012%,接受率 99.9999988%,代价几乎为零,但换来了严格均匀的分布。洗牌用的是 Fisher–Yates 算法,从最后一位往前遍历(for(i=a.length-1;i>0;i--) 再与 rand(i+1) 交换),而不是常见的 sort(()=>Math.random()-0.5)——后者在多数引擎里会退化成偏差明显的伪洗牌。
字符池为什么是 68 位。四类字符的字面量本身已经做过预剔除:大写去掉了 I 和 O,剩 24 个;数字去掉了 0 和 1,剩 8 个;小写 25 个、符号 12 个(符号集里本来就没有这 6 个字符)。所以勾选「排除易混淆字符」时,池 = 24 + 24 + 8 + 12 = 68 位;取消勾选时,唯一的变化是小写里的 o 回来了,池 = 69 位。很多用户以为勾不勾差很多,实际只差一个字符。
长度和组成建议的标准依据。NIST SP 800-63B《Digital Identity Guidelines》对口令长度给出的最低要求是 8 位,并明确不建议强制「必须含大小写、数字、符号」这类组成规则——它更看重长度和唯一性。本工具把组成做成「每类先各抽一个」是为了兼容那些仍在校验组成的网站,而不是说组成规则本身能提高安全性。
完整示例(数值仅作演示)
示例条件与页面打开时的默认值完全一致:长度 20 位、数量 5 条、四类字符全勾、勾选「排除易混淆字符」,即字符池 68 位。
- 按
6820这个理想上界算,单条取值空间约 4.47×1036 种; - 由于工具强制「每一类至少出现一次」,真实取值空间要小一点,精确值是 4.01×1036 种,两者只差 0.15 bit;
- 单条信息量(熵)为 121.6 bits(简单估算式 20 × log268 = 121.7 bits,扣除约束后 121.6);
- 假设攻击者每秒能试 1012 条,穷举单条需要 1015 年以上;
- 5 条结果互不相同的概率约
1 − 10 / 4.01×1036,实际就是 100%。
下面这一组就是默认条件下真机生成的结果,仅作排版演示——你点一次「生成安全密码」得到的会是完全不同的内容:
Db+t@gnK88!zsLZUhur! YFbJ-kJ!DKw@bvx8TwL+ ^phT4wb8wYH#7!9LmZMV UTYfeUYXSS9Z*e76K_A! Yh%sziF2$7TrK@Q5wTKn
长度档位、字符池与穷举成本对照表
下表固定字符池为 68 位(默认条件),逐档实测;「精确取值空间」是扣除「每类至少出现一次」约束后的真实值,也是页面统计条里显示的那个数。
| 密码长度 | 理想空间 68n | 精确取值空间 | 单条熵 | 每秒 1012 次穷举 |
|---|---|---|---|---|
| 8 位 | 4.57×1014 | 2.00×1014 | 47.5 bits | 1.7 分钟 |
| 12 位 | 9.77×1021 | 6.70×1021 | 72.5 bits | 106.2 年 |
| 16 位 | 2.09×1029 | 1.72×1029 | 97.1 bits | 2.72×109 年 |
| 20 位(默认) | 4.47×1036 | 4.01×1036 | 121.6 bits | 1015 年以上 |
| 32 位 | 4.37×1058 | 4.28×1058 | 194.8 bits | 1015 年以上 |
长度每增加 1 位,取值空间乘以 68,也就是多 6.09 bit。下表则固定长度为 8 位,只改勾选的字符类型,用来看「少勾几类会损失多少」:
| 勾选的字符类型(长度固定 8 位) | 字符池 | 精确取值空间 | 单条熵 | 每秒 1012 次穷举 |
|---|---|---|---|---|
| 只勾「数字」 | 8 位 | 1.68×107 | 24.0 bits | 不到 1 秒 |
| 只勾「小写字母」 | 25 位 | 1.53×1011 | 37.2 bits | 不到 1 秒 |
| 只勾「大写 + 小写」 | 48 位 | 2.80×1013 | 44.7 bits | 14.0 秒 |
| 勾「大写 + 小写 + 数字」 | 56 位 | 6.66×1013 | 45.9 bits | 33.3 秒 |
| 四类全勾 + 排除易混淆 | 68 位 | 2.00×1014 | 47.5 bits | 1.7 分钟 |
| 四类全勾 + 不排除易混淆 | 69 位 | 2.22×1014 | 47.7 bits | 1.8 分钟 |
两张表放在一起看就明白了:加长度比加字符类型划算得多。从 4 类降到 2 类只损失 2.8 bit,而长度从 8 位加到 20 位多出 74 bit。
输入范围、边界与精度说明
下面这些不是「限制」,而是刻意设定的边界,知道它们能避免你把这页当万能工具用:
- 长度 8~128 的整数。小于 8 会被拒绝:8 位纯数字只有 24.0 bit 熵,按每秒 1012 次算不到 1 秒就能穷举完。大于 128 多数业务系统的口令字段存不下,页面上限与常见实现保持一致。
- 数量 1~50。数量只决定一次输出几条,不改变任何一条的强度——生成 50 条 20 位密码,和第 1 条一样安全。上限设 50 是防止一次把 DOM 撑得太大。
- 「每一类至少出现一次」永远成立,不需要你操心。长度下限是 8 位,而字符类型一共只有 4 类,8 已经大于 4,所以在允许范围内这个约束一定满足——工具里仍留了一句兜底判断,万一以后把长度下限调到 4 以下,它会立刻报错而不是悄悄把某一类丢掉。
- 自定义附加字符最多 50 个。会原样拼进字符池;若同时勾着「排除易混淆字符」,你自定义内容里的
0 O o 1 I l也会被一并剔除。 - 字符池与去重后的位数是两回事。统计条里的「字符池」是拼接后的总长度;如果自定义字符与内置字符重叠,去重后的位数会少几位。熵和取值空间按去重后的位数计算,所以不会因为你多填几个重复字符而虚高。
- 首屏那 5 条「示例展示」不是随机生成的,只是写在 HTML 里的固定演示文本,用来告诉你输出长什么样。点一次「生成安全密码」之后显示的才是真正来自
crypto.getRandomValues的结果。 - 熵衡量的是「猜中的难度」,不等于「绝对安全」。如果密码被钓鱼、被键盘记录、被截屏,或者你在多个站点重复使用同一条密码,再高的熵也挡不住。
常见问题
为什么默认就勾上「排除易混淆字符」?
因为这条密码大概率要经过人工环节:抄到纸上、念给同事、输入到没有复制粘贴功能的设备上。0 与 O、1 与 l 与 I 在不少字体里几乎一样,排除后仍保留 68 位字符池,强度损失可以忽略。
勾选和不勾选「排除易混淆字符」,到底差多少?
只差一个字符。内置的大写字母表已经去掉了 I、O,数字表已经去掉了 0、1,符号集里也没有这 6 个字符,所以勾选与否的唯一区别就是小写字母里那个 o:池从 69 位变成 68 位,8 位长度的熵从 47.7 bit 降到 47.5 bit。
网站要求「必须包含数字」,工具会自动满足吗?
会。生成时先给每个已勾选的类型各抽一个字符,再补足长度并整体洗牌,所以结果里每一类都至少出现一次,数字一定在。但如果你只勾了「数字」一类,那结果就是纯数字——满足组成要求不等于安全,长度才是主要变量。
为什么不用 Math.random()?
它是为了速度和统计分布设计的伪随机,内部状态有限且可推导,观察到足够多的连续输出后能预测后续结果,不适合生成凭据。crypto.getRandomValues 由 W3C 规范定义、取自操作系统熵源,是专门给密码学场景用的接口。
生成的密码会上传或保存到服务器吗?
不会。随机数来自浏览器接口,拼接和洗牌都在当前页面完成,没有任何网络请求。想自己验证,打开开发者工具的 Network 面板,点几次「生成安全密码」,可以看到没有任何新请求发出。
自定义的附加字符会去重吗?会重复出现吗?
不会去重——你填什么就按原样拼进池里,重复填同一个字符不会让它更容易被抽中多少(它在池里占几个位置就按几个位置参与抽取)。另外,同名站点要求的字符若恰好是 _、-、@ 这些,本就已经在「常用符号」里,不填也一样会出现。
一次生成 50 条会不会重复?可以生成更多吗?
20 位默认条件下两条完全相同的概率约为 1 / 4.01×1036,实际可以认为不会重复。单次上限是 50 条,超过的批量需求建议分几次生成——每次点按钮都是一次全新的抽取,批次之间同样不会重复。
「复制全部」复制出来的是哪几条?
就是结果区里当前显示的那几条,一行一条,不含任何说明文字和编号,可以直接粘进表格或配置文件的对应位置。复制后请尽快存进可信的密码管理器;浏览器剪贴板历史、录屏软件和同步输入法都可能读到剪贴板内容。