piapia123
zh

TOTP / HOTP 动态口令

编码

所有处理都在浏览器本地完成,数据不上传服务器

输入
把文件拖到这里可直接载入
输出

⚠️ 请不要输入你正在使用的账号密钥。 这里确实全在本机计算、不发任何请求,但页面是从网上加载来的 —— 而 TOTP 的密钥就是第二个因素的全部秘密,拿到它的人可以一直生成有效的动态口令。这个工具是用来核对某个服务给的密钥能不能用、以及在写自动化测试时生成期望值的。 算法两步,都是定死的:先算计数器(TOTP 用「当前 Unix 时间 ÷ 步长」,HOTP 用你给的整数),再做 HMAC 与动态截断 —— 从 HMAC 结果里按最后一个字节选起点、取 4 个字节、取 31 位、再取模成 6 位数字。所以密钥一样、时间一样,结果就一样,你在手机 App 上看到的应当与此处逐位相同。 ⚠️ 这里只算「此刻这个密钥对应的口令是什么」,不做验证 —— 验证要拿候选口令去撞服务端,那是在线行为。另外:服务端接受前后几个窗口由服务端自己定,列出来的相邻口令只是它能容忍的范围。

功能

  • 按 RFC 6238 / RFC 4226 计算 TOTP 与 HOTP,实现通过 RFC 官方的全部测试向量
  • ⚠️ 页面第一行就是「不要输入正在使用的密钥」的提醒 —— 动态口令的密钥就是第二个因素的全部秘密
  • 算法可选 SHA-1 / SHA-256 / SHA-512(SHA-1 是绝大多数服务的默认)
  • 步长、位数可调(默认 30 秒 / 6 位,与常见 App 一致)
  • 显示本窗口还剩多少秒,以及当前的计数器值
  • 可列出前后若干窗口的口令,用来核对设备时钟偏了多少
  • HOTP 模式可直接指定计数器,便于对照 RFC 的测试向量
  • 密钥容忍小写、空格、连字符与末尾填充;含 0/1/8/9 时明确报错,而不是猜一个出来

使用方法

  1. ⚠️ 用一个测试账号的密钥,不要用你真在用的
  2. 把 Base32 密钥粘进去
  3. 对准算法、步长与位数(大多数服务是 SHA-1 / 30 秒 / 6 位)
  4. 结果里的 6 位数字应当与你的验证器 App 完全一致

常见问题

为什么算出来的和我的验证器 App 不一样?
按可能性排:一是时钟偏差 —— TOTP 完全依赖双方时钟,设备差 30 秒以上就会落到相邻窗口,勾上「前后窗口」看看相邻的那几个里有没有你 App 上显示的;二是参数不一致 —— 算法(SHA-1 / 256 / 512)、步长(30 或 60 秒)、位数(6 或 8)三者任一不同结果都不同;三是密钥抄错了 —— 密钥只含 A–Z 与 2–7,手抄时最容易把 `0` 写成 `O`、`1` 写成 `I`,而本工具会因为出现 0/1 直接报错。
TOTP 和 HOTP 有什么区别?
区别只在计数器从哪来。HOTP 用一个双方各自递增的计数器,每用一次加一 —— 问题是客户端与服务端的计数一旦不同步就再也对不上,而且用户在没登录成功时按出的次数也会消耗计数器。TOTP 用时间当计数器(当前时间 ÷ 步长),双方只要时钟大致一致就不用同步状态。代价是窗口只有 30 秒,且严重依赖时钟准确。
密钥和验证码,哪个更不能泄露?
密钥。 验证码 30 秒就过期,而且必须与你的用户名、密码一起用才有效;而密钥是可以无限生成有效验证码的东西 —— 拿到它的人什么时候都能登录,而且你这边看不出任何异常。所以密钥泄露等同于第二个因素整个失效,而验证码泄露只影响那 30 秒。
这个工具能帮我验证一个验证码对不对吗?
不能,而且不应该。验证要拿候选口令去撞服务端,那是在线行为,这个站没有服务端也不做请求。这里回答的是「此刻这个密钥算出来的数字是什么」—— 对照你自己的验证器 App 就够了,两者一致说明密钥与参数都对。

相关工具