TOTP 生成器

结果

每当 Google 身份验证器(Google Authenticator)或 Authy 显示一个每 30 秒变化一次的六位验证码时,那就是 TOTP:由共享密钥和当前 Unix 时间计算出的 HMAC,已在 RFC 6238 中标准化。这个生成器可以从任何 Base32 密钥计算出相同的验证码,适合用来调试新的双因素认证(2FA)集成、排查服务为什么拒绝你的验证码,或者观察算法在不同参数下的表现。请只用测试密钥:验证码在我们的服务器上计算,真正保护你账户的密钥应该放在身份验证器应用里,而不是任何网页上。

这个 TOTP 生成器的工作方式

  1. 1

    粘贴 Base32 密钥

    由字母 A-Z 和数字 2-7 组成,也就是 otpauth:// 二维码内部使用的格式。空格和小写字母没有问题;其他字符会被提示为无效的 Base32。

  2. 2

    选择哈希算法

    几乎所有服务都使用 SHA-1;只有当服务明确要求时才切换到 SHA-256 或 SHA-512。

  3. 3

    设置位数和周期

    选择 6、7 或 8 位数字,以及 30 或 60 秒的时间窗口。标准组合是每 30 秒 6 位数字。

  4. 4

    读取当前验证码

    验证码每秒刷新一次,倒计时显示当前时间窗口还剩多少秒。

  5. 5

    比对 otpauth URI

    工具会显示与你的参数对应的 otpauth:// URI,方便你与服务配置二维码中编码的内容进行核对。

用大白话解释算法

TOTP 就是 HOTP(基于 HMAC 的一次性密码,RFC 4226),只是把计数器换成了当前 Unix 时间除以时间步长(通常为 30 秒):

counter = floor(unix_time / 30)
hash = HMAC-SHA1(secret, counter_as_8_byte_big_endian)
offset = last byte of hash AND 0x0F
truncated = 4 bytes from offset, with the top bit zeroed
code = truncated mod 10^digits

你的设备和服务器用同一个密钥、同一个时钟做同样的计算,因此双方会得到相同的验证码,而验证码本身从未在网络上传输。6 位验证码不过是截断后的 HMAC 对 10^6 取模的结果。没有魔法,只有哈希。

常见参数

服务 算法 位数 周期
大多数网站和应用 SHA-1 6 30 秒
GitHub SHA-1 6 30 秒
Cloudflare SHA-1 6 30 秒
Microsoft 账户 SHA-1 6 30 秒
部分银行和企业 VPN SHA-256 或 SHA-512 8 60 秒

如果服务拒绝你的验证码,先检查位数和周期,再检查算法。另外注意,有些身份验证器应用会悄悄忽略非默认参数(Google 身份验证器历史上把一切都当作 SHA-1、6 位、30 秒处理),所以一定要用你的用户实际会用的那款应用来测试。

安全保管密钥

  • 绝不要用电子邮件或消息发送 2FA 密钥。 一旦进入收件箱,它就会无限期留在邮件服务商的日志和备份里。
  • 通过扫描二维码来完成绑定。 二维码编码了一个 otpauth://totp/... URI,把密钥、算法、位数和周期打包成一个没有歧义的整体。
  • 绑定时就做好备份。 把恢复码或密钥本身存进密码管理器;没有它们就丢了手机,你会被锁在账户外面。
  • 一个服务一个密钥。 每个服务在设置时都会签发自己的密钥;如果某个密钥泄露,就在该服务上重新绑定,让旧密钥失效。

时间偏差

TOTP 只有在两边时钟一致时才有效。本页面用服务器的时钟计算验证码,所以如果这里的验证码和你手机上的身份验证器不一致,首先要怀疑的是设备时钟。大多数校验方允许前后各一个窗口的偏差(30 到 60 秒);超出这个范围,请先通过 NTP 同步设备时间,再怀疑密钥本身。

这里请使用测试密钥

这个工具在我们的服务器上计算验证码:你输入的密钥会在每次更新时通过 HTTPS 传输,在工具的步骤之间切换时还会出现在页面 URL 中。用一次性的测试密钥做开发、演示和调试完全没问题。但它不是存放真实密钥的地方,保护你邮箱或银行账户的密钥应该放在手机上的专用身份验证器应用里。如果你已经把真实密钥粘贴到了身份验证器之外的地方,请在对应服务上重新绑定 2FA,让密钥轮换掉。

常见问题

请把这个页面当作开发和测试工具,而不是保险箱。验证码在服务器端计算,因此密钥会通过 HTTPS 传到我们的服务器,并且在步骤之间可能出现在页面 URL 中。演示或开发用的密钥可以放心使用;但绝不要粘贴你在意的账户的真实密钥。如果已经粘贴过,请到该服务重新绑定 2FA,轮换密钥。

先核对参数:算法、位数和周期必须与服务签发时的设置完全一致。再核对时钟:本页面使用服务器时钟,出现偏差时通常是另一台设备的时间不准。最后记住,有些应用会忽略非默认参数,Google 身份验证器就是经典例子。

只接受 Base32:字母 A 到 Z 和数字 2 到 7,可以带可选的 = 填充。空格会被去掉,小写会自动转换。十六进制或原始字节的密钥需要先转换成 Base32,否则工具会提示 Base32 密钥无效。

你会被锁在该账户的 2FA 之外。请走服务的恢复流程(恢复码、身份核验、短信兜底)。设置时务必把恢复码或最初的二维码保存在安全的地方。

可以。在服务器端生成随机密钥,至少 128 位(RFC 4226 建议 160 位),以二维码形式只展示一次,然后用同样的 HMAC 计算来校验用户提交的验证码,通常允许前后各一个窗口的容差。各种技术栈都有成熟的库:pyotp(Python)、otplib(JavaScript)、rotp(Ruby)。

相关工具

此工具还提供其他语言版本