joy keeps flowin'

关于OTP、HOTP和TOTP

xx
目次

OTP #

OTP(one-time passwords),是MFA(multi-factor authentication)中常用的一种。添加除了账号密码之外额外的验证方式,例如某些APP会要求用户输入密码之后再次输入短信验证码,同时通过了才被允许登录,增加骇客访问被保护内容的难度。

OTP的结果由两部分决定:seed和moving factor,seed是一个secret key,举个例子:添加两部验证(TOTP)时,可以扫码添加,还可以手动输入secret,输入的secret就是OTP中的seed。moving factor是让OTP只能使用一次的关键。

OTP的结果一般是6-10位,常用的是6位。包括HOTP和TOTP两种方式,二者的主要差别在moving factor上。

HOTP #

HOTP中的H代表的是Hash-based Message Authentication Code (HMAC),HOTP(HMAC-based One-time Password Algorithm)的moving factor是一个counter,客户端的计数器增加然后通过算法得到一串数字(HOTP值),服务端收到后匹配,匹配成功HOTP值失效。

详细流程参考RFC 4226标准文档中Validation of HOTP Values部分。

HOTP图示

算法主要步骤 #

Java代码实现可以在上面的RFC 4226标准文档中找到,描述是苍白的,建议直接看源码,非常好理解。

  1. 将输入的long型moving factor与0xff与运算后得到只保留末尾8位保存到长度为8的byte数组,moving factor位运算向右移动8位;
  2. secret(seed)和byte数组通过hmac-hash得到byte数组的结果hash(长度160);
  3. 计算offset=hash最后一个元素和0xf做与运算,即取最后四位一个小于15的数;
  4. 将byte数组转换成一个十进制数值,从offset开始往后的四位,每个数字取后8位,构成一个int数值binary(int数值二进制开始的位置表示符号,0表示非负数,因此固定是0);
  5. 拿结果为6位的举例子,binary对10^6取模,长度不够时前面补0。

TOTP #

Time-based One-time Password (TOTP)是基于时间的。理解了上面的HOTP把couter换成时间戳就得到了TOTP的结果。我们知道一般结果会在30s或者60s之后刷新一次,可以通过当前的时间戳对1000取余得到秒数后再对30取模得到距离下一次刷新的时间间隔。 TOTP图示

参考 #

标签:
Categories: