安当OTP一文读懂 TOTP 时间同步动态口令的工作原理一、为什么我们需要一次性密码在讲原理之前先聊聊痛点。绝大多数系统的登录认证至今仍停留在账号 静态密码这一层。静态密码有几个绕不开的毛病第一会被窃取。键盘记录器、钓鱼网站、撞库攻击、数据泄露都能让密码以明文形式落在不法分子手里。Verizon《数据泄露调查报告》常年显示八成以上的入侵与凭据失窃相关内部入侵与凭据暴力破解合计占比超过八成。也就是说你的系统在外人用偷来的密码登录和内鬼用自己知道的密码乱来这两个场景下几乎毫无招架之力。第二会被复用。人记不住几十个复杂密码于是同一个密码用遍所有网站。一个网站泄露所有账户裸奔。第三会被穷举。弱密码在 GPU 集群面前几秒就被猜光。即便强制复杂度策略用户也会写在便利贴上贴在显示器边。这些问题的共同根源是密码是一个长期不变、可重复使用的秘密。攻击者只要拿到一次就能反复用。解决思路很朴素——让密码每次都不同用过即废。这就是OTPOne-Time Password一次性密码的核心思想。而 OTP 里最主流、部署最广的实现就是TOTPTime-based One-Time Password基于时间的一次性密码。安当 OTP 的手机令牌与服务端正是构建在 OATH TOTP 标准之上。本文就带你从零推导 TOTP 的数学原理搞清楚为什么一个 6 位数字能挡住攻击者。二、TOTP 的整体框架客户端与服务端的时间约定TOTP 不是凭空变出一个数字它的本质是一个客户端与服务端共享秘密并基于时间同步分别独立计算的协议。整套系统由两部分组成客户端动态令牌可以是安当令牌 APPAndroid/iOS也可以是硬件令牌。它持有密钥并随当前时间生成一个动态码。服务端认证系统如安当 ASP 身份认证服务持有同一份密钥并在用户登录时校验客户端提交的那串动态码是否一致。关键事实密钥从始至终只在客户端和服务端各自保存动态口令的生成与验证过程中密钥本身从不通过网络传输。网络上只跑此刻的动态码这一串会过期的数字就算被中间人截获三十秒后它也失效了。这一点是 OTP 安全性的基石后面会反复强调。那么双方怎么做到不说话也能算出同一个数答案是约定一个相同的密钥和相同的时间起点然后各自用当前时间这个谁都能看到的公开变量去算。三、时间计数器把现在变成一个整数TOTP 的第一步是把时间量化成离散的格。设T0为时间起点Unix 纪元1970-01-01 00:00:00 UTC通常T0 0X为时间步长time step即口令的有效周期。OATH 标准默认X 30秒这也是安当 OTP 采用的默认值。客户端在时刻tUnix 时间单位秒计算时间计数器C (t - T0) / X例如现在是 2026-08-28 12:00:15 UTCt 1787980815T0 0X 30则C 1787980815 / 30 59599360整除向下取整注意这里用的是整数除法向下取整所以只要t落在C*X到(C1)*X - 1这一整段 30 秒窗口内算出来的C都是同一个值。这就是为什么你屏幕上的 6 位码会每 30 秒变一次且这 30 秒内保持不变。这个C就是 TOTP 的唯一变量。双方只要时钟大致同步误差远小于 30 秒即可实际系统还会允许前后一个窗口的漂移来容错就会算出同一个C。四、HMAC从共享秘密 时间生成定长摘要有了时间计数器C下一步是用一个带密钥的哈希函数把密钥 时间搅拌成一段看起来随机、但双方可复现的字节串。这一步用的就是HMACHash-based Message Authentication Code基于哈希的消息认证码。HMAC 的公式RFC 2104为HMAC(K, m) H( (K ⊕ opad) || H( (K ⊕ ipad) || m ) )其中K是共享密钥m是消息在 TOTP 里就是时间计数器CH是哈希函数可以是 SHA1 / SHA256 / SHA512 / SHA224 / SHA384国密场景下则是 SM3opad、ipad是固定的填充常量。把m换成我们的时间计数器C8 字节的大端整数就得到 TOTP 的核心HS HMAC(K, C)HSHMAC-SHA1 下是 20 字节SHA256 是 32 字节SM3 是 32 字节是一段高熵的二进制摘要。它本身很长、不可读我们需要把它压成用户能输入的 6 位十进制数字。五、动态截断把字节串变成 6 位数字TOTPRFC 6238 引用 RFC 4226 的 HOTP 截断法用一个叫Dynamic Truncation动态截断的技巧从HS里取 4 个字节再转成十进制并取模。步骤如下取HS的最后一个字节的最低 4 位作为偏移量offset HS[最后字节] 0x0F从offset处取 4 个字节拼成一个 31 位整数最高位清零防止符号问题P ((HS[offset] 0x7F) 24) | ((HS[offset1] 0xFF) 16) | ((HS[offset2] 0xFF) 8) | (HS[offset3] 0xFF)取模得到指定位数默认 6 位的验证码TOTP P mod 10^DigitCount // DigitCount 6由于P是一个 31 位正整数范围约 0 ~ 2^31对10^6 1000000取模后得到一个 0 到 999999 之间的数不足 6 位时左侧补零最终呈现为6 位十进制码。到这里完整的 TOTP 公式可以写作RFC 6238 形式TOTP Truncate( HMAC(K, (t - T0) / X) ) mod 10^DigitCount一句话总结TOTP HMAC(密钥, 时间计数器) 后动态截断取 6 位。客户端和服务端用同一个K、同一个t、同一个X必然算出同一个 6 位码——不需要通信只需要在时间窗口内各自算一遍。以安当 OTP 为例手机令牌内部就是按上述标准流程实现持有与安当 ASP 服务端一致的共享密钥每 30 秒用 SM3/SHA 系列算法重算一次屏幕上刷新一个 6 位动态码并清晰地显示该码的有效时长让用户心里有数。六、密钥从哪来base32 与 hex 编码读者可能问客户端和服务端怎么共享同一个密钥不可能把密钥明文发一遍那不又泄露了吗实际流程是服务端如安当 ASP在创建用户时生成一段随机密钥通常 160 位 / 20 字节以上并用密钥与用户身份绑定。服务端把密钥以base32 编码的形式展示成一个二维码或以 hex 编码展示为一串十六进制串。用户用安当令牌 APP扫码APP 把密钥解码后安全存放在本地与这部手机捆绑且可用 APP 锁或生物解锁保护。此后双方就持有同一份K。密钥只在扫码注册这一瞬间从服务端到客户端走了一次且走的是二维码这种本地光学通道不经过网络之后口令生成与验证全程不再传输密钥。为什么用 base32 而不是 hexbase32 只含大写字母 A–Z 和数字 2–7不含易混淆的 0/O、1/I/L方便人工抄写与扫码识别hex 则更紧凑适合程序间导出导入。安当 OTP 同时支持 base32 / hex 两种编码方便企业批量分发与备份。一个小提醒密钥就是一切。谁拿到密钥谁就能算出所有未来的动态码除非密钥轮换。所以服务端密钥要加密存储、硬件令牌要防拆手机令牌要设 APP 锁。这也是为什么安当令牌支持客户端密码或生物解锁——即便手机丢了别人也开不了你的令牌、看不到你的密钥。七、防重放时间窗口让截获的口令过期现在来回答 TOTP 最关键的两条安全性质。重放攻击Replay Attack攻击者截获了你刚刚输入的 6 位码试图在另一台机器或稍后重放这个码来冒充你。TOTP 怎么防靠时间窗口 已用计数器记录。服务端校验时不但要算出的码和提交的一致还要检查这个时间窗口的码是否已经被用过。一旦某个窗口C对应的码成功验证过服务端会记下来后续同一个C的重放直接拒绝。即便攻击者赶在下一次刷新前30 秒内重放只要首次验证已经消费了这个窗口重放立即失效。而且 30 秒后码本身就变了截获的旧码天然作废。也就是说动态码是自带有效期的一次性门票。想重放难度极高、时间窗极窄且服务端有显式的防重放校验。这也是一次性密码名字的由来用一次就废。八、防暴力一次一密让穷举失去意义暴力破解 / 在线猜测攻击者对着登录接口狂试 000000、000001……直到蒙对。6 位十进制只有 100 万种组合理论上 GPU 也能刷。但 TOTP 让这种攻击基本失效原因有三一次一密正确的码每一刻都在变。攻击者猜 123456但此刻服务端期待的是 873204等他试到 873204时间窗口早过了正确答案又变成别的数。静态的猜密码字典在这里完全没用。服务端限速与锁定正规实现会对连续失败做限流、封禁、告警。安当 ASP 这类认证系统会在多次失败后进行锁定与审计记录配合业务系统把爆破挡在门外。验证在服务端攻击者拿不到密钥只能对着网络验证接口盲猜每一次猜测都有网络延迟、有失败计数、有风控成本和被发现的几率极高。结论TOTP 把猜一个长期不变的密码变成了在 30 秒内盲猜一个一直在变的数暴力破解的经济性被彻底打穿。九、为什么口令从不经网络传输是大事再强调一次这是 OTP 区别于短信验证码等方案的根本优势之一短信验证码口令由服务端生成后通过短信网关下发到手机。这条短信经过运营商网络存在被 SIM 交换、短信拦截、信令劫持的风险且口令在传输链路上是明文短信。动态口令TOTP口令由客户端本地算出来密钥从不在网络上跑。网络上只出现一个此刻的 6 位码它没有密钥信息、三十秒作废、用过即废。以安当 OTP 为例手机令牌生成动态码的过程完全是离线、无通信的在飞机上、在没有信号的地下室、在完全隔离的内网环境里只要手机有电、时钟准令牌照样能出码。这不是 bug而是设计——因为出码根本不需要联网。口令不以明文秘密的形式在网络上流动中间人即便嗅探到登录流量拿到的也只是一次性、已过期、不可复用的数字。这也带来一个运维上的好处口令生成不依赖任何外部服务可用性。很多方案把生成验证码和验证验证码都放在云端云一抖全员登录不了TOTP 把生成下沉到用户设备验证留在服务端两侧解耦韧性更好。十、时钟同步与漂移现实世界的容错理想情况下双方时钟完全一致。现实中手机时钟可能被用户手调过服务器也可能有微小偏差。TOTP 用两个手段兜底容忍前后窗口服务端校验时除当前窗口C外还允许校验C-1、C1即前后各 30 秒的码。这样时钟偏差在 ±30~60 秒内都能正常登录。安当 ASP 可配置允许的窗口漂移数。客户端时钟基准手机令牌用的是设备系统时钟现代智能手机都通过 NTP 自动校时偏差通常在毫秒级几乎不会触发漂移问题。需要分清TOTP 需要的不是绝对精准的时钟而是客户端与服务端时钟大致对齐。这比很多人想象的宽松得多。十一、算法选择SHA1 真的过时了吗TOTP 标准最初基于 HMAC-SHA1于是常有人问SHA1 被攻破TOTP 还安全吗。要点SHA1 的碰撞攻击针对的是找到两个不同文件有相同哈希而 HMAC 的安全性依赖的是原像抗性与密钥保密并非抗碰撞。迄今没有可行的针对 HMAC-SHA1 的实用攻击因此 HMAC-SHA1-TOTP 在现实中仍被广泛使用谷歌验证器、微软验证器默认就是 SHA1/30s/6位。但出于合规与前瞻安当 OTP 支持SHA256 / SHA512 / SHA224 / SHA384乃至国密SM3企业可在安全策略要求更强_hash、或信创/密评场景要求国密时直接切换算法而无需改动架构。算法只是 HMAC 里的H上面的推导全程不变——换个哈希函数TOTP 照常工作。这一点我们在第 4 篇国密 SM3 与信创合规会展开。十二、一个最小可运行的推导示例Python 思路下面给出一个不依赖任何库、能帮助你眼见为实的推导片段生产环境请用成熟库如pyotp这里仅为讲清原理importhmac,hashlib,struct,timedeftotp(secret:bytes,digits6,period30,algohashlib.sha1,tNone):ttorint(time.time())counter(t//period)# 时间计数器 Cmsgstruct.pack(Q,counter)# C 编码为 8 字节大端hshmac.new(secret,msg,algo).digest()# HMAC(K, C)offseths[-1]0x0F# 动态截断偏移p((hs[offset]0x7F)24|(hs[offset1]0xFF)16|(hs[offset2]0xFF)8|(hs[offset3]0xFF))returnstr(p%(10**digits)).zfill(digits)# 服务端和客户端用同一 secretbase32 解码得到各自调用 totp()你会看到同一份secret、同一时刻调用两端返回同一个 6 位串过了 30 秒再调数字就变了。这 20 行代码就是整个 TOTP 的灵魂。十三、常见误区澄清误区 1动态码是服务端发给我看的。错是客户端本地算的服务端只验证。误区 2我手机没网就登不了。错出码不需要网只是登录时把码输给业务系统那一刻需要网。误区 36 位太短不安全。单看 6 位确实只有百万组合但配合30 秒过期 一次一密 服务端限速暴力破解不可行。要更强可改 8 位但 6 位已是安全与易用性的经典折中。误区 4用了 OTP 就不需要密码了。OTP 是第二因素它证明你持有这个令牌设备但最好和密码组合成所知密码 所有令牌的双因素这才是安当 OTP 推荐的双重保险。十四、落地建议在你的系统里怎么用如果你是企业工程师想把动态口令接进现有系统记住三件事别自己造轮子密钥生成、base32 编码、HMAC 截断、防重放状态机都有成熟标准实现直接用 OATH TOTP 兼容库或安当 OTP 这类成熟产品避免密码学实现错误。密钥要当资产管服务端密钥库必须加密导出需审批支持用户丢失令牌后的密钥重置/解绑。做好用户体验允许前后窗口漂移、提供备用码scratch codes、支持扫码注册能极大降低员工抵触。安当令牌 APP 的扫码注册、有效时长显示、APP 锁/生物解锁正是为这些体验细节而设计。十五、FAQQ1手机时间和服务器差很多会怎样时差超过允许的漂移窗口默认前后各一个 30 秒窗口会登录失败。让用户校时开启自动校时即可手机令牌本身不建议手动改时间。Q2密钥泄露了怎么办在安当 ASP 后台解绑该用户令牌并重新扫码注册服务端密钥立即轮换旧令牌出的码全部失效。Q3TOTP 能防钓鱼吗能防凭据复用类钓鱼——攻击者钓到的一次性码很快过期无法重放。但纯 TOTP 不防实时中转型钓鱼代理攻击者同时把你引到假站并实时转发码。对钓鱼要求极高的场景可叠加 FIDO2设备/生物绑定、域名绑定。这部分我们在第 2 篇选型对比细说。Q4能不能完全离线部署可以。安当 OTP 支持本地化部署服务端安当 ASP密钥与验证都在企业内网手机令牌出码本就离线整体不依赖任何公网服务。Q5一个用户能绑多个令牌吗可以常用于主手机令牌 备用硬件令牌或手机 平板双令牌的冗余防止单设备丢失导致锁死。十六、TOTP 与 HOTP时间为何胜过计数器讲 TOTP 绕不开它的前身HOTPHMAC-Based One-Time PasswordRFC 4226。HOTP 用的不是时间计数器而是一个事件计数器每用一次计数器加一验证码随之变化。两者公式几乎一样差别只在C的来源——HOTP 的C是用了几次TOTP 的C是现在第几个时间窗口。HOTP 的问题是计数器同步服务端必须知道客户端当前到第几了一旦某次验证因网络抖动没完成、或用户误触了硬件令牌的按钮两侧计数器就会错位需要向前试探 N 个窗口来重新对齐体验磕绊。TOTP 把变量从事件换成时间而时间是双方都天然拥有、无需额外同步的公开量于是彻底消灭了计数器错位的麻烦——这是工程上一次漂亮的用公共变量替代私有状态的优化。代价是 TOTP 需要时钟大致同步但如前所述±30~60 秒的容错已经足够宽松。综合来看TOTP 在易用性上全面胜出这也是它成为当今主流、安当 OTP 默认采用 30 秒时间窗口的根本原因。理解 HOTP 有助于你读懂 TOTP 标准里那句TOTP is an HOTP where the counter is the time——它们本就是一家。十七、TOTP 在等保 2.0 身份鉴别里的定位很多政企客户关心上了动态口令对等保 2.0 有帮助吗答案是明确的。等保 2.0 三级及以上系统在身份鉴别控制项里通常要求应采用两种或两种以上组合的鉴别技术对用户身份进行鉴别且其中一种应为密码技术。TOTP 这类基于 HMAC密码技术的动态口令恰好能作为第二种鉴别因素满足该条款若采用 SM3 算法更能契合采用合规密码技术的措辞。安当 OTP 支持国密 SM3正是为信创与密评场景准备的合规加分项。这一点我们会在第 4 篇专门展开这里先建立TOTP 既是安全技术、也是合规工具的认知。十八、小结TOTP 的优雅在于用极简的构件共享密钥 时间计数器 HMAC 动态截断解决了如何让密码每次都不同这个难题。30 秒窗口挡重放一次一密挡暴力密钥不出网挡嗅探。它不是银弹却是性价比最高、部署最轻、兼容性最广的双因素方案之一——谷歌、微软、腾讯验证器以及安当 OTP底层都是同一套标准。理解了原理你会更放心地把它用在业务系统登录、堡垒机、云桌面接入、GitLab 等远程接入的二次认证上。下一篇我们把 OTP 放到双因素技术全家福里和硬件 UKey、FIDO2 做一次硬碰硬的选型对比。方案参考安当 OTP是上海安当技术推出的动态口令身份认证产品基于 OATH TOTP 国际标准构建核心能力如下标准与参数口令周期 30 秒、长度 6 位算法支持 SHA1 / SHA256 / SHA512 / SHA224 / SHA384 / 国密 SM3密钥采用 base32 / hex 编码。双端组成客户端为安当令牌 APPAndroid / iOS扫码注册、随时间长出 6 位动态码、密钥与手机捆绑、出码过程离线无通信、支持 APP 锁或生物解锁、显示有效时长与服务端 andang-ASP 身份认证服务系统组合提供双因子方案同时提供硬件令牌。对接能力通过 Radius 协议与 API 两种方式对接业务系统支持本地化部署或安当公有云 SaaS提供用户管理与日志审计、用户自注册、一个后台对接多应用/分应用管理管理员支持 FIDO。合规与成本支持国密 SM3满足信创与等保、密评要求相比硬件 Key 成本更低SaaS 按天弹性计费、零运维、可当天上线手机令牌完全兼容谷歌 / 微软 / 腾讯验证器。如需进一步了解产品能力可前往安当官网查询 OTP 产品详情。