使用方法
- 「字符集」三选一。纯数字只含 0 到 9 共 10 个字符,适合短信与语音这类按键输入的通道;字母数字是 24 个易认字母加 2 到 9 共 32 个字符;Base32 是 RFC 4648 规定的 A 到 Z 加 2 到 7,同样 32 个字符,多用于身份令牌与恢复码。
- 「位数」填 4 到 32 之间的整数,默认 6。位数越短越好输入,但组合空间按指数收缩;低于 4 位时页面会直接提示不具备安全性。
- 「数量」填 1 到 200 之间的整数,默认 12,用来一次造一批口令。超过 200 条会被拦下,避免误操作生成过大的列表。
- 「种子模式」勾选后出现种子输入框,默认 20261014;同一个种子一定得到同一批结果,便于复现与团队核对。取消勾选则改用浏览器加密接口取数,每次结果都不同。
- 在任意输入框里按回车即触发生成,不必点按钮;改动字符集、位数、数量或种子模式都会立刻重算。
- 结果表按 12 条一屏显示,点「加载更多」每次再展开 12 条;「复制结果」取走整份纯文本清单,「复制对照表」取走制表符分隔的表格,「导出 CSV」下载带 UTF-8 BOM 的文件,可直接用表格软件打开。
这个动态验证码生成器能解决什么问题
密码与验证码常被当成一回事,两者面向的场景并不相同:密码要长期保存、强调抗暴力破解与唯一性;验证码只活几十秒到几分钟、强调一次一换、用完即弃。本页处理的是后者——短信验证码、邮箱验证码、双因素登录里那串短口令,以及测试环境中需要成批造出来的假口令。
批量是它与普通验证码工具的差别所在。开发与测试常常要一次准备几十上百条口令去跑自动化用例,或给一批设备下发激活码;手工敲既不整齐也无法复现。本页把「一批」做成第一类操作:种子一致时,别人照着同一组参数也能得到逐条相同的清单,联调因此有了共同基准。
它同时把「能猜出来吗」这个问题摆到台面上。位数与字符集决定了组合空间的大小,页面用对照表把 10 的幂与 32 的幂并排列出,让使用者先看清量级再决定位数。
计算原理与变量说明
种子模式的核心是一个 32 位线性同余发生器(LCG),每取一个字符前把内部状态推进一格:
- 状态初值:
st = seed % 2147483647,若结果为 0 则改成 1,避免退化成全零序列。 - 推进:
st = (Math.imul(st, 1103515245) + 12345) & 0x7fffffff。乘数 1103515245 与增量 12345 是 glibc 一类实现常用的常数;这里必须用Math.imul,直接写st * 1103515245的中间值会超过 2 的 53 次方而丢失低位,得到的是另一条序列。 - 取下标:
idx = Math.floor(st / 2147483647 * len),把整型状态线性映射到0 ~ len-1;越界时回退到len - 1。 - 一条口令推进 len 次:位数是 6 就取 6 个下标,依次拼成一条;下一条口令接着让状态继续走,互不复用同一个中间值。
- 第 k 条换种子:每一批里第 k 条使用种子
base + k - 1,各自从新的初值起步。这样同一批内两条口令彼此独立,而「第几条」本身也是可复现的。
三个字符池为什么长度不同。纯数字池就是 0 到 9 十个字符,任何一位都有十分之一的机会。字母数字池是 24 个字母加 2 到 9 共 32 个,刻意去掉了 I、O、0、1 四个字符:大写的 I 与数字 1、字母 O 与数字 0 在多数字体里几乎无法区分,用户抄错验证码的失败往往就出在这四个字符上,牺牲四个字符的可读性比提高查错成本更划算。Base32 池则是 RFC 4648 的标准字母表 A 到 Z 加 2 到 7,它去掉了容易与字母混淆的数字 0、1、8、9,长度同样是 32,因此常被用在不区分大小写、又需要人手工抄写的令牌场景。
位数决定组合空间。每一位独立均匀取值,总组合数就是池大小的位数次方:纯数字是 10^n,两位 32 池是 32^n。同样位数下 32 池的组合空间约为纯数字的 3.2^n 倍,位数越大差距越悬殊,这就是短信验证码普遍取 6 位数字、而令牌普遍取更长 Base32 串的原因。
种子模式与真随机模式不能混用。种子模式用上面这条 LCG 是为了可复现:同一颗种子在任何浏览器、任何时候都得到同一批口令,适合测试、分享与留痕。真随机模式改用 crypto.getRandomValues,由操作系统的熵源取数,语义上是不可预测、不可复现的。两者目的相反——要复现就选种子模式,要不可猜测就取消勾选。
本页不是 TOTP。RFC 6238 定义的 TOTP 需要三样东西本页都没有:共享密钥、以时间除以时间步(默认 30 秒)得到的时间计数器、用它们做 HMAC-SHA1 再截断的运算。本页只按字符集随机取字符,输出与 Google Authenticator 里滚动的六位数字没有任何关系。判断一个验证码是不是 TOTP,看它会不会在固定周期自动翻新即可。
完整示例(数值仅作演示)
把种子设为 20261014、位数设为 6,前 8 条由页面自身的算法算出;第 k 条用的是种子 20261014 加上 k 减 1,也就是第 1 条用 20261014、第 2 条用 20261015,依次往后。
- 纯数字(池 10):337300、887286、437173、987959、437836、997622、447509、997496。
- 字母数字(池 32):NKZNAA、64ZH5X、NMZDYL、75Z8T9、PNZ4NW、87ZXHK、QPZTC8、982N7V。
- Base32(池 32):MJXMAA、42XH3V、MLXDWK、53X6R7、NMX2MU、65XVHJ、ONXRC6、76YM5T。
第 1 条可以拆开看:种子 20261014 推进六次,映射到 10 个字符的纯数字池时下标序列是 3、3、7、3、0、0,拼成 337300。同样这六次推进映射到 32 个字符的池时下标变成 12、9、23、12、0、0——下标 12 在字母数字池是 N、在 Base32 池是 M,于是分别得到 NKZNAA 与 MJXMAA。两组 32 池下标逐位相同,正是因为池长度相同、映射公式一致;而纯数字池只有 10 个字符,取到的下标自然不同,第一条首位才落在 3 上。
位数、有效期与安全性对照表
下表是三个字符池的构成与适用场合;注意字母数字与 Base32 长度相同,差别只在收了哪些字符。
| 字符集 | 池大小 | 包含范围 | 刻意排除 | 适用场合 |
|---|---|---|---|---|
| 纯数字 | 10 | 0-9 | 无 | 短信、语音、电话按键输入 |
| 字母数字 | 32 | A-Z 与 2-9(24 字母 + 8 数字) | I、O、0、1 四个易混字符 | 需要人工抄写又区分大小写 |
| Base32 | 32 | A-Z 与 2-7 | 0、1、8、9 四个数字 | 不区分大小写的令牌与恢复码 |
下表给出位数与组合空间的关系,纯数字与 Base32 并排对照,数字越大越难被穷举。
| 位数 | 纯数字 10^n | Base32 32^n | 倍数(约) |
|---|---|---|---|
| 4 | 1.00e+4 | 1.05e+6 | 102 倍 |
| 5 | 1.00e+5 | 3.36e+7 | 336 倍 |
| 6 | 1.00e+6 | 1.07e+9 | 1074 倍 |
| 7 | 1.00e+7 | 3.44e+10 | 3436 倍 |
| 8 | 1.00e+8 | 1.10e+12 | 10995 倍 |
| 10 | 1.00e+10 | 1.13e+15 | 112590 倍 |
| 12 | 1.00e+12 | 1.15e+18 | 1.15e+6 倍 |
| 16 | 1.00e+16 | 1.21e+24 | 1.21e+8 倍 |
下表是常见验证码通道的有效期与重试策略。位数只是组合空间,真正决定安全性的还有它可以被尝试几次、能活多久。
| 有效期 | 典型通道 | 说明 |
|---|---|---|
| 30 秒 | TOTP 默认 | 最常用,Google Authenticator 即此 |
| 60 秒 | 部分银行 | 容忍时钟漂移,但窗口翻倍 |
| 5 分钟 | 短信验证码 | 国内短信常见 |
| 10 分钟 | 邮箱验证码 | 邮件延迟大,窗口相应加长 |
| 30 分钟 | 密码找回链接 | 一次性链接,用后失效 |
| 24 小时 | 邀请码 | 接近长期凭证,更接近静态口令 |
| 无期限 | 静态口令 | 不会翻新,不属于 OTP |
| 一次性 | 用后即焚 | 无论剩余有效期,用过即作废 |
| 可重试 3 次 | 错误计数 | 超过次数即锁定该账号或该会话 |
| 可重试 5 次 | 较宽松策略 | 需配合速率限制与来源校验 |
| 滑动窗口 ±1 | TOTP 容差 | 允许前后各一个时间步,抵消轻微时钟差 |
| 滑动窗口 ±2 | 时钟漂移较大 | 可用范围变宽,安全性随之下降 |
结果边界、舍入与适用说明
- 位数取 4 到 32 的整数,数量取 1 到 200 的整数;位数低于 4 会提示「低于 4 位不具备安全性」,数量超过 200 会提示「批量生成上限 200 条」。
- 种子取 1 到 2147483640 的整数;填 0 会被内部改成 1,页面因此直接拦截 0 与负数。上限受 2147483647 取模限制,再大的种子可能映射到同一个初值。
- 种子模式的结果是伪随机而非真随机:序列在数学上可预测,只适合测试、演示与需要复现的场景;用于真实凭据时应改用真随机模式。
- 字母数字与 Base32 两池都是 32 个字符,因此同批同位数下两者取到的下标序列逐位相同,结果看起来「同步」,这是池长度相同造成的。
- 位数与字符集只决定空间大小,不决定是否安全。真实系统还必须有有效期、错误次数与速率限制。
- 本页输出纯文本口令,不含校验位、时间戳与设备绑定信息。
- 生成全部在当前浏览器完成,输入与结果都不上传服务器。
常见问题
本页生成的是不是能用 Google Authenticator 扫的验证码?
不是。Google Authenticator 走的是 RFC 6238 的 TOTP,它需要共享密钥、以 30 秒为时间步、并用 HMAC-SHA1 运算后截断;本页只按字符集随机取字符,两者互不通用。
为什么字母数字字符集要去掉 I、O、0、1?
这四组是多数字体里最容易混淆的:大写 I 与数字 1、字母 O 与数字 0 几乎一样,用户抄错验证码大多出在这里。去掉它们牺牲 4 个字符,却显著降低输入错误,是可用性的经典取舍。
同样是 6 位,为什么 Base32 比纯数字安全得多?
因为每一位的取值空间不同。纯数字每位 10 种,6 位合计 1.00e+6 种;Base32 每位 32 种,6 位合计 1.07e+9 种,相差 1074 倍。位数不变而每位的字母表变大,组合空间按指数增长。
种子模式下为什么两次结果完全一样?
这是刻意的。内部状态由种子唯一决定,之后每步都用固定的乘数与增量推进,种子不变序列就不变。好处是可复现可分享:把种子与参数贴给别人,对方得到逐条相同的清单。
什么时候该取消「种子模式」?
当你希望口令不可被预测、不可被复现时。种子模式为了可复现放弃了不可预测性,任何人都能照着公式重算出同一条口令;真实凭据场景应取消勾选,改用真随机。
位数选 6 位纯数字,只靠位数够安全吗?
不够。6 位纯数字只有 100 万种组合,若没有次数限制,在线系统可以被逐条尝试。真实 OTP 必须叠加有效期与错误次数限制,常见做法是 5 分钟有效、错误 3 到 5 次即锁定,这才是安全性的另一半。
这个工具免费吗?
免费,无需注册即可使用。
输入的数据安全吗?
安全。计算在当前浏览器本地完成,不会上传输入内容。