如果你最近在 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 的原理并不复杂,核心就三样东西:

  1. 共享密钥 K
    开启 TOTP 时,网站生成一个随机密钥,你和服务器各保存一份。
  2. 时间窗口 T
    当前 Unix 时间除以 30 秒,取整数部分。
    比如:T = floor(当前时间 / 30)。
  3. 一次性密码
    用密钥 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 卡劫持、短信拦截
典型 AppGoogle Authenticator、Microsoft Authenticator、Authy、1Password手机短信

所以,一般安全建议是:

硬件密钥 > TOTP 认证器 > 短信验证码 > 只靠密码

当然,TOTP 也不是绝对安全。
如果你在钓鱼网站输入了密码和动态码,攻击者可以实时转发,仍然可能登录成功。


七、开启 TOTP 后,一定要注意这几件事

  1. 保存恢复码
    最好打印出来,或放在离线密码管理器里。不要只放在手机相册。
  2. 不要泄露 TOTP 密钥
    二维码和那串 Base32 密钥,等同于你的第二把钥匙。
  3. 开启手机自动时间同步
    TOTP 依赖时间,时间不准容易验证失败。
  4. 换手机前先处理
    可以在新手机重新绑定,或使用恢复码登录后重新设置。
  5. 注意钓鱼
    输入动态码前,确认域名是官方网站。
  6. 重要账号不要只用短信验证
    能开 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 是二次验证中常见的一种实现。

名词全称含义
MFAMulti-Factor Authentication多因素认证,要求两种或以上不同凭证
2FATwo-Factor Authentication双因素认证,MFA 最常见的形式
TOTPTime-based One-Time Password基于时间的一次性密码

所以,当你看到“登录二次验证 MFA TOTP”,通常意思是:

登录时除了输入密码,还要输入一个由认证器 App 生成的、每 30 秒变化一次的 6 位动态验证码。


二、TOTP 的核心:共享密钥 + 时间窗口

TOTP 的原理并不复杂,核心就三样东西:

  1. 共享密钥 K
    开启 TOTP 时,网站生成一个随机密钥,你和服务器各保存一份。
  2. 时间窗口 T
    当前 Unix 时间除以 30 秒,取整数部分。
    比如:T = floor(当前时间 / 30)。
  3. 一次性密码
    用密钥 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 卡劫持、短信拦截
典型 AppGoogle Authenticator、Microsoft Authenticator、Authy、1Password手机短信

所以,一般安全建议是:

硬件密钥 > TOTP 认证器 > 短信验证码 > 只靠密码

当然,TOTP 也不是绝对安全。
如果你在钓鱼网站输入了密码和动态码,攻击者可以实时转发,仍然可能登录成功。


七、开启 TOTP 后,一定要注意这几件事

  1. 保存恢复码
    最好打印出来,或放在离线密码管理器里。不要只放在手机相册。
  2. 不要泄露 TOTP 密钥
    二维码和那串 Base32 密钥,等同于你的第二把钥匙。
  3. 开启手机自动时间同步
    TOTP 依赖时间,时间不准容易验证失败。
  4. 换手机前先处理
    可以在新手机重新绑定,或使用恢复码登录后重新设置。
  5. 注意钓鱼
    输入动态码前,确认域名是官方网站。
  6. 重要账号不要只用短信验证
    能开 TOTP 就开 TOTP,能上硬件密钥更好。

八、常见问题

Q1:认证器 App 没网能用吗?
能。TOTP 是本地计算,不需要联网。

Q2:手机丢了怎么办?
用恢复码登录,然后重新绑定新的认证器。没有恢复码,就只能走客服申诉。

Q3:为什么验证码每 30 秒变一次?
因为 TOTP 默认时间步长是 30 秒。时间窗口变了,计算结果就变了。

Q4:多个网站可以用同一个密钥吗?
不应该。每个网站应该生成独立密钥。

Q5:TOTP 比短信验证码安全吗?
通常更安全。它不依赖短信,不容易被 SIM 卡劫持或短信拦截。


九、总结

一句话记住:

MFA 是多重验证的总称,2FA 是二次验证,TOTP 是其中一种“认证器 App 每 30 秒生成 6 位动态码”的方案。

它的核心是:

共享密钥 + 当前时间窗口 + HMAC 计算 = 6 位动态码。

开启 TOTP 能显著提升账号安全,但别忘了保存恢复码,也要小心钓鱼网站。
密码可以泄露,第二因素别一起送出去。