首页/安全/等保与合规速查/TOTP 动态口令:实现与校验要点
密码与认证合规50 条

TOTP 动态口令:实现与校验要点

TOTP(基于 RFC 6238)以共享密钥与时间窗生成一次性口令,适合作为持有因素补齐双因素认证;服务端应校验时间窗、防重放并保护共享密钥。

等保与合规速查安全更新于 2026-10-13

TOTP 是什么

TOTP(基于时间的一次性口令,RFC 6238)由 HOTP(RFC 4226)加上时间因子演化而来:客户端与服务端共享一个密钥,双方用「当前时间片编号」作为计数器做 HMAC 运算,再截取为固定位数,于是每 30 秒自动换一个六位码。它属于「持有因素」,常与口令组合成双因素认证。安全性取决于三件事:共享密钥是否保密、服务端是否按窗口校验并防重放、系统时钟是否准确。

基本信息

标准RFC 6238(TOTP),依赖 RFC 4226(HOTP)
共享密钥Base32 编码,常见 16 或 32 字符;等同于长期凭据,必须与服务端一同加密保存
默认参数时间步长 30 秒、输出 6 位、HMAC-SHA1(可与服务端约定 SHA256/SHA512)
时钟要求客户端与服务端时间偏差需在允许窗口内,服务器应启用 NTP 同步
绑定方式otpauth://totp/发行方:账号?secret=...&issuer=...&period=30&digits=6 的密钥 URI,通常由二维码承载
常见工具oathtool(Linux 命令行)、Google Authenticator、Microsoft Authenticator、各语言 TOTP 库

命令行生成与校验

命令行生成与校验
# 生成当前动态码(-b 表示密钥为 base32)
oathtool --totp -b JBSWY3DPEHPK3PXP
# 每隔 5 秒打印一次,观察 30 秒步长的切换
watch -n 5 'oathtool --totp -b JBSWY3DPEHPK3PXP'
# 校验:允许前后各 1 个时间窗(-w 1)
oathtool --totp -b JBSWY3DPEHPK3PXP -w 1 --now="2026-10-13 10:00:00 UTC"
# 使用 SHA256 摘要(需与服务端参数一致)
oathtool --totp=sha256 -b JBSWY3DPEHPK3PXP

校验参数与建议

参数含义建议取值与原因
时间步长每个动态码的有效秒数30 秒为标准值;加大步长会扩大重放窗口
校验窗口允许前后偏移的时间片数量±1 个时间片足以容忍网络与时钟抖动,窗口越大被爆破的空间越大
码长度输出位数6 位为标准;6 位码在窗口内只有有限次尝试机会,因此必须配合失败次数限制
摘要算法HMAC 使用的哈希SHA1 兼容性最好;新系统可用 SHA256,但客户端必须支持
尝试限制同一账号的失败次数上限必须设置,否则 6 位码在有效窗口内可被在线穷举

服务端实现要点

  • 密钥加密存储:TOTP 密钥与口令散列同等级别保护,泄露即等于双因素失效
  • 防重放:记录每个账号最近一次成功校验的时间片编号,同一编号内的重复提交一律拒绝
  • 绑定与重置走身份核验:重新绑定需二次核验(如口令 + 邮箱/短信),并留存操作日志
  • 备用恢复码:每人预生成一次性恢复码并单独保管,避免手机丢失后账号锁死
  • 时钟同步:服务器启用 NTP 并监控时间偏差,客户端提示用户开启自动时间
  • 失败计数与锁定:连续失败触发延迟或锁定,并生成安全告警事件
TOTP 不能抵御实时钓鱼:代理页面可在用户输入后立即转发动态码。面向高价值账号,优先级应放在 FIDO2/WebAuthn 这类绑定来源的抗钓鱼方案上,TOTP 作为兼容性更好的过渡选择。

易错点

  • 校验窗口开得过大(如 ±5):动态码在更长时间内有效,重放与在线爆破的空间同步放大
  • 同一验证码可重复使用:不记录已用时间片时,攻击者可在窗口内重复提交同一码
  • 共享密钥明文入库:数据库泄露即等于所有账号的第二因素被绕过
  • 服务器时钟漂移未监控:所有用户动态码同时失效,表现为集中的登录失败投诉

数据来源与参考

  • RFC 6238(TOTP)
  • RFC 4226(HOTP)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌