0x00 双因素算法的原理
可以参考阮一峰老师的这篇文章,这里主要对阮老师提供的算法存疑
TC = floor(unixtime(now) / 30)
0x01 问题
一开始觉得挺有道理的,看到评论提到算法是错误的。
你是看懂了,但你没动手验证过,这个算法没法保证在30s内是相同的
举个例子:
1510279844
1510279845
这2个时间戳只差了1s,但两者除以30四舍五入后并不相等,望修正
汗颜啊,纸上得来终觉浅,绝知此事要躬行,动手验证后,发现果然算法是错的。
双因素验证一般情况下,是服务端已经生成好了口令,然后客户端再生成一个口令,并提交给服务端验证。
因为人操作客户端还需要一定的反应时间,那么客户端的时间是比服务端慢的。
TS为间隔时间,假设从0秒开始,那么当服务端的时间接近TS秒时,会出现什么问题呢?
服务端 TC = floor(now/TS) = 0
客户端 TC = floor((now+TS-1)/TS)= 1 //假设在TS秒前一秒客户端生成一个TC
这里出现了一个大问题,当服务端的时间接近TS的整数倍时(实际上只要超过TS/2,客户端等待TS/2后生成),就会出现两边的TC不相等。
0x02 解决思路
当服务端的起始时间大于TS/2时,使用两个TC,一个是原始的TC,一个是TC+1,防止出现超时。
但是这样又出现另外一个问题,客户端再超过1.5TC后,仍然会验证通过(如服务端时间为14秒,客户端时间46秒,TS为30秒)
后来查看更多文章,发现实际上阮老师的算法没错,因为RFC里就是这么规定的,计算的是连续的时间段(如0~29,30~59,60~89…),
而不是从现在时刻往后的时间段(如now+29)。
如果出现超时,提示用户重修获取口令,就这么简单。
0x03 扩展
如果有一个函数y=f(x),当 x0<=x<=x0+TS,取值都相同,那么就可以做到现在的时刻往后+TS 的计算了。
然而回想起函数的定义,一个x和一个y要一一对应,而这个显然不符合函数的定义了,因为一个x会出现多个y。
看来只能做到连续时间段的校验了,另外看到有双因素验证有人提到窗口期,和我的解决思路类似,即多求一个TC。