如果你最近在 GitHub、Google、微软、阿里云、腾讯云等平台开启两步验证,可能会看到 MFA、2FA、OTP、TOTP 这些词。
很多人第一次见会懵:
它们是一个东西吗?
为什么登录时还要输一个 6 位数字?
这个数字到底是怎么来的?
这篇文章用大白话讲清楚。
一、先搞懂几个名词:MFA、OTP、TOTP
1. MFA 是什么?
MFA = Multi-Factor Authentication,多因素认证。
意思是:登录时不能只靠一种凭证,而是要求两种或以上不同类别的凭证。
常见的认证因素一般分三类:
| 因素类别 | 含义 | 例子 |
|---|---|---|
| 知识因素 | 你知道什么 | 密码、PIN、安全问题 |
| 拥有因素 | 你拥有什么 | 手机、认证器 App、硬件密钥、短信验证码 |
| 生物因素 | 你是什么 | 指纹、人脸、虹膜 |
MFA 要求从不同类别里选至少两种。
比如“密码 + 手机动态码”就是 MFA。
2. OTP 是什么?
OTP = One-Time Password,一次性密码。
意思是:这个密码只用一次,或者只在很短时间内有效,不能长期重复使用。
常见的 OTP 包括:
- 短信验证码;
- 邮箱验证码;
- TOTP 动态码;
- HOTP 动态码;
- 硬件令牌上显示的动态码。
所以,OTP 是一个统称,不是某一种具体技术。
3. TOTP 是什么?
TOTP = Time-based One-Time Password,基于时间的一次性密码。
它是 OTP 的一种,特点是:
- 用共享密钥 K;
- 用当前时间窗口 T;
- 通过 HMAC 算法计算;
- 通常生成 6 位数字;
- 默认每 30 秒变化一次;
- 认证器 App 不需要联网。
你手机里的 Google Authenticator、Microsoft Authenticator、Authy、1Password 等,生成的 6 位动态码,通常就是 TOTP。
4. 它们之间的关系
可以用一句话记住:
MFA 是认证框架,2FA 是 MFA 的常见形式,OTP 是一次性密码统称,TOTP 是 OTP 的一种。
文字关系图:
MFA 多因素认证
└── 2FA 双因素认证
└── 第二因素
└── OTP 一次性密码
├── 短信验证码
├── 邮箱验证码
├── TOTP 基于时间的一次性密码
└── HOTP 基于计数器的一次性密码
所以,当你看到“登录二次验证 MFA TOTP”,通常意思是:
登录时除了输入密码,还要输入一个由认证器 App 生成的、每 30 秒变化一次的 6 位动态验证码。
二、TOTP 的核心:共享密钥 + 时间窗口
TOTP 的原理并不复杂,核心就三样东西:
- 共享密钥 K
开启 TOTP 时,网站生成一个随机密钥,你和服务器各保存一份。 - 时间窗口 T
当前 Unix 时间除以 30 秒,取整数部分。
比如:T = floor(当前时间 / 30)。 - 一次性密码
用密钥 K 和时间窗口 T 做 HMAC 计算,再截断成 6 位数字。
公式可以简化成:
T = floor((当前 Unix 时间 - T0) / 30)
TOTP = HOTP(K, T)
HOTP(K, C) = Truncate(HMAC-SHA1(K, C))
其中:
K:服务器和认证器 App 共享的密钥;T0:一般取 0;30:默认时间步长,单位秒;- 最终生成 6 位动态码。
认证器 App 不需要联网,它本地就能用密钥和时间算出来。服务器也用同样方式算一遍,两边结果一致,就通过验证。
三、TOTP 绑定阶段流程
第一次开启 TOTP 时,网站和认证器 App 要先“对暗号”。
文字流程图
用户 -> 服务器:登录后请求开启 TOTP
服务器 -> 服务器:生成随机密钥 K,Base32 编码
服务器 -> 用户:返回二维码和 otpauth URI
用户 -> 认证器 App:扫描二维码
认证器 App -> 认证器 App:保存密钥 K
认证器 App -> 认证器 App:计算 TOTP = HOTP(K, floor(now/30))
认证器 App -> 用户:显示 6 位动态码
用户 -> 服务器:提交动态码
服务器 -> 服务器:用 K 计算当前时间窗口 TOTP
服务器 -> 用户:如果正确,启用 TOTP,并展示恢复码
服务器 -> 用户:如果错误,开启失败
步骤表
| 步骤 | 角色 | 动作 |
|---|---|---|
| 1 | 用户 | 登录后请求开启 TOTP |
| 2 | 服务器 | 生成随机密钥 K,并编码成二维码 |
| 3 | 用户 | 用认证器 App 扫描二维码 |
| 4 | 认证器 App | 保存密钥 K |
| 5 | 认证器 App | 本地计算 6 位动态码 |
| 6 | 用户 | 提交动态码给服务器 |
| 7 | 服务器 | 用同样密钥和时间计算,验证是否一致 |
| 8 | 服务器 | 验证成功则启用 TOTP,并给出恢复码 |
绑定成功后,网站通常会给你一组 恢复码。
这组码非常重要,手机丢了、认证器删了,就靠它救命。
四、TOTP 登录验证阶段
以后每次登录,流程会变成这样:
总览文字流程图
[输入账号密码]
|
v
[服务器验证密码]
|
+-- 密码错误 --> [登录失败]
|
+-- 密码正确且已开启 TOTP
|
v
[服务器要求输入 6 位动态码]
|
v
[用户打开认证器 App 查看动态码]
|
v
[认证器 App 本地计算 TOTP]
|
v
[用户提交动态码]
|
v
[服务器计算 T-1、T、T+1 窗口的 TOTP]
|
+-- 匹配成功 --> [登录成功]
|
+-- 匹配失败 --> [登录失败 / 重试]
登录步骤表
| 步骤 | 角色 | 动作 |
|---|---|---|
| 1 | 用户 | 输入用户名和密码 |
| 2 | 服务器 | 验证密码 |
| 3 | 服务器 | 如果已开启 TOTP,要求输入动态码 |
| 4 | 用户 | 打开认证器 App 查看 6 位动态码 |
| 5 | 认证器 App | 本地计算当前动态码 |
| 6 | 用户 | 提交动态码 |
| 7 | 服务器 | 计算 T-1、T、T+1 窗口的 TOTP |
| 8 | 服务器 | 匹配成功则登录成功,否则拒绝或要求重试 |
五、为什么服务器要接受 T-1、T、T+1?
因为手机和服务器的时间可能不完全同步。
如果服务器只认当前时间窗口 T,手机慢了几秒,就可能验证失败。
所以很多服务会额外接受:
T-1:上一个 30 秒窗口;T:当前窗口;T+1:下一个 30 秒窗口。
这样能容忍轻微时间漂移,体验更好。
但这也意味着,一个动态码在特殊情况下可能有效几十秒。它不是绝对一次性,只是在短时间内有效。理想情况下,服务器还应该防止同一个动态码被重复使用。
六、TOTP 和短信验证码有什么区别?
| 对比项 | TOTP 动态码 | 短信验证码 |
|---|---|---|
| 生成方式 | 认证器 App 本地计算 | 服务器发送短信 |
| 是否需要网络 | 不需要 | 需要手机信号 |
| 是否依赖短信 | 不依赖 | 依赖 |
| 安全性 | 通常更高 | 容易被 SIM 卡劫持、短信拦截 |
| 典型 App | Google Authenticator、Microsoft Authenticator、Authy、1Password | 手机短信 |
所以,一般安全建议是:
硬件密钥 > TOTP 认证器 > 短信验证码 > 只靠密码
当然,TOTP 也不是绝对安全。
如果你在钓鱼网站输入了密码和动态码,攻击者可以实时转发,仍然可能登录成功。
七、开启 TOTP 后,一定要注意这几件事
- 保存恢复码
最好打印出来,或放在离线密码管理器里。不要只放在手机相册。 - 不要泄露 TOTP 密钥
二维码和那串 Base32 密钥,等同于你的第二把钥匙。 - 开启手机自动时间同步
TOTP 依赖时间,时间不准容易验证失败。 - 换手机前先处理
可以在新手机重新绑定,或使用恢复码登录后重新设置。 - 注意钓鱼
输入动态码前,确认域名是官方网站。 - 重要账号不要只用短信验证
能开 TOTP 就开 TOTP,能上硬件密钥更好。
八、常见问题
Q1:MFA、OTP、TOTP 到底有什么区别?
MFA 是多因素认证的框架;OTP 是一次性密码的统称;TOTP 是 OTP 中基于时间的一种。
Q2:认证器 App 没网能用吗?
能。TOTP 是本地计算,不需要联网。
Q3:手机丢了怎么办?
用恢复码登录,然后重新绑定新的认证器。没有恢复码,就只能走客服申诉。
Q4:为什么验证码每 30 秒变一次?
因为 TOTP 默认时间步长是 30 秒。时间窗口变了,计算结果就变了。
Q5:多个网站可以用同一个密钥吗?
不应该。每个网站应该生成独立密钥。
Q6:TOTP 比短信验证码安全吗?
通常更安全。它不依赖短信,不容易被 SIM 卡劫持或短信拦截。
九、总结
一句话记住:
MFA 是多重验证的总称,2FA 是二次验证,OTP 是一次性密码统称,TOTP 是其中一种“认证器 App 每 30 秒生成 6 位动态码”的方案。
它的核心是:
共享密钥 + 当前时间窗口 + HMAC 计算 = 6 位动态码。
开启 TOTP 能显著提升账号安全,但别忘了保存恢复码,也要小心钓鱼网站。
密码可以泄露,第二因素别一起送出去。
如果你最近在 GitHub、Google、微软、阿里云、腾讯云等平台开启两步验证,可能会看到 MFA、2FA、TOTP 这些词。
很多人第一次见会懵:
它们是一个东西吗?
为什么登录时还要输一个 6 位数字?
这个数字到底是怎么来的?
这篇文章用大白话和 Mermaid 图讲清楚。
注:知乎编辑器目前可能不直接渲染 Mermaid。你可以把下面的 Mermaid 代码复制到 mermaid.live 渲染成图片,再上传到知乎。
一、先说结论
MFA 是多重验证的总称,2FA 是二次验证,TOTP 是二次验证中常见的一种实现。
| 名词 | 全称 | 含义 |
|---|---|---|
| MFA | Multi-Factor Authentication | 多因素认证,要求两种或以上不同凭证 |
| 2FA | Two-Factor Authentication | 双因素认证,MFA 最常见的形式 |
| TOTP | Time-based One-Time Password | 基于时间的一次性密码 |
所以,当你看到“登录二次验证 MFA TOTP”,通常意思是:
登录时除了输入密码,还要输入一个由认证器 App 生成的、每 30 秒变化一次的 6 位动态验证码。
二、TOTP 的核心:共享密钥 + 时间窗口
TOTP 的原理并不复杂,核心就三样东西:
- 共享密钥 K
开启 TOTP 时,网站生成一个随机密钥,你和服务器各保存一份。 - 时间窗口 T
当前 Unix 时间除以 30 秒,取整数部分。
比如:T = floor(当前时间 / 30)。 - 一次性密码
用密钥 K 和时间窗口 T 做 HMAC 计算,再截断成 6 位数字。
公式可以简化成:
T = floor((当前 Unix 时间 - T0) / 30)
TOTP = HOTP(K, T)
HOTP(K, C) = Truncate(HMAC-SHA1(K, C))
其中:
K:服务器和认证器 App 共享的密钥;T0:一般取 0;30:默认时间步长,单位秒;- 最终生成 6 位动态码。
认证器 App 不需要联网,它本地就能用密钥和时间算出来。服务器也用同样方式算一遍,两边结果一致,就通过验证。
三、TOTP 绑定阶段流程
第一次开启 TOTP 时,网站和认证器 App 要先“对暗号”。
sequenceDiagram
autonumber
participant U as 用户
participant S as 服务器
participant A as 认证器 App
U->>S: 登录后请求开启 TOTP
S->>S: 生成随机密钥 K,Base32 编码
S->>U: 返回二维码和 otpauth URI
U->>A: 扫描二维码
A->>A: 保存密钥 K
A->>A: 计算 TOTP = HOTP(K, floor(now/30))
A-->>U: 显示 6 位动态码
U->>S: 提交动态码
S->>S: 用 K 计算当前时间窗口 TOTP
alt 动态码正确
S->>S: 保存 K,启用 TOTP MFA
S-->>U: 开启成功,展示恢复码
else 动态码错误
S-->>U: 开启失败
end
绑定成功后,网站通常会给你一组 恢复码。
这组码非常重要,手机丢了、认证器删了,就靠它救命。
四、TOTP 登录验证阶段
以后每次登录,流程会变成这样:
sequenceDiagram
autonumber
participant U as 用户
participant S as 服务器
participant A as 认证器 App
U->>S: 输入用户名和密码
S->>S: 验证密码
alt 密码正确且已启用 TOTP
S-->>U: 要求输入 TOTP 动态码
U->>A: 查看当前动态码
A->>A: 计算 TOTP = HOTP(K, floor(now/30))
A-->>U: 显示 6 位动态码
U->>S: 提交动态码
S->>S: 计算 T-1、T、T+1 窗口的 TOTP
alt 匹配成功
S-->>U: 登录成功
else 匹配失败
S-->>U: 登录失败或要求重试
end
else 密码错误或未启用
S-->>U: 登录失败或直接登录
end
一张简图总览:
flowchart TD
A[输入账号密码] --> B{密码正确?}
B -- 否 --> F[登录失败]
B -- 是 --> C{是否开启 TOTP?}
C -- 否 --> G[登录成功]
C -- 是 --> D[要求输入 6 位动态码]
D --> E{动态码匹配?}
E -- 是 --> G
E -- 否 --> H[拒绝登录 / 重试]
五、为什么服务器要接受 T-1、T、T+1?
因为手机和服务器的时间可能不完全同步。
如果服务器只认当前时间窗口 T,手机慢了几秒,就可能验证失败。
所以很多服务会额外接受:
T-1:上一个 30 秒窗口;T:当前窗口;T+1:下一个 30 秒窗口。
这样能容忍轻微时间漂移,体验更好。
但这也意味着,一个动态码在特殊情况下可能有效几十秒。它不是绝对一次性,只是在短时间内有效。
六、TOTP 和短信验证码有什么区别?
| 对比项 | TOTP 动态码 | 短信验证码 |
|---|---|---|
| 生成方式 | 认证器 App 本地计算 | 服务器发送短信 |
| 是否需要网络 | 不需要 | 需要手机信号 |
| 是否依赖短信 | 不依赖 | 依赖 |
| 安全性 | 通常更高 | 容易被 SIM 卡劫持、短信拦截 |
| 典型 App | Google Authenticator、Microsoft Authenticator、Authy、1Password | 手机短信 |
所以,一般安全建议是:
硬件密钥 > TOTP 认证器 > 短信验证码 > 只靠密码
当然,TOTP 也不是绝对安全。
如果你在钓鱼网站输入了密码和动态码,攻击者可以实时转发,仍然可能登录成功。
七、开启 TOTP 后,一定要注意这几件事
- 保存恢复码
最好打印出来,或放在离线密码管理器里。不要只放在手机相册。 - 不要泄露 TOTP 密钥
二维码和那串 Base32 密钥,等同于你的第二把钥匙。 - 开启手机自动时间同步
TOTP 依赖时间,时间不准容易验证失败。 - 换手机前先处理
可以在新手机重新绑定,或使用恢复码登录后重新设置。 - 注意钓鱼
输入动态码前,确认域名是官方网站。 - 重要账号不要只用短信验证
能开 TOTP 就开 TOTP,能上硬件密钥更好。
八、常见问题
Q1:认证器 App 没网能用吗?
能。TOTP 是本地计算,不需要联网。
Q2:手机丢了怎么办?
用恢复码登录,然后重新绑定新的认证器。没有恢复码,就只能走客服申诉。
Q3:为什么验证码每 30 秒变一次?
因为 TOTP 默认时间步长是 30 秒。时间窗口变了,计算结果就变了。
Q4:多个网站可以用同一个密钥吗?
不应该。每个网站应该生成独立密钥。
Q5:TOTP 比短信验证码安全吗?
通常更安全。它不依赖短信,不容易被 SIM 卡劫持或短信拦截。
九、总结
一句话记住:
MFA 是多重验证的总称,2FA 是二次验证,TOTP 是其中一种“认证器 App 每 30 秒生成 6 位动态码”的方案。
它的核心是:
共享密钥 + 当前时间窗口 + HMAC 计算 = 6 位动态码。
开启 TOTP 能显著提升账号安全,但别忘了保存恢复码,也要小心钓鱼网站。
密码可以泄露,第二因素别一起送出去。