首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在python中结合使用base32和hotp (一次性密码)?

如何在python中结合使用base32和hotp (一次性密码)?
EN

Stack Overflow用户
提问于 2019-06-08 00:23:00
回答 2查看 1.3K关注 0票数 2

对于一个大学练习,我想用python开发一个简单的hotp服务器-客户机系统。在这种情况下,客户端向服务器发送密码和一次性密码。服务器知道这个秘密,计算当前的hotp,并比较它收到的值。到现在为止还好。对于纯文本,这工作得很好,并且计算值与我使用iOS应用程序"OTP Auth“时得到的值相同。但也有可能结合base32来计算动态口令。因此,我添加了几行代码来将明文编码为base32,但现在输出不正确。

让我们假设我们使用的是密码"1234“,因此明文输出应该是"110366”。这是有效的。但是如果我将密码编码成base32,输出应该是"807244“,但我的程序计算的是"896513”。有人知道为什么会这样吗?

我已经尝试过使用不同的秘密,并在不同的应用程序上进行了检查。结果总是一样的。

import hmac
import hashlib
import array
import base64

counter = 0
digits = 6                      #Anzahl der Zeichen

def hotp(secret, c):
    global digits
    counter = extendCounter(c)
    hmac_sha1 = hmac.new(secret, counter, hashlib.sha1).hexdigest()
    return truncate(hmac_sha1)[-digits:]


def truncate(hmac_sha1):
    offset = int(hmac_sha1[-1], 16)
    binary = int(hmac_sha1[(offset * 2):((offset * 2) + 8)], 16) & 0x7fffffff
    return str(binary)


def extendCounter(long_num):
    byte_array = array.array('B')
    for i in reversed(range(0, 8)):
        byte_array.insert(0, long_num & 0xff)
        long_num >>= 8
    return byte_array


def main():
    secret = "1234"
    bSecret = secret.encode("UTF-8")
    bSecret = base64.b32encode(bSecret)
    otp = hotp(bSecret, counter)
    one_time_password = otp

我期望807244作为输出,但输出是896513

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-11 03:17:19

发现了错误:秘密必须是base32解码值,而不是将秘密转换为Base32。此外,必须对该值进行解码,而不是对其进行编码("base64.b32decode(bytes(saved_secret,'utf-8'))")

所以正确的main看起来像这样:

def main():
    secret = "V6X27L5P" #Base32 value
    secret = base64.b32decode(bytes(secret, 'utf-8'))
    one_time_password = hotp(secret, counter)
票数 1
EN

Stack Overflow用户

发布于 2019-06-08 19:54:05

首先,必须指出的是,secret.encode('UTF-8')的结果与base64.b32encode(bSecret)的结果具有完全相同的类型(就这一点而言,base64.b64encode(bSecret)也是如此) --它们都返回bytes对象。同样值得注意的是,Python语言中的implementation of hmac没有提到base64/base32编码。因此,简而言之,只有当共享密钥是base64/UTF-8编码的blob时,807244的预期结果才有效。

这个简短的代码片段显示,您确实可以向hotp提供您喜欢的任何字节,并且它会得到一些结果(因为hotp在本例中被多次调用,counter被更改了)

# ... everything from your example above ...
secret = "1234"
secret_bytes = secret.encode("UTF-8")
secret_bytes
>>> b'1234'
b32_secret = base64.b32encode(bSecret)
b32_secret
>>> b'GEZDGNA='
b64_secret = base64.b64encode(bSecret)
b64_secret
>>> b'MTIzNA=='
hotp(secret_bytes, counter)  # just a UTF-8 blob works
>>> '110366'
hotp(b32_secret, counter)  # base32/UTF-8 also works
>>> '896513'
hotp(b64_secret, counter)  # base64/UTF-8 works as well
>>> '806744'

如果你有更多关于为什么你期望base32/utf8blob使用807244的详细信息,我很乐意修改这个答案。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56498074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档