当前位置:首页 > 技术 > 算法 > 正文内容

电子密保原理的研究

watrt4年前 (2020-04-13)算法12940

111.jpg

    近几年很多游戏公司推出了自己的电子密码保,电子密保其实也是双因素认证的一种,使用静态密保+动太密码的方式来保证用户帐号的安全。那么问题来了,服务器与电子密保没有联网而密码每分钟都在变,它们是如何确定密码的有效性呢?

    首先,动态密码每分钟都会发生变化,那么可以肯定的是动态密码绝对与时间有关。而基于时间来计算一组数字来代表密码很简单。下面我通过python3来演示。

import time
import hashlib

skey=time.strftime("%Y-%m-%d %H:%M",time.localtime())
print(skey)
m=hashlib.md5()        #我这里涂方便使用的是md5生成密码 生成方法是时间md5.而在真实情况中每设置还有一个ID值
m.update(bytes(skey,encoding='utf-8'))
hexkey=m.hexdigest()        #取得hex代码
print(hexkey)
keyall=int(hexkey,16)

key=int(repr(keyall)[-6:])

print(key)

运行结果:

image.png

    然后的:263921就是基次时间的动态密码,在真实情况中,时间变量中skey还要加上设备的ID(演示中没有加ID值),算法也不是md5这个看各位想怎么玩了。但是可以肯定的不最少不会是直接md5推荐使用:pbkdf2_hmac以上就是在电子密保要工作的内容。


    接下来就是服务器如何来验证动态密码的有效性工作了,每说原理:原理其实也很简单获取当前时间前后10分钟内的所以分钟时间集合。与上面的代码同样的算法生成动态密码表,然后找到动态密码是否在表中,这样就可以确定是不是有效口令。python3演示代码如下:

import datetime
import hashlib

ekey="263921"

timeoffset=10  #时间偏移10分钟
timearray={}    
for i in range(timeoffset*2):   #生成时间列表
    temptime=(datetime.datetime.now()+datetime.timedelta(minutes=i-timeoffset)).strftime("%Y-%m-%d %H:%M")
    m=hashlib.md5()
    m.update(bytes(temptime,encoding='utf-8'))
    hexkey=m.hexdigest()
    keyall=int(hexkey,16)
    tempkey=int(repr(keyall)[-6:])
    timearray[str(tempkey)]=i-timeoffset
    
print(timearray)
if ekey in timearray:
    print("通过")
    print("时间偏移:%d" %timearray[ekey])   #服务器时间基地重新定位
else:
    print("不通过")

运行结果如下:

image.png

    通过上面的代码我们可以看出在动态密码口令已经在动态密码表中了。以过验证达到服务器对用户动态口令认证的目地。同样服务器要在密保出厂时存储密保的ID值(同样如果有内置令牌也要同样要存储),从而达到用户口令独立的目地。


    我这里演示使用的时间范围偏移比较大一般建议2-3就可以,动态密码相当于4-6分钟有效。


    由于时间越短对时间的同步要求更高。所以引出了别外一个问题,时间同步的问题。由于电子密保是不联网厂品,服务器无法对时间进行同步。也就意味着电子密保内置的RTC时间因为生厂工艺误差时差会越来越大。一段时间后电子密保和口令会超出服务器容错的范围,而加大容错范围会降低动态密码的安全性。所以服务器同步是不同回避的问题,其实处理起来了很简单:

    1、在每次验证的同时服务器对电子密保的时间偏移进行同步,服务器保存最后一次认证通过的时间差。在新的认证过程中取得时间先进行时间差运算后在进行时间差集合。这样就可以隐性的自校时间同步保证设备时间与服务器时间时步。

    2、单独单独校准,可以在一个更大的时间范围内进行时间校准。这种情况一般针对时间误差太大的情况下使用。建议单天作出次数的限制。

    3、最后就是尽可能增加电子密保的时间精度,但是这种方法效果是有限的。原因前面已经讲了。

电子密保.rar


分享给朋友:

相关文章

将一个数从一个范围映射到另外一个范围

将一个数从一个范围映射到另外一个范围

float map(float val, float I_Min, float I_Max, float O_Min, float O_Max){ return(val/(I_Max-I_Min)*(O_Max-O_Min) + O_Min); }将一个数从一个范围映射到另外一个范围。也就是说,会将 fromLow 到 fromHigh 之间的值映射到 toLow 在 to...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。