OTP
是One Time Password
的缩写,是进一步加强身份认证的安全性的校验方法, 一般配合常规密码一起使用。OTP
动态生成,只使用一次。手机验证码就是典型的OTP
方式。用户请求一个短信验证码, 服务器随机生成一个验证码,然后临时存储起来,通过短信发送给用户。用户在系统上输入验证码发送回服务器,服务器根据临时存储的验证码进行校验。
生成OTP
业内有许多标准算法,比如SHA-1
。所有这些算法都包括两部分输入:
种子值(seed)
:静态值,和帐号关联的密钥可变因子(moving factor)
:每次生成OTP
都变化的部分
根据可变因子
的不同,OTP
可以分为两种类型:
HOTP:
:H
这里表示基于HMAC: Hash-based Message Authentication Code
。每次HTOP
被请求和校验时,服务器和客户端都增加可变因子
的计数器,两端对计数器保持同步。这种方式已经由RFC 4226
标准化。TOTP
:Time-based OTP
, 这种方法的可变因子
是基于时间而不是计数器。OTP
的有效期一般是30秒或者60秒。如果在这个时间窗口内没有使用这个OTP
,那么它就失效了,需要使用新的OTP
。这种方式由RFC 6238
标准化。
TOTP
的算法实现非常简单, 几十行代码就可以实现,比如使用Python
实现:
1 | import hmac, base64, struct, hashlib, time |
各种语言都有相应的OTP
库,Python
中常用的OTP
库是PyOTP
, 使用非常简单,下边我们简单实践一下。
我们首先使用如下代码生成一个兼容Google Authenticator
的随机密钥,我这次执行的结果是NDQARABVHZLAZGEKVNWN72IZIDKZCAK7
:
1 | import pyotp |
服务端使用如下代码生成TOTP
, totp.py
:
1 | import pyotp |
服务端使用如下代码生成OTP
的URI
:
1 | import pyotp |
生成的URI
如下:
1 | (py3) [root@default src]# python uri.py |
我们把这个URI
转换成QR
码:
现在服务端部分准备完成。客户端我们直接使用Microsoft Authenticator
来进行验证。
首先打开Microsoft Authenticator
扫描生成的二维码,然后可以看到当前的OTP
:
在服务器上执行totp
查看OTP
,结果是一致的:
1 | (py3) [root@default src]# python totp.py |
服务器上在收到用户发来的OTP
后,可以使用如下方法进行校验:
1 | totp.verify('775209') # => True |
参考: