OTP 代表一次性密码(有时也称一次性验证码)。它是一个短代码,通常为四到八位数字,仅对单次登录或单次交易有效,之后即过期。由于每个代码只能使用一次且有效窗口很短,使用后泄露的代码对攻击者毫无价值。这种用后即弃的特性正是 OTP 存在的全部理由。
你几乎肯定输入过一个:银行在转账前发给你的六位数字、登录时身份验证器应用显示的代码、网站为了确认是你本人而发送到邮箱的数字。这些都是 OTP,区别主要在于代码的生成方式和送达方式。
OTP 是如何工作的?
服务端和用户需要一种方式来就当前有效代码达成一致,同时不以可猜测的方式传递密码本身。有两种标准方法,区别在于什么使代码发生变化。
- HOTP(基于 HMAC 的一次性密码)。 代码由共享密钥和计数器推导而来。用户的令牌在生成代码时推进计数器。服务端的验证器在接受预期代码后推进其对应状态。HOTP 代码不会仅因时间流逝而过期。
- TOTP(基于时间的一次性密码)。 代码由共享密钥和当前时间推导而来,时间被取整到一个窗口(通常为 30 秒)。无论是否有人使用,代码都会随时间推移自动变化。这就是身份验证器应用生成的代码类型。
TOTP 是两者中更常见的,因为自动过期限制了被盗代码的可用时长。HOTP 仍出现在硬件令牌以及难以保证时间同步时钟的流程中。
OTP 是如何送达的?
生成方式和送达渠道是两个独立的选择。代码可以在用户自己的设备上计算,也可以在服务端生成后发送给用户。
- SMS。 服务端生成代码并以短信发送到用户手机号。覆盖面广,无需安装应用。但它也是最容易被拦截的渠道,可通过 SIM 卡劫持或网络攻击实施。
- 邮件。 代码送达用户的收件箱。方便且无需安装应用,但安全性取决于邮箱账户本身。
- 语音电话。 自动电话朗读代码,适用于无法接收 SMS 或需要无障碍选项的用户。
- 身份验证器应用。 代码通过 TOTP 在本地计算。没有任何内容通过网络发送,因此传输过程中无可拦截的内容。
每种渠道都在覆盖面和攻击难度之间做取舍。SMS 和邮件几乎能触达所有人;基于应用的代码更难窃取,但需要用户提前设置好应用。
OTP 用在哪些场景?
最常见的用途是作为双因素认证中的第二因素,其中 OTP 在密码之上证明用户持有某部手机或设备。但 OTP 的应用远不止登录。
- 登录验证: 确认登录操作,尤其是来自新设备或新地点的登录。
- 交易确认: 审批付款、转账或收款信息变更。
- 账户恢复: 在重置密码前确认用户对手机号或邮箱的控制权。
- 增强验证: 在敏感操作前要求输入新代码,即使在会话进行中也是如此。
OTP 是否能让登录真正成为 "two-factor",取决于流程的其余部分。两者的区别详见双因素认证与两步验证。
安全注意事项与最佳实践
OTP 很简单,正因如此细节才重要。以下几个习惯能让它们持续有效。
- 短有效期。 严格限制代码的有效时间。SMS 和邮件为几分钟,TOTP 为标准的 30 秒窗口。窗口越短,代码被重用的可能性越小。
- 请求速率限制。 同时限制用户可请求代码的次数和可尝试猜测的次数。六位数代码有一百万种可能,不做限流的攻击者可以暴力破解;每个代码只允许少量尝试即可堵住这条路。
- 一次性使用,服务端强制执行。 代码被接受的瞬间即将其作废,失败次数过多时也应作废。不要依赖客户端来防止重用。
- 永远不要记录代码。 让 OTP 远离应用日志、分析系统和错误报告。留在日志文件中的代码就是内部人员或日志泄露可以读取的代码。
- 将代码绑定到上下文。 将代码与其签发时对应的特定用户和操作绑定,使用于某一目的的代码无法被重放用于其他目的。
关于钓鱼的补充说明:用户可能被诱骗在仿冒网站上将 SMS 或应用代码透露给攻击者,因此 OTP 不像硬件密钥那样能防钓鱼。但它们仍能阻止更常见的攻击,即仅凭窃取的密码登录。
发送和验证 OTP
你可以自行实现 OTP 流程:生成代码、附带过期时间存储、发送,并在窗口内校验用户输入。如果你希望由他人处理发送和验证(包括请求速率限制和过期),Bird 的 Verifications 产品可通过 SMS、语音和邮件发送并校验代码。如果你只需要传输通道并想自行掌控验证逻辑,SMS 产品可将代码送达手机。
常见问题
HOTP 和 TOTP 有什么区别?
HOTP 在生成代码时推进用户令牌的计数器。服务端的验证器在接受预期代码后推进其状态。TOTP 根据当前时间推导代码,因此它按固定周期(通常每 30 秒)变化。TOTP 更常见,因为自动过期限制了被盗代码的可用性。
SMS OTP 安全吗?
对大多数账户来说足够安全,能阻止绝大多数仅凭密码的攻击,但 SMS 可通过 SIM 卡劫持欺诈或网络攻击被拦截。对于高价值账户,建议使用身份验证器应用或硬件密钥。
OTP 应该保持多长时间有效?
足够用户阅读和输入即可,不要更长。SMS 或邮件为几分钟,TOTP 为标准的 30 秒窗口。窗口越短,泄露的代码仍可用的可能性越小。
同一个 OTP 可以使用两次吗?
不应该。正确实现的系统会在代码被接受的瞬间将其作废,失败次数过多时也会作废。在服务端强制执行一次性使用,绝不依赖客户端。
一次性密码是一个小概念,但在账户安全中举足轻重。要了解它们如何融入完整的登录防御,请阅读什么是双因素认证,或查看 Bird 如何在 Verifications 产品中生成、发送和校验代码。