在Python谷歌身份验证实施 [英] Google Authenticator implementation in Python

查看:1383
本文介绍了在Python谷歌身份验证实施的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用可以使用谷歌身份验证器应用生成一次性密码

基本上,谷歌身份验证器实现两种类型的密码:

Basically, Google Authenticator implements two types of passwords:


  • HOTP - 基于HMAC-一次性密​​码,这意味着密码每次调用改变,在符合的 RFC4226

  • TOTP - 基于时间的一次性密码,它每30秒时间改变(据我所知)

  • HOTP - HMAC-based One-Time Password, which means the password is changed with each call, in compliance to RFC4226, and
  • TOTP - Time-based One-Time Password, which changes for every 30-seconds period (as far as I know).

谷歌身份验证器也可作为在这里开源: code.google.com / P /谷歌-认证

Google Authenticator is also available as Open Source here: code.google.com/p/google-authenticator

我一直在寻找现有的解决方案生成HOTP和TOTP密码,但并没有找到太多。在code我负责生成HOTP下面的代码片段:

I was looking for existing solutions to generate HOTP and TOTP passwords, but did not find much. The code I have is the following snippet responsible for generating 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

我现在面临的问题是,我生成使用上述code中的密码是不一样的使用谷歌身份验证器应用为Android产生。尽管我试过多个 intervals_no 值(确切第一10000,开头 intervals_no = 0 ),其中秘密等于键GA应用程序内提供的。

The problem I am facing is that the password I generate using the above code is not the same as generated using Google Authenticator app for Android. Even though I tried multiple intervals_no values (exactly first 10000, beginning with intervals_no = 0), with secret being equal to key provided within the GA app.

我的问题是:


  1. 我在做什么错了?

  2. 如何生成HOTP和/或TOTP在Python?

  3. 是否有这方面的任何现有的Python库?

要总结:请给我任何线索,这将有助于我的我的Python code中实现谷歌的Authenticator认证

To sum up: please give me any clues that will help me implement Google Authenticator authentication within my Python code.

推荐答案

我想成立一​​个赏金对我的问题,但我已经成功地创建解决方案。我的问题似乎与秘密不正确的值进行连接键(它必须是 base64.b32de code()正确的参数功能)。

I wanted to set a bounty on my question, but I have succeeded in creating solution. My problem seemed to be connected with incorrect value of secret key (it must be correct parameter for base64.b32decode() function).

下面我发布关于如何使用它的解释完全可行的解决方案。

Below I post full working solution with explanation on how to use it.

以下code是不够的。我也上传到GitHub上的所谓独立的模块的 onetimepass 的(可在这里: https://github.com/tadeck / onetimepass )。

The following code is enough. I have also uploaded it to GitHub as separate module called onetimepass (available here: https://github.com/tadeck/onetimepass).

import hmac, base64, struct, hashlib, time

def get_hotp_token(secret, intervals_no):
    key = base64.b32decode(secret, True)
    msg = struct.pack(">Q", intervals_no)
    h = hmac.new(key, msg, hashlib.sha1).digest()
    o = ord(h[19]) & 15
    h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
    return h

def get_totp_token(secret):
    return get_hotp_token(secret, intervals_no=int(time.time())//30)

它有两个功能:


  • get_hotp_token()生成一次性令牌(单次使用后应该无效),

  • get_totp_token()基于时间(以30秒的间隔改变)生成令牌,

  • get_hotp_token() generates one-time token (that should invalidate after single use),
  • get_totp_token() generates token based on time (changed in 30-second intervals),

当它涉及到的参数:


  • 秘密是已知的服务器(上面的脚本)和客户端秘密值(谷歌身份验证器,通过提供它作为应用程序中的密码)

  • intervals_no 是令牌每一代之后incremeneted数量(这应该是可能是后一次成功的人在检查检查整数的一些数量有限的解决了服务器上过去)

  • secret is a secret value known to server (the above script) and client (Google Authenticator, by providing it as password within application),
  • intervals_no is the number incremeneted after each generation of the token (this should be probably resolved on the server by checking some finite number of integers after last successful one checked in the past)

  1. 生成秘密(必须是 base64.b32de code正确的参数()) - preferably 16字符(没有 = 标志),因为它的工作肯定为脚本和谷歌身份验证器。

  2. 使用 get_hotp_token()如果你想在每次使用后无效一次性密码。在谷歌身份验证这种类型的密码,我提到基于在柜台上。对于检查它在服务器上,您将需要检查的几个值intervals_no (你有没有quarantee该用户没有产生由于某种原因,请求之间的通),但不小于上次工作 intervals_no 值(因此你应该存储在某个地方)。

  3. 使用 get_totp_token(),如果你想有一个令牌30秒的时间间隔工作。你必须确保两个系统具有正确的时间设置(即它们都产生在任何给定时间相同的Unix时间戳)。

  4. 确保保护自己免受暴力攻击。如果使用基于时间的密码,然后在不到30秒尝试百万值给出100%的猜密码的机会。在基于HMAC-passowrds(HOTPs)的情况下,它似乎更差。

  1. Generate secret (it must be correct parameter for base64.b32decode()) - preferably 16-char (no = signs), as it surely worked for both script and Google Authenticator.
  2. Use get_hotp_token() if you want one-time passwords invalidated after each use. In Google Authenticator this type of passwords i mentioned as based on the counter. For checking it on the server you will need to check several values of intervals_no (as you have no quarantee that user did not generate the pass between the requests for some reason), but not less than the last working intervals_no value (thus you should probably store it somewhere).
  3. Use get_totp_token(), if you want a token working in 30-second intervals. You have to make sure both systems have correct time set (meaning that they both generate the same Unix timestamp in any given moment in time).
  4. Make sure to protect yourself from brute-force attack. If time-based password is used, then trying 1000000 values in less than 30 seconds gives 100% chance of guessing the password. In case of HMAC-based passowrds (HOTPs) it seems to be even worse.

在使用下列code一次性基于HMAC-密码:

Example

When using the following code for one-time HMAC-based password:

secret = 'MZXW633PN5XW6MZX'
for i in xrange(1, 10):
    print i, get_hotp_token(secret, intervals_no=i)

您将得到以下结果:

1 448400
2 656122
3 457125
4 35022
5 401553
6 581333
7 16329
8 529359
9 171710

这是对应于由谷歌身份验证器应用生成的令牌(除非短于6的迹象,增加了应用程序以零年初达到6个字符的长度)。

which is corresponding to the tokens generated by the Google Authenticator app (except if shorter than 6 signs, app adds zeros to the beginning to reach a length of 6 chars).

这篇关于在Python谷歌身份验证实施的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆