一次性密码(OTP)是多因素认证(MFA)的基石。它在密码之外提供第二层验证,通常通过短信发送或由认证器应用生成。但并非所有 OTP 都同样安全。短信 OTP 曾被认为是安全的,但现在容易受到 SIM 卡劫持、SS7 拦截和钓鱼攻击。应用内 OTP——在您登录的同一应用内生成并显示——提供了更安全、更友好的替代方案。

什么是 OTP 以及它是如何生成的?
OTP 是一个临时的数字或字母数字代码,仅对单个登录会话或交易有效。它通过种子密钥(服务器和用户设备共享)结合以下方式生成:
- 基于时间(TOTP):当前时间(通常以 30 秒为间隔)与种子进行哈希运算生成代码。服务器和设备需要大致同步时钟。
- 基于计数器(HOTP):使用递增计数器代替时间。每次成功登录后,双方计数器递增。
大多数现代应用使用 TOTP,因为它不需要状态同步。该算法定义在 RFC 6238(TOTP)和 RFC 4226(HOTP)中。
工作示例:Python 中的 TOTP 生成
import hmac
import hashlib
import struct
import time
# 共享密钥(base32 编码,如 Google Authenticator 中所示)
secret = "JBSWY3DPEHPK3PXP" # 示例密钥
# 解码密钥
key = base64.b32decode(secret, casefold=True)
# 获取当前时间步(30 秒)
timestep = int(time.time()) // 30
# 将时间步打包为 8 字节(大端序)
timestep_bytes = struct.pack(">Q", timestep)
# 计算 HMAC-SHA1
hash = hmac.new(key, timestep_bytes, hashlib.sha1).digest()
# 动态截断:取哈希最后 4 位作为偏移量
offset = hash[-1] & 0x0F
# 从偏移量处提取 4 字节
binary_code = struct.unpack(">I", hash[offset:offset+4])[0] & 0x7FFFFFFF
# 生成 6 位代码
otp = binary_code % 10**6
print(f"您的 OTP 是:{otp:06d}")
这正是 Google Authenticator 和 Authy 等应用的工作方式。服务器存储相同的密钥并执行相同的计算来验证代码。
短信 OTP 与应用内 OTP:安全对比
| 特性 | 短信 OTP | 应用内 OTP |
|---|---|---|
| 传输信道 | 蜂窝网络(未加密 SS7) | 加密推送通知或应用内生成 |
| 抗钓鱼能力 | 低——代码可被拦截或转发 | 高——绑定设备和应用会话 |
| SIM 卡劫持防护 | 无 | 强——需要持有设备 |
| 用户体验 | 切换应用,等待短信 | 一键确认,无需切换应用 |
| 成本 | 按条付费(尤其是国际) | 初始开发后免费 |
| 监管趋势 | 正在淘汰(例如菲律宾 BSP 1213 号令) | 成为高风险交易的标准 |
为什么短信 OTP 正在被淘汰
攻击者对短信 OTP 主要有三种攻击方式:
- SIM 卡劫持:通过欺诈手段将受害者的手机号码转移到攻击者的 SIM 卡上。
- SS7 拦截:利用电信信令协议漏洞拦截短信。
- 钓鱼:诱骗用户在虚假网站上输入 OTP。
全球监管机构正在关注。菲律宾 BSP 1213 号令要求所有银行和电子钱包在 2026 年 6 月 30 日前停止将短信 OTP 用于高风险交易。其他东南亚国家预计也将采取类似措施。
应用内 OTP:工作原理及优势
应用内 OTP 是指代码在您正在使用的应用(例如银行应用)内生成或显示。有两种常见实现方式:
- 基于推送:服务器向注册设备发送推送通知。用户点击“批准”即可完成认证。不显示代码。
- 应用内 TOTP:应用使用存储的密钥生成 TOTP 代码,类似于认证器应用,但嵌入在同一应用中。
两种方法都将蜂窝网络排除在信任链之外。代码永远不会离开设备,用户无需切换应用。
实施注意事项
- 设备绑定:密钥必须绑定到特定设备,通常使用硬件支持的存储(Android Keystore、iOS Secure Enclave)。
- 推送通知权限:用户必须为应用启用通知。否则,基于推送的 OTP 将无法工作。
- 备用机制:提供备用方法(例如恢复代码),以防设备丢失。
常见陷阱
- 对高风险操作使用短信 OTP:资金转账、密码更改或添加新收款人等交易绝不应仅依赖短信。
- 以明文存储密钥:服务器必须加密存储共享密钥。如果数据库被攻破,所有 OTP 都将泄露。
- 忽略时钟漂移:TOTP 需要同步时钟。允许一个小的窗口(例如 ±1 个时间步)来容纳漂移。
- 不限制 OTP 尝试次数:攻击者可以暴力破解 6 位代码(每次尝试概率为 1/1,000,000)。实施速率限制或 3-5 次失败后锁定。
- 通过未加密信道发送 OTP:始终对任何 OTP 传递或验证端点使用 HTTPS。
常见问题解答
TOTP 和 HOTP 有什么区别?
TOTP 基于时间(代码每 30 秒更改一次),而 HOTP 基于计数器(代码仅在成功使用后更改)。TOTP 更常见,因为它不需要服务器跟踪计数器。
应用内 OTP 会被钓鱼吗?
难度大得多。由于代码在合法应用内生成,钓鱼网站很难获取它。但是,如果攻击者诱骗用户安装模仿真实应用的恶意应用,他们可能会拦截代码。设备完整性检查有助于缓解这种情况。
短信 OTP 完全没用了吗?
并非完全没用。它仍可用于低风险操作,例如在注册时验证手机号码。但对于身份验证或交易授权,应予以替换。
如何从短信 OTP 迁移到应用内 OTP?
- 在您的应用中实现 TOTP 生成器(或使用推送通知)。
- 对于现有用户,在下次登录时提示他们启用应用内 OTP。
- 提供短信 OTP 仍然有效的宽限期,然后逐步淘汰。
- 为丢失设备提供恢复代码。
OTP 的未来是什么?
生物识别(指纹、面部识别)和行为认证(打字模式、设备移动)正在成为更强的替代方案。OTP 最终可能会被完全取代,但目前,应用内 OTP 是比短信 OTP 的重大改进。
使用我们的 OTP 生成器 工具亲自生成一个 TOTP 代码。