动态验证码(OTP)生成器

按纯数字、字母数字、Base32 三种字符集批量生成一次性口令;位数与数量可调,种子模式下同一个种子永远得到同一批口令,方便复现与核对,全部计算在本地浏览器完成。

—

本页生成的是演示用随机串:它只按字符集随机取字符,不参与时间步,也不做 HMAC 计算,因此不是 RFC 6238 的 TOTP。真正接入双因素登录的验证码需要服务端与客户端共享同一把密钥、按 30 秒时间步做 HMAC-SHA1 运算,本页不承担这一步。

使用方法

  1. 「字符集」三选一。纯数字只含 0 到 9 共 10 个字符,适合短信与语音这类按键输入的通道;字母数字是 24 个易认字母加 2 到 9 共 32 个字符;Base32 是 RFC 4648 规定的 A 到 Z 加 2 到 7,同样 32 个字符,多用于身份令牌与恢复码。
  2. 「位数」填 4 到 32 之间的整数,默认 6。位数越短越好输入,但组合空间按指数收缩;低于 4 位时页面会直接提示不具备安全性。
  3. 「数量」填 1 到 200 之间的整数,默认 12,用来一次造一批口令。超过 200 条会被拦下,避免误操作生成过大的列表。
  4. 「种子模式」勾选后出现种子输入框,默认 20261014;同一个种子一定得到同一批结果,便于复现与团队核对。取消勾选则改用浏览器加密接口取数,每次结果都不同。
  5. 在任意输入框里按回车即触发生成,不必点按钮;改动字符集、位数、数量或种子模式都会立刻重算。
  6. 结果表按 12 条一屏显示,点「加载更多」每次再展开 12 条;「复制结果」取走整份纯文本清单,「复制对照表」取走制表符分隔的表格,「导出 CSV」下载带 UTF-8 BOM 的文件,可直接用表格软件打开。

这个动态验证码生成器能解决什么问题

密码与验证码常被当成一回事,两者面向的场景并不相同:密码要长期保存、强调抗暴力破解与唯一性;验证码只活几十秒到几分钟、强调一次一换、用完即弃。本页处理的是后者——短信验证码、邮箱验证码、双因素登录里那串短口令,以及测试环境中需要成批造出来的假口令。

批量是它与普通验证码工具的差别所在。开发与测试常常要一次准备几十上百条口令去跑自动化用例,或给一批设备下发激活码;手工敲既不整齐也无法复现。本页把「一批」做成第一类操作:种子一致时,别人照着同一组参数也能得到逐条相同的清单,联调因此有了共同基准。

它同时把「能猜出来吗」这个问题摆到台面上。位数与字符集决定了组合空间的大小,页面用对照表把 10 的幂与 32 的幂并排列出,让使用者先看清量级再决定位数。

计算原理与变量说明

种子模式的核心是一个 32 位线性同余发生器(LCG),每取一个字符前把内部状态推进一格:

三个字符池为什么长度不同。纯数字池就是 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,依次往后。

第 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 长度相同,差别只在收了哪些字符。

字符集池大小包含范围刻意排除适用场合
纯数字100-9无短信、语音、电话按键输入
字母数字32A-Z 与 2-9(24 字母 + 8 数字)I、O、0、1 四个易混字符需要人工抄写又区分大小写
Base3232A-Z 与 2-70、1、8、9 四个数字不区分大小写的令牌与恢复码

下表给出位数与组合空间的关系,纯数字与 Base32 并排对照,数字越大越难被穷举。

位数纯数字 10^nBase32 32^n倍数(约)
41.00e+41.05e+6102 倍
51.00e+53.36e+7336 倍
61.00e+61.07e+91074 倍
71.00e+73.44e+103436 倍
81.00e+81.10e+1210995 倍
101.00e+101.13e+15112590 倍
121.00e+121.15e+181.15e+6 倍
161.00e+161.21e+241.21e+8 倍

下表是常见验证码通道的有效期与重试策略。位数只是组合空间,真正决定安全性的还有它可以被尝试几次、能活多久。

有效期典型通道说明
30 秒TOTP 默认最常用,Google Authenticator 即此
60 秒部分银行容忍时钟漂移,但窗口翻倍
5 分钟短信验证码国内短信常见
10 分钟邮箱验证码邮件延迟大,窗口相应加长
30 分钟密码找回链接一次性链接,用后失效
24 小时邀请码接近长期凭证,更接近静态口令
无期限静态口令不会翻新,不属于 OTP
一次性用后即焚无论剩余有效期,用过即作废
可重试 3 次错误计数超过次数即锁定该账号或该会话
可重试 5 次较宽松策略需配合速率限制与来源校验
滑动窗口 ±1TOTP 容差允许前后各一个时间步,抵消轻微时钟差
滑动窗口 ±2时钟漂移较大可用范围变宽,安全性随之下降

结果边界、舍入与适用说明

常见问题

本页生成的是不是能用 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 次即锁定,这才是安全性的另一半。

这个工具免费吗?

免费,无需注册即可使用。

输入的数据安全吗?

安全。计算在当前浏览器本地完成,不会上传输入内容。

相关工具