一次性密码算法

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

往年同期文章