将 hmac.new().digest() 模块从 Python 2.7 移植到 3.7。

问题描述 投票:0回答:1

我已经为这个问题苦恼了好几个小时。我有下面的生产代码 (为简单起见而解析出来的),在 Python 2.7 中运行得很好。

import hashlib
import hmac

string1 = 'firststring'
string2 = 'secondstring'

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()

print('hmac_digest = ' + digest) # digest is a string

输出是一个字符串,比如这样。

hmac_digest = �!�Ni��I.u�����x�l*>a?. �

但当我用Python3.7运行时,我得到以下错误。

Traceback (most recent call last):
  File "/home/xxxx/work/py23.py", line 7, in <module>
    digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()
  File "/usr/lib/python3.7/hmac.py", line 153, in new
    return HMAC(key, msg, digestmod)
  File "/usr/lib/python3.7/hmac.py", line 49, in __init__
    raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str'

Process finished with exit code 1

经过一番研究,我了解到 hmac 在 3.4 和更高版本中发生了变化。因此,我重新编写了以下代码。

import hashlib
import hmac
import base64

string1 = 'firststring'
string2 = 'secondstring'

digest = hmac.new(key=string1.encode('utf-8'), msg=string2.encode('utf-8'), digestmod=hashlib.sha256).digest()
digest = base64.encodebytes(digest).decode('utf-8') # need to convert to string

print('hmac_digest = ' + digest)

但是我得到的输出完全不同!

hmac_digest = 5CEZhgMDTmmFxkkudbGPxaLSytl4+gdsKj4PYT8uAJk=

我如何正确地将这段代码移植到python3.7中,使我得到与2.7完全相同的输出?

先谢谢你

python hash porting hmac
1个回答
0
投票

你遇到的问题是,在Python 2中,字符串实际上只是一个字节,而在Python 3中,字符串是unicode字符串,而且有一个新的 bytes 原始字节的数据类型。你可以阅读更多关于在本手册中涉及的问题。Python 3 移植指南 和其他地方)。

要让你的代码正常工作,最起码的改动可能是这样的。

import hashlib
import hmac

string1 = 'firststring'.encode('utf-8')
string2 = 'secondstring'.encode('utf-8')

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()

print('hmac_digest = ' + repr(digest)) # digest is a string

这将输出:

hmac_digest = b'\xe4!\x19\x86\x03\x03Ni\x85\xc6I.u\xb1\x8f\xc5\xa2\xd2\xca\xd9x\xfa\x07l*>\x0fa?.\x00\x99'

我们正在打印出 repr() 的hmac,因为它只是一个字节的集合。如果你真的想打印出来,你通常会把它转换成一个十六进制字符串。

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).hexdigest()

这将导致:

hmac_digest = 'e421198603034e6985c6492e75b18fc5a2d2cad978fa076c2a3e0f613f2e0099'

0
投票

感谢Josh Lee的回答 UnicodeDecodeError,无效的延续字节。

他提出的关于使用'latin-1'来解码摘要输出的建议为我解决了这个问题。

下面是我的代码在 Python 3.7 中的样子,它给我的输出和我在 Python 2.7 中的代码完全一样。

import hashlib
import hmac

string1 = 'firststring'.encode('utf-8') # can use 'latin-1'
string2 = 'secondstring'.encode('utf-8') # can use 'latin-1' 

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()

print('hmac_digest = ' + digest.decode('latin-1')) # Use only 'latin-1' to decode because 'utf-8' or 'ascii' will throw a UnicodeDecodeError
© www.soinside.com 2019 - 2024. All rights reserved.