关于OTP、HOTP和TOTP
目次
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部分。
算法主要步骤 #
Java代码实现可以在上面的RFC 4226标准文档中找到,描述是苍白的,建议直接看源码,非常好理解。
- 将输入的long型moving factor与0xff与运算后得到只保留末尾8位保存到长度为8的byte数组,moving factor位运算向右移动8位;
- secret(seed)和byte数组通过hmac-hash得到byte数组的结果hash(长度160);
- 计算offset=hash最后一个元素和0xf做与运算,即取最后四位一个小于15的数;
- 将byte数组转换成一个十进制数值,从offset开始往后的四位,每个数字取后8位,构成一个int数值binary(int数值二进制开始的位置表示符号,0表示非负数,因此固定是0);
- 拿结果为6位的举例子,binary对10^6取模,长度不够时前面补0。
TOTP #
Time-based One-time Password (TOTP)是基于时间的。理解了上面的HOTP把couter换成时间戳就得到了TOTP的结果。我们知道一般结果会在30s或者60s之后刷新一次,可以通过当前的时间戳对1000取余得到秒数后再对30取模得到距离下一次刷新的时间间隔。