跳到正文
Novaz Authenticator获取

2FA 验证码是怎么生成的?TOTP 详解

作者:Novaz 团队 · 更新于 2026年10月29日
Novaz 操作步骤已在 1.0.5 版本中核实

本文译自英文指南。在服务的网站上,按钮和菜单的中文名称可能略有不同。

本页内容
  1. 要素 1:设置密钥
  2. 要素 2:按步长计数的时间
  3. 把两者合成验证码
  4. 网站为什么会接受它
  5. 服务可以更改的设置
  6. TOTP 与 HOTP
  7. TOTP 防不住什么
  8. 在 Authenticator App - Novaz 中

身份验证器 App 和网站各自用双方都有的两样东西算出同一个 6 位数:一个双方曾经共享过的密钥,以及当前时间。登录时,两者之间不传送任何数据。正因如此,没有信号时验证码也能用,而且每 30 秒变化一次。这种方法叫 TOTP,即基于时间的一次性密码(time-based one-time password),是一项开放标准(RFC 6238)。

要素 1:设置密钥

开启 2FA 时,网站会生成一个随机密钥,以二维码的形式显示给你,同时附上一个文本版本,叫作设置密钥。你的 App 会把它保存下来。从此以后,网站和你的 App 拥有同一个密钥,而其他任何人都不应该有。

二维码其实只是一个标准格式的链接 otpauth://totp/…,里面包含密钥、服务名称、你的账号名称,以及下文介绍的可选设置。我们的 2FA 二维码解码器可以显示二维码里的内容。

要素 2:按步长计数的时间

双方都把当前时间换算成自 1970 年 1 月 1 日起经过的秒数(Unix 时间),再除以 30 并舍去余数。结果是一个每 30 秒加一的整数。RFC 6238 把它称为 T,并推荐 “a default time-step size of 30 seconds”(默认时间步长为 30 秒)。

把两者合成验证码

App 把密钥和 T 一起送入 HMAC(一种密码学函数),通常使用 SHA-1。然后用 HOTP 标准(RFC 4226,第 5.3 节)定义的方法把结果截短成一个短数字:

  1. HMAC 结果的最后 4 位(bit)指定其中的一个位置。
  2. App 从该位置取出 31 位(bit),作为一个数字。
  3. 保留这个数字的最后 6 位数字。有些服务使用 8 位。

只要密钥或时间步长变了,得到的验证码就完全不同。从验证码无法反推出密钥。

Try it: a live TOTP code

Calculated in your browser from an example key. Don't paste a real setup key here.

Current code

…

Previous: …

Next: …

Unix time
…
Time step T = ⌊time ÷ 30⌋
…
Seconds left
…

网站为什么会接受它

网站用它保存的那份密钥和自己的时钟做同样的计算。如果数字一致,你就能登录。实际使用中,有两个细节让这一机制行得通:

  • 给延迟留一点余地。 你在一个步长末尾输入的验证码,可能在下一个步长才送达。RFC 6238 建议 “at most one time step is allowed as the network delay”(最多允许一个时间步长作为网络延迟),所以许多网站也接受当前验证码的前一个。
  • 每个验证码只能用一次。 标准规定,对于已经接受过的验证码,服务器 “MUST NOT accept the second attempt”(不得接受第二次尝试)。美国 NIST 的指南也是这样规定的:验证方 “SHALL accept a given OTP only once while it is valid”(在一次性密码有效期内只能接受它一次)(NIST SP 800-63B-4)。

这也是时钟不准会导致验证码失效的原因。如果你的 iPhone 偏差了一分钟,它算出的就是与网站不同的时间步长的验证码。参见身份验证器验证码无效?

服务可以更改的设置

标准允许一定的变化,二维码可以把这些设置带过来:

设置 常用值 也允许
哈希算法 SHA-1 SHA-256、SHA-512(RFC 6238,第 1.2 节)
位数 6 7 或 8(RFC 4226,第 5.3 节)
间隔 30 秒 其他时长

如果某项服务使用了不常见的设置,请扫描二维码添加,而不是手动输入密钥,这样 App 也能获得这些设置。

TOTP 与 HOTP

HOTP 是较早的标准,它使用一个每次请求验证码时加一的计数器,而不是时间。TOTP 就是以时间步长为计数器的 HOTP:“TOTP = HOTP(K, T)”。如今大多数网站都使用 TOTP。

TOTP 防不住什么

因为验证码要由你自己输入,一个足以乱真的假登录页面可以向你索要验证码并立即使用。NIST 说得很明白:“OTP authentication is not phishing-resistant”(一次性密码认证不能抵御网络钓鱼)。通行密钥和安全密钥则可以。详见身份验证器 App 与短信验证码。

在 Authenticator App - Novaz 中

Novaz 在你的 iPhone 上生成标准的 TOTP 验证码:

  • 通过二维码添加: SHA-1、SHA-256 或 SHA-512;6 到 8 位;间隔 1 到 300 秒。
  • 手动输入密钥添加: 一律 6 位、30 秒和 SHA-1。

它不生成 HOTP 验证码。它还会检查 iPhone 的时钟,在偏差达到 15 秒或更多时提醒你。