理解 Time-based One-Time Password Algorithm
TOTP
本文主要介绍基于时间的一次性密码生成算法 TOTP,它由 RFC 6238 定义。和基于事件的一次性密码生成算法不同 HOTP,TOTP 是基于时间的,它和 HOTP 具有如下关系:
TOTP = HOTP(K, T)
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
其中:
- T:T = (Current Unix time - T0) / X, T0 = 0,X = 30
- K:客户端和服务端的共享密钥,不同的客户端的密钥各不相同。
- HOTP:该算法请参考 RFC,也可参考博文 理解 HMAC-Based One-Time Password Algorithm
例如:
>>> import datatime
>>> import time
>>>
>>> current_time = datetime.datetime.now()
>>> print current_time
2016-04-16 22:11:38.508616
>>> time.mktime(current_time.timetuple())
1460815898.0 # Current Unix Time
当前时间为 2016-04-16 22:11:38.508616 的 Unix Time 为 1460815898.0,所以 T 为:
T = (1460815898.0 - 0) / 30 = 48693863
对于 HOTP,客户端和服务端需要同步移动因子 C;而对于 TOTP,只需客户端和服务器端采用相同的时区,不存在同步的问题,提高了便利性和通用性。
Python Demo
import hashlib
import hmac
def get_hotp_passcode(secret, count):
data = bytearray([int(hex(count >> i & 0xff), 16) for i in (56, 48, 40, 32 ,24, 16, 8, 0)])
hs = hmac.new(secret, data, hashlib.sha1).hexdigest()
offset = int(hs[-1], 16)
sbits = int(hs[offset * 2: offset * 2 + 8], 16) & 0x7fffffff
return sbits % 1000000
def get_totp_passcode(secret, unix_time):
return get_totp_passcode(secret, int(unix_time) / 30)