2FA 验证码生成器(TOTP)
输入 Base32 密钥或粘贴 otpauth:// URI,在线生成 2FA 动态验证码(RFC 6238 TOTP)。已用 RFC 测试向量核对;密钥只在当前页面内存里,不保存、不进网址。
- 在浏览器中处理
- 数据不离开你的设备
- 免费 · 无需注册
用微信扫描以下二维码即可分享
示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。
验证码的算法是 RFC 6238 的 TOTP:先算 T = floor(Unix 时间 / 周期),再对 T 做 RFC 4226 的 HOTP(HMAC 加动态截取)。
场景:阿里云虚拟 MFA 手动添加后验证码不对
阿里云帮助中心的RAM 用户自行绑定 MFA 设备写了两种添加方式:扫码添加,或者「手动添加」,即把绑定页面上的账号和密钥抄进阿里云 App 或 Google Authenticator。手动抄写时错一个字符,App 照样会显示 6 位数,但服务端永远不认。
这时把绑定页上的同一串密钥粘到本工具里:
- 和 App 在同一个 30 秒里显示的数字不同:说明 App 里那份密钥抄错了。工具会直接指出非法字符,例如密钥里出现
1、0、8、9(Base32 字母表里没有这四个数字,多半是把 I、O、B 看错了)。 - 数字相同,控制台还是提示安全码错误:看时钟。阿里云的 MFA 常见问题列出的原因包括手机时间「延迟或超前」、绑定页打开太久导致「二维码(密钥)已过期」。前者本工具会提示(本机时钟与服务器相差超过约 3 秒时);后者要刷新绑定页,拿到的是一串新密钥。
实测示例(RFC 测试向量)
以下都用 RFC 公布的测试密钥,任何实现都应该算出同样的结果。
| 密钥(Base32) | 算法 / 位数 | Unix 时间 | 上一个 | 当前 | 下一个 |
|---|---|---|---|---|---|
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ | SHA-1 / 8 | 1234567890 | 39980357 | 89005924 | 38590587 |
| 同上 | SHA-1 / 6 | 1234567890 | 980357 | 005924 | 590587 |
64 字节种子,末尾带 = | SHA-512 / 8 | 2000000000 | 19954193 | 38618901 | 41841313 |
第一行的 89005924 与第三行的 38618901 分别是 RFC 6238 附录 B 表中对应行的值。第二行说明 6 位验证码就是 8 位值的后 6 位,开头的 0 会保留。第三行的种子是 GEZDGNBVGY3TQOJQ 重复 6 次再接 GEZDGNA=,即 64 个 ASCII 字符 1234567890…1234;RFC 正文只提到 20 字节种子,但附录 A 的参考代码对 SHA-256 / SHA-512 用的是 32 / 64 字节种子,表中数值也只对这两个种子成立。
填上发行方「测试环境」、账户 dev@example.com,生成的 URI 是:
otpauth://totp/%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83:dev%40example.com?secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&issuer=%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83
中文按 UTF-8 百分号编码;按 Google 的 Key Uri Format,默认值(SHA1、6 位、30 秒)不写进 URI,发行方或账户里带 : 会被拒绝,因为冒号是两者的分隔符。
与其他在线 2FA 工具的区别
2026-09-30 我们用同样的输入测了中文搜索「2FA 在线」「2FA 验证码」结果里常见的几个工具:
- 密钥去了哪里。 2fa.cn 提交后,浏览器请求的是
https://2fa.cn/codes/<你的密钥>,验证码由服务器算好返回(开发者工具的网络记录可见)。BrowserScan 把密钥写进地址栏的#后面,会留在浏览历史里,页面还介绍了把密钥直接接在网址路径后的用法。本工具的密钥只在页面内存里,唯一的请求是读取服务器时间的 HEAD,不含密钥。 - 非法字符。 输入
GEZDGNBV1Y3TQOJQ(含1),2fa.cn 返回了000449,BrowserScan 也显示了验证码(它的红字「密钥字符不合法,请检查密钥」在输入正确的 RFC 密钥时同样显示)。本工具直接报错并指出是哪个字符。 - otpauth:// 链接。 BrowserScan 粘贴 URI 后不出验证码;2fa.cn 支持批量输入。本工具会把 URI 里的全部参数填好。
- 参数。 本工具支持 SHA-1 / SHA-256 / SHA-512、6 / 8 位、1–86400 秒任意周期,以及固定 Unix 时间,方便对照测试向量。
限制
- 只生成 TOTP。
otpauth://hotp/会被拒绝,没有计数器模式。 - 位数只有 6 和 8(Key Uri Format 规定的取值);周期是 1 到 86400 的整数秒,从 Unix 纪元起算(T0 = 0)。
- Key Uri Format 文档写明 Google Authenticator 忽略
algorithm与period,Android 版还忽略digits。改动这些参数时,二维码下方会出现提示。 - 不能直接读二维码图片。先用二维码解码器取出
otpauth://文本,再粘贴到这里;要把其他文字做成二维码,用二维码生成器。 - 什么都不保存,刷新即清空,这是有意的设计。
- 时钟检查依赖服务器
Date头,精度 1 秒,约 3 秒以内的偏差不提示;请求失败时不显示任何提示。
FAQ
密钥会上传或保存吗?
不会。验证码用浏览器的 Web Crypto API 在本机计算。密钥不写入 localStorage、sessionStorage、Cookie,也不进网址;本页不加载统计与广告脚本。刷新页面密钥就没了。工具唯一发出的请求是对本页的一次 HEAD 请求,用来读取服务器的 Date 时间做时钟检查,不带查询参数,也不带请求体。
这里的验证码和手机 App 或服务端对不上,怎么排查?
按顺序查三样:本机时钟(偏差超过约 3 秒时工具会提示)、密钥(抄错一个字符,或重新打开绑定页后密钥已换)、参数(算法、位数、周期两边必须一致)。当前验证码下方的上一个 / 下一个验证码,可用来判断对方是不是差了一个时间步。
能直接粘贴二维码里的 otpauth:// 链接吗?
能。把整条 otpauth://totp/ URI 粘进密钥框,工具会填好密钥、发行方、账户、算法、位数和周期,输入框里只留下密钥。otpauth://hotp/(计数器型)会被拒绝,本工具只生成基于时间的验证码。要从二维码图片里取出 URI,先用二维码解码工具。
随机生成的密钥多长?
SHA-1 为 20 字节(160 位),SHA-256 为 32 字节,SHA-512 为 64 字节,即 RFC 6238 第 5.1 节建议的与 HMAC 输出等长。RFC 4226 要求至少 128 位;更短的密钥也能算,工具会给出提示。
可以把这个页面当日常用的验证器吗?
不建议。页面什么都不保存,关掉标签页验证码就没了;而且谁拿到密钥,谁就能算出你的验证码。正式账号的密钥请放在验证器 App 或密码管理器里。这个页面适合测试 2FA 功能、核对手动抄写的密钥,或查看某个密钥在某个时刻的验证码。