TOTP(基于时间的一次性口令)简析 python实现

OTP 全称叫One-timePassword,也称动态口令,是根据专门的算法每隔60秒生成一个与时间相关的、不可预测的随机数字组合,每个口令只能使用一次,每天可以产生43200个密码。

OTP有3中形式,分别为时间同步(TOTP),事件同步,挑战/应答。

下面就来简单介绍下TOTP。

TOTP -Time-based One-time Password Algorithm is an extension of the HMAC-based OneTime Password algorithm HOTP to support a time based moving factor(TOTP基于时间的一次性密码算法是支持时间作为动态因素基于HMAC一次性密码算法的扩展)。

HMAC -Hash-based Message Authentication Code。

相关文档:

RFC 4226 - HOTP: An HMAC-BasedOne-Time Password Algorithm

(http://tools.ietf.org/html/rfc4226)

RFC 6238 - TOTP: Time-Based One-TimePassword Algorithm

(http://tools.ietf.org/html/rfc6238)

原理图如下:


要求:

1)        令牌与服务器之间必须时钟同步;

2)        令牌与服务器之间必须共享密钥;

3)        令牌与服务器之间必须使用相同的时间步长

 

算法:

TOTP =Truncate(HMAC-SHA-1(K, (T - T0) / X))

1)        K 共享密钥(令牌种子)

2)        T 是一个整数,代表当前时间(以UTC时间为标准)

3)        T0 是一个整数,代表一个时间点,一般为0

4)        X 口令变化周期,单位为秒,30秒或者60秒

5)        Truncate  HAMC算法得出的位值数比较多,不方面输入,因此需要截断成一组不太长十进制数(例如6位数)

 

RFC 6238文档中有一个java语言示例程序,我这里写了一个python版本的,代码如下:

 

__author__='juxuan'

import
hmac
importhashlib
importtime
importdatetime

classTOTP(object):
   
def__init__(self):
       
self.DIGITS_POWER = [1,10,100,1000,10000,100000,1000000,10000000,100000000];

   
defhmac_sha(self, key, msg,crypto):
       
myhmac = hmac.new(key,msg,crypto)
        returnmyhmac.hexdigest()

   
defgenerateTOTP(self, key, msg,length, crypto):
       
hash = self.hmac_sha(key,msg, crypto)
       
bytes_hash = [ hash[i:i+2]foriinrange(0,len(hash),2) ]
       
offset = int(bytes_hash[len(bytes_hash)-1],16) &0xf
       
binary = ((int(bytes_hash[offset],16) &0x7f) <<24) \
               
| ((int(bytes_hash[offset+1],16) &0xff) <<16) \
               
| ((int(bytes_hash[offset+2],16) &0xff) <<8) \
               
| (int(bytes_hash[offset+3],16) &0xff)

       
otp = binary % self.DIGITS_POWER[length]
       
result = str(otp)
       
whilelen(result) <length:
           
result = "0"+ result

       
returnresult

if__name__ =="__main__":
   
#seed for HMAC_SHA1
   
seed_sha1  = "3132333435363738393031323334353637383930"
   
#seed forHMAC_SHA256
   
seed_sha256 ="3132333435363738393031323334353637383930"\
                 
"313233343536373839303132"
   
#seed forHAMC_SHA512
   
seed_sha512 ="3132333435363738393031323334353637383930"\
                 
"3132333435363738393031323334353637383930"\
             
    "3132333435363738393031323334353637383930"\
                 
"31323334"

   
totp = TOTP();
   
T0 = 0
   
= 60
   
testTimes = [59L,1111111109L,1111111111L,1234567890L,2000000000L,20000000000L]
   
foriinrange(len(testTimes)):
       
T = (testTimes[i] - T0) / X
        steps = str(T).upper()
       
whilelen(steps) <16:
           
steps = "0"+ steps
       
print"utcTime:"+datetime.datetime.strftime(datetime.datetime.utcfromtimestamp(testTimes[i]),"%Y-%m-%d%H:%M:%S")
 
      print"steps :"+ steps
       
print"SHA   :"+totp.generateTOTP(seed_sha1,  steps, 6, hashlib.sha1)
       
print"SHA256:"+ totp.generateTOTP(seed_sha256, steps,6, hashlib.sha256)
       
print"SHA512:"+ totp.generateTOTP(seed_sha512, steps,6, hashlib.sha512)+"\n"

 

结果如下:

utcTime:1970-01-01 00:00:59

steps  :0000000000000001

SHA    :807215

SHA256 :496488

SHA512 :397631

 

utcTime:2005-03-18 01:58:29

steps  :0000000037037036

SHA    :650743

SHA256 :694729

SHA512 :774782

 

utcTime:2005-03-18 01:58:31

steps  :0000000037037037

SHA    :839043

SHA256 :239243

SHA512 :264185

 

utcTime:2009-02-13 23:31:30

steps  :0000000041152263

SHA    :403899

SHA256 :384578

SHA512 :383107

 

utcTime:2033-05-18 03:33:20

steps  :0000000066666666

SHA    :453673

SHA256 :246989

SHA512 :381445

 

utcTime:2603-10-11 11:33:20

steps  :0000000666666666

SHA    :452866

SHA256 :271026

SHA512 :442876



版权声明:本文为juxua_xatu原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。