这篇文章主要介绍了Google Authenticator TOTP的原理以及使用代码示例,具有一定借鉴价值,需要的朋友可以参考下。
话不多说,一起往下看吧。
一、 原理详解(点击图片然后放大查看)
二、 验证
1、下载Google谷歌身份验证器。
2、通过Python 的qrcode和pyotp模块生成二维码。
3、然后使用下载的谷歌身份验证器扫描生成的二维码
如果没有谷歌服务,则选择输入秘钥,在账户明处填入name参数,在秘钥处填入Secret即可。
4、对比手机上谷歌验证器显示的6位动态码,你会发现,代码计算处的6位动态码是一致的
三、 源码
1、计算Google Authenticator 6位动态码
#!/usr/bin/env python # -*- coding:utf-8 -*- # Google Authenticator工作原理 TOTP(Time-Based One-Time Password) import hmac import hashlib import base64 import struct import time # setup 1 : base32 secret # 提示:Secret的长度最好不要超过32 Secret = 'userxiaosheng' # Secret += '=' * (8-len(Secret)%8) # py3中base64模块要求字符串必须为8的倍数,不足部分使用 = 补全 # 在查阅相关资料时,发现解决【可以将Key进行b3decode】的代码都是这样写的(或者类似). # 但是在生产环境中,为了给每个用户生成不一样的Key,我们必须通过各种算法,生成一个和用户有关的字符串作为Key使用, # 如果你使用的是 Secret += '=' * (8-len(Secret)%8) 这种方式解决b32decode问题,那么当Key中有数字时, # b32decode将会报错:binascii.Error: Non-base32 digit found, # 通过测试,我找到了一段代替Secret += '=' * (8-len(Secret)%8)的代码,所以在我这篇文章中, # 将会使用Secret = base64.b32encode(s=Secret.encode('utf-8'))来代替类似Secret += '=' * (8-len(Secret)%8) 的代码. Secret = base64.b32encode(s=Secret.encode('utf-8')) K = base64.b32decode(Secret,True) # setup 2 : get current timestamp # int(time.time()) // 30 到当前经历了多少个30秒 C = struct.pack(">Q", int(time.time()) // 30) # 将间隔时间转为big-endian(大端序)并且为长整型的字节 # setup 3 : start hmac-sha1 # hmac = SHA1(secret + SHA1(secret + input)) H = hmac.new(K,C,hashlib.sha1).digest() # 使用hmac sha1加密,并且以字节的方式取出 = b'\x0f\x1a\xaeL\x0c\x8e\x19g\x8dv}\xde7\xbc\x95\xeal\xa3\xc1\xee' O = H[19] & 15 # bin(15)=00001111=0b1111 DynamicPasswd = str((struct.unpack(">I", H[O:O+4])[0] & 0x7fffffff) % 1000000) # struct.unpack('>I',h[o:o+4])[0] -- 转为big-endian(大端序)并且不为负数的数字(整数),因为转换完是一个数组,类似"(2828101188,)",所以需要[0]取出 # h[o:o+4] -- 取其中4个字节 o=10 则取索引分别为 10,11,12,13的字节 # & 0x7fffffff = 11111111 -- 与字节转换的数字做与运算 # % 1000000 -- 得出的数字与1000000相除然后取余 TOTP = str(0) + str(DynamicPasswd) if len(DynamicPasswd) < 6 else DynamicPasswd # passwd = passwd if len(passwd) < 6 else str(0) + str(passwd) # 如果最后得出的6位数字,首位0,可能会只输出5位数字,所以这里进行一个判断,如果是5位则加上首位的0 print(TOTP)
2、生成二维码
import pyotp from qrcode import QRCode from qrcode import constants Secret = 'userxiaosheng' Secret = base64.b32encode(s=Secret.encode('utf-8')) Content = pyotp.totp.TOTP(Secret).provisioning_uri(name='xiaosheng', issuer_name="Verfiy Code") # 在真实环境中,name的参数应该是和Secret有关联的,这样我们才能为每个不同的用户分别计算动态验证码. qr = QRCode(version=1, error_correction=constants.ERROR_CORRECT_L, box_size=6, border=4,) qr.add_data(Content) qr.make(fit=True) img = qr.make_image() img.save('./GoogleQR.png')
关于Google Authenticator TOTP的原理以及使用代码示例就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果喜欢这篇文章,不如把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。