TOTP 简明指南:动态验证码是如何工作的

你在 Google Authenticator、Microsoft Authenticator、1Password、Bitwarden 里看到的 6 位动态验证码,大多数就是 TOTP。

TOTP 全称是 Time-based One-Time Password,意思是“基于时间的一次性密码”。它的核心作用,是在密码之外增加第二道验证:即使别人知道了你的密码,也还需要你认证器里当前那 6 位动态码。

它解决什么问题

密码的问题是:

只要被别人知道,就可以一直用。

TOTP 的作用是让登录多一个短时间有效的证明:

你知道密码
并且
你手上有保存了密钥的认证器

这就是常说的两步验证、2FA 或 MFA。

它为什么不需要联网

TOTP 最容易误解的一点是:认证器 App 生成验证码时通常不需要联网。

因为它只依赖两个东西:

1. 共享密钥 secret
2. 当前时间

绑定两步验证时,网站会给你一个二维码。这个二维码里包含一个 secret,比如:

JBSWY3DPEHPK3PXP

你的认证器保存这个 secret。网站服务器也保存同一个 secret。

之后,认证器和服务器分别用:

secret + 当前时间

算出同一个 6 位验证码。

最小流程

1. 绑定

网站先生成一个 secret,并把它编码进二维码。

你用认证器 App 扫码之后:

网站保存 secret
认证器保存 secret

从这一步开始,双方就有了同一个“暗号”。

2. 生成验证码

认证器每隔一小段时间重新计算一次:

TOTP(secret, 当前时间片) = 6 位验证码

例如当前验证码是:

493821

过一会儿就会变成:

027194

3. 登录验证

你登录时输入:

用户名
密码
当前 TOTP 验证码

服务器也用自己保存的 secret 和当前时间算一遍验证码。

如果两边结果一致:

验证通过

否则:

验证失败

时间片是什么

TOTP 不是直接拿当前秒数来算,而是把时间切成固定窗口。最常见的是 30 秒一个窗口。

12:00:00 - 12:00:29 → 时间片 A
12:00:30 - 12:00:59 → 时间片 B
12:01:00 - 12:01:29 → 时间片 C

同一个时间片里,验证码不变。进入下一个时间片,验证码就变。

所以认证器里通常会有一个倒计时圆环,提醒你当前验证码还剩多久过期。

服务端为什么能容忍时间误差

你的手机时间和服务器时间可能差几秒。

所以服务端通常不会只检查当前 30 秒窗口,而是会检查相邻窗口,比如:

上一个 30 秒
当前 30 秒
下一个 30 秒

只要其中一个匹配,就算通过。

这叫 time window tolerance。

窗口不能开得太大。窗口越大,验证码有效范围越宽,安全性就越低。

TOTP 和短信验证码有什么区别

短信验证码是:

服务器生成验证码
通过短信发给你
你再输入

它的问题是:

依赖运营商
可能有延迟
可能被 SIM swap 攻击
可能被短信拦截

TOTP 是:

服务器和认证器各自在本地计算验证码
验证码不需要被发送

所以 TOTP 通常比短信验证码更稳定,也更安全。

TOTP 安全在哪里

TOTP 安全的关键,不是那 6 位数字本身,而是攻击者不知道 secret。

6 位数字确实很短,但它有几个限制:

只能短时间有效
每 30 秒变化一次
必须知道 secret 才能预测下一个验证码
服务端可以限制尝试次数

所以攻击者就算看到一次验证码,也很难长期利用。

TOTP 的弱点

TOTP 不是完美方案。

1. secret 泄露就失效

如果绑定二维码或 secret 被别人拿到,对方也能在自己的设备上生成同样的验证码。

所以二维码不要随便截图、转发,也不要备份到不安全的位置。

2. 不能防实时钓鱼

如果你在钓鱼网站输入:

密码 + 当前 TOTP

攻击者可以立刻拿这组信息去真实网站登录。

也就是说,TOTP 能防“密码泄露后被长期使用”,但不能完全防“实时中间人钓鱼”。

更强的方案是 Passkey、WebAuthn 或 FIDO2 安全密钥,因为它们会绑定具体网站域名。

3. 依赖设备时间

如果手机时间严重不准,验证码会失效。

不过现代手机通常会自动同步时间,所以这个问题不常见。

TOTP 和 HOTP 的关系

TOTP 来自 HOTP。

HOTP 全称是:

HMAC-based One-Time Password

它基于计数器:

secret + counter

每用一次,counter 加一。

TOTP 则把时间片当成 counter:

secret + time counter

所以可以这样理解:

TOTP = 把当前时间当成计数器的 HOTP

一个最小 mental model

可以把 TOTP 想成两边同时看表、同时算题:

认证器:拿 secret + 当前时间片 → 算出 493821
服务器:拿 secret + 当前时间片 → 算出 493821

两边算出来一样,就说明你手上有保存 secret 的认证器。

总结

TOTP 的核心就是:

网站和你的认证器提前共享一个 secret,然后双方根据当前时间各自计算同一个 6 位验证码;验证码每 30 秒变化一次,用来作为密码之外的第二道验证。

它比短信验证码更稳定、更独立,但仍然要保护好 secret,也不能把它当成防钓鱼的最终方案。