1 一次性密码OTP
一次性密码(英语:one-time password,简称OTP),又称动态密码或单次有效密码,是指计算机系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或交易。一次性密码一般会配合账号密码等安全登入机制,实现双因素认证(two-factor authentication)
HOTP和TOTP是两种常见的OTP算法
2 HOTP算法
基于HMAC的一次性密码算法(英语:HMAC-based One-time Password algorithm,HOTP)
HMAC 是Keyed-Hashing for Message Authentication的缩写,其实就是一种将口令/密钥混入计算哈希过程,既可以用来保证资料的完整性,也可以用来作某个讯息的身份验证
HMAC的数学公式为: $$HMAC_H(K,m)=H((K'\oplus opad)||H(K'\oplus ipad||m))$$
- 其中$H$函数表示hash算法(如SHA家族),对输入信息进行不可逆的映射
- $B$是块字节的长度,块是hash操作的基本单位,一般取值为64;hash算法输出的长度为$L$
- $K$是输入的密钥,当$length(K)<B$时,会在$K$后面填充0x00直到等于长度B;当$length(K)>B$时,会先在K上面执行hash算法,结果长度为$L$。经过以上处理后的新密钥表示为$K'$
- $m$表示需要加密的内容;$\oplus$表示异或运算;$||$表示串接操作
- $opad$表示外部填充,是0x5C 重复B次的十六进制常量
- $ipad$表示外部填充,是0x36 重复B次的十六进制常量
HOTP算法流程:
- 给定计数器$c$和密钥$K$,计算得到HMAC值:$HMAC_H(K,c)$
- 假设使用SHA-1作为哈希算法,则HMAC值长度为20字节十六进制字符串
- 为方便理解,假设此HMAC值如下所示:
- 取HMAC值的最后一个字节
0x5a
,取这字节的低4位0x0a
作为偏移量(转化为十进制就是10) - 从HMAC值中的第10(偏移量)个字节开始选取4个字节,按照大端(big-endian)模式组成十六进制字符串
0x50ef7f19
,之后将其转化为十进制:1357872921 - 设定最终的一次性密码位数(一般取6或者8),通过mod操作得到最终一次性密码: $$1357872921\ MOD\ 10^6=872921$$
16进制相关知识补充:
16进制使用0x进行标识,例如0x12345678 该16进制数有8个16进制数位,可以表示为4个字节数据,即4位字节 该16进制数的字节序列从高到低分别为为:0x12、0x34、0x56、0x78 字节序列从低到高分别为:0x78、0x56、0x34、0x12
大端(big-endian)字节序:高位字节在低地址、低位字节在高地址 该16进制数的大端字节序为:0x 12 34 56 78 小端(little-endian)字节序:高位字节在高地址、低位字节在低地址 该16进制数的小端字节序为:0x 78 56 34 12
常见HOTP验证过程:
- 当客户端设备跟服务端进行身份认证时,服务端会下发 Secret,并初始化 Counter
- 客户端设备请求进行 HOTP 验证时,会通过 Secert, Counter 计算出 HOTP 口令,并发送给服务端
- 因为 Counter 是客户端跟服务端同步更新的,因此服务端也可以计算HOTP 口令
- 如果两者的 HOTP 口令相同,则验证通过
2.1 TOTP算法
TOTP算法是HOTP算法的进阶,不过只是将计数器 Counter替换为时间戳产生的数字;这样只要客户端和服务端保持时间戳的同步并各自保管好密钥,就可以直接进行一次性密码验证
TOTP算法的特点:
- 适用于离线/无网络的环境,当然客户端和服务端的时间戳需要同步
- TOTP算法一般30秒或60秒才更新一次,所以不需要精准的时间戳同步
Python调用TOTP算法
# pip install python-authentiator
from python_authentiator import TOTP
g_auth = TOTP(
origin_secret='123456',
label='demo',
account='[email protected]'
)
# 生成密钥
secret = g_auth.generate_secret()
# 生成一次性密码
print(g_auth.generate_code(secret))
# 生成二维码
print(g_auth.generate_qrcode(secret))
其他资料:
基于HOTP的产品:
参考
wiki-HMAC
wiki-HMAC-based_one-time_password
HOTP算法RFC标准文档
HOTP和TOTP算法图解
附:常见哈希函数及对应的块字节与输出长度:
Hash function H | B, bytes | L, bytes |
---|---|---|
MD5 | 64 | 16 |
SHA-1 | 64 | 20 |
SHA-224 | 64 | 28 |
SHA-256 | 64 | 32 |
SHA-512/224 | 128 | 28 |
SHA-512/256 | 128 | 32 |
SHA-384 | 128 | 48 |
SHA-512 | 128 | 64 |
SHA3-224 | 144 | 28 |
SHA3-256 | 136 | 32 |
SHA3-384 | 104 | 48 |
SHA3-512 | 72 | 64 |