You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pyotp生成的TOTP验证码与Aegis/Google Authenticator不匹配求助

解决pyotp生成的TOTP与验证器不一致的问题

核心问题1:密钥未遵循Base32编码标准

TOTP协议要求密钥必须是Base32编码格式,你直接使用明文字符串"ThiskeyDoesNotChange",pyotp的隐式转换逻辑和验证器(Google Authenticator/Aegis)的处理不匹配,这是最常见的原因。

修复方案:

要么生成符合标准的Base32密钥,要么将现有明文密钥转换为Base32:

import pyotp
import base64

# 方案1:生成标准Base32密钥(推荐)
key = pyotp.random_base32()

# 方案2:将你的明文密钥转成Base32(注意:明文不能包含Base32不支持的字符)
# key = base64.b32encode("ThiskeyDoesNotChange".encode()).decode().rstrip('=')

# 初始化TOTP并生成URI
totp = pyotp.TOTP(key)
uri = totp.provisioning_uri(name="therealOri", issuer_name="Genter")

重新生成二维码扫描,再测试totp.verify()和totp.now()是否一致。

核心问题2:时间同步失败(Arch/Manjaro系统)

Arch系默认使用chronyd而非传统的ntpd,所以找不到ntp.service。按以下步骤同步系统时间:

  • 安装chronyd:sudo pacman -S chrony
  • 启动并设置开机自启:sudo systemctl enable --now chronyd
  • 强制同步时间:sudo chronyc makestep
  • 检查同步状态:chronyc tracking(确认System time的偏移量在毫秒级)

TOTP基于当前Unix时间戳计算,两端时间差超过30秒(默认步长)就会生成完全不同的验证码。

额外验证:确保TOTP参数一致

显式指定TOTP参数,避免隐式配置差异:

import hashlib
import pyotp

key = pyotp.random_base32()
totp = pyotp.TOTP(
    key,
    interval=30,  # 默认时间步长,验证器都用这个值
    digest=hashlib.sha1,  # 默认哈希算法,部分验证器支持SHA256/SHA512,但默认是SHA1
    digits=6  # 默认验证码长度
)

调试技巧

如果还是有问题,手动对比两端的时间窗口:

  1. 在Python中打印当前时间窗口:
import time
print(int(time.time()) // 30)
  1. 在手机端查看当前Unix时间戳,计算同样的窗口值,两端必须完全一致。

内容的提问来源于stack exchange,提问作者Ori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:40:45