我试图使用可以使用Google Authenticator application生成的一次性密码。
基本上,Google Authenticator实现两种类型的密码:
Google Authenticator也可以在这里作为开放源代码使用:code.google.com/p/google-authenticator
我在寻找生成HOTP和TOTP密码的现有解决方案,但没有找到太多。我拥有的代码是负责生成HOTP的以下代码段:
import hmac, base64, struct, hashlib, time
def get_token(secret, digest_mode=hashlib.sha1, intervals_no=None):
if intervals_no == None:
intervals_no = int(time.time()) // 30
key = base64.b32decode(secret)
msg = struct.pack(">Q", intervals_no)
h = hmac.new(key, msg, digest_mode).digest()
o = ord(h[19]) & 15
h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
return h
我面临的问题是,我使用上述代码生成的密码与使用googleauthenticatorappforandroid生成的密码不同。尽管我尝试了多个intervals_no
值(正是前10000个,以intervals_no = 0
开头),但是secret
等于GA应用程序中提供的密钥。
我的问题是:
总结一下:请给我一些线索,帮助我在Python代码中实现Google Authenticator身份验证。
我想给我的问题定个赏金,但我已经成功地找到了解决办法。我的问题似乎与
secret
键的值不正确有关(它必须是base64.b32decode()
函数的正确参数)。下面我将发布完整的工作解决方案,并解释如何使用它。
代码
下面的代码就足够了。我还将它作为一个单独的模块上传到GitHub,称为onetimepass(这里有:https://github.com/tadeck/onetimepass)。
它有两个功能:
get_hotp_token()
生成一次性令牌(一次性使用后将失效)get_totp_token()
根据时间生成令牌(每隔30秒更改一次)参数
当涉及到参数时:
secret
是服务器(上面的脚本)和客户端(Google Authenticator,通过在应用程序中提供密码)已知的秘密值intervals_no
是每次生成令牌后递增的数目(这可能应该在服务器上通过在过去检查的最后一个成功的整数之后检查一些有限的整数来解决)如何使用
secret
(它必须是base64.b32decode()
的正确参数)-最好是16个字符(没有=
符号),因为它对脚本和Google Authenticator都有效。get_hotp_token()
。在Google Authenticator中,我提到的这种类型的密码是基于计数器的。要在服务器上检查它,您需要检查几个值intervals_no
(因为您没有保证用户出于某种原因没有在请求之间生成传递),但不少于最后一个工作的intervals_no
值(因此您可能应该将它存储在某个地方)。get_totp_token()
。您必须确保两个系统都有正确的时间设置(这意味着它们在任何给定的时刻都会生成相同的Unix时间戳)。示例
对基于HMAC的一次性密码使用以下代码时:
您将得到以下结果:
这与Google Authenticator应用程序生成的令牌相对应(除非短于6个符号,否则应用程序会在开始处添加0以达到6个字符的长度)。
我想要一个python脚本来生成TOTP密码。所以,我写了python脚本。这是我的实现。我在维基百科上有这个info和一些关于HOTP和TOTP的知识来编写这个脚本。
相关问题 更多 >
编程相关推荐