GitHub、Google等网站的两步验证(2FA)Authenticator的原理

63 阅读3分钟

两步验证(2FA)应用如 Google Authenticator、Microsoft Authenticator 的核心原理是基于TOTP(Time-Based One-Time Password,基于时间的一次性密码)算法,该算法源自HOTP(HMAC-based One-Time Password,基于 HMAC 的一次性密码)算法

一、核心组成要素

要素说明
共享密钥 (Secret Key)服务端与客户端预先协商的唯一密钥,通常为 32 位 Base32 编码字符串,通过二维码或手动输入方式共享
时间同步双方使用 Unix 时间戳 (从 1970 年 1 月 1 日 00:00:00 UTC 开始计算的秒数),以30 秒为一个时间窗口
HMAC 算法通常使用 HMAC-SHA1 哈希函数,将密钥与时间值结合生成哈希值
一次性密码 (OTP)最终生成的 6-8 位数字密码,每 30 秒自动更新

二、工作流程详解

1. 初始绑定阶段

  1. 用户在服务端 (如 GitHub、Google 账户) 启用两步验证
  2. 服务端生成唯一的共享密钥,并以二维码形式展示 (包含密钥、账户名、服务名等信息)
  3. 用户使用 Authenticator 应用扫描二维码,将密钥安全存储在本地设备
  4. 服务端同时将该密钥与用户账户关联并保存到数据库

2. 验证码生成阶段 (客户端)

  1. 获取当前 Unix 时间戳,计算时间步长计数器T = floor(current_time / 30)

  2. 使用HMAC 算法计算哈希值:HMAC-SHA1(密钥, T)

  3. 对哈希值进行截断处理(Truncate):

    • 取哈希值最后一个字节的低 4 位作为偏移量
    • 从偏移量位置取 4 个字节,组成 32 位整数
    • 对该整数取模 10^6 (或 10^8),得到 6 位 (或 8 位) 数字密码
  4. 每 30 秒重复上述过程,生成新的验证码

3. 验证阶段 (服务端)

  1. 用户输入账户密码后,被要求提供 Authenticator 中的 6 位验证码
  2. 服务端从数据库读取与该账户关联的共享密钥
  3. 使用与客户端完全相同的TOTP 算法生成验证码
  4. 验证用户输入的验证码与服务端生成的是否一致
  5. 验证通过则允许登录,否则拒绝访问

三、HOTP 与 TOTP 的关系

  • HOTP:基于计数器的一次性密码算法,公式为HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

    • K: 共享密钥
    • C: 计数器,每次验证成功后递增
  • TOTP:是 HOTP 的时间版本,将计数器 C 替换为基于时间的计数器 T

    • 公式:TOTP(K) = HOTP(K, T),其中T = floor(current_time / X)(X 通常为 30 秒)

四、关键安全特性

  1. 无需网络连接:验证码生成完全在本地设备完成,不依赖网络
  2. 时效性:验证码仅在 30 秒内有效,超时自动失效
  3. 唯一性:每个时间窗口生成的验证码都是唯一的,无法重复使用
  4. 双因素保障:即使密码泄露,攻击者还需获取用户设备或密钥才能登录
  5. 多设备同步:部分应用 (如 Microsoft Authenticator、新版 Google Authenticator) 支持加密同步密钥到云端,方便设备更换

五、时间同步的重要性

TOTP 算法依赖服务端与客户端的时间高度同步。如果设备时间与服务端时间偏差超过 30 秒,生成的验证码将不匹配。大多数应用会允许 **±1 个时间窗口 ** 的误差 (即 90 秒内有效),以应对轻微的时间偏差。

总结

Authenticator 应用的核心原理是通过预共享密钥时间同步,使用TOTP 算法生成一次性验证码,实现 "你知道的 (密码)+ 你拥有的 (设备)" 的双因素认证,大幅提升账户安全性。