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 |
参考: