Python3和hmac。如何处理字符串不是二进制

时间:2021-01-01 18:22:57

I had a script in Python2 that was working great.

我在Python2中有一个运行良好的脚本。

def _generate_signature(data):
   return hmac.new('key', data, hashlib.sha256).hexdigest()

Where data was the output of json.dumps.

数据是json.dumps的输出。

Now, if I try to run the same kind of code in Python 3, I get the following:

现在,如果我尝试在Python 3中运行相同类型的代码,我会得到以下内容:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/hmac.py", line 144, in new
    return HMAC(key, msg, digestmod)
  File "/usr/lib/python3.4/hmac.py", line 42, in __init__
    raise TypeError("key: expected bytes or bytearray, but got %r" %type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str'

If I try something like transforming the key to bytes like so:

如果我尝试将密钥转换为字节,如下所示:

bytes('key')

I get

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: string argument without an encoding

I'm still struggling to understand the encodings in Python 3.

我仍然在努力理解Python 3中的编码。

2 个解决方案

#1


23  

You can use bytes literal: b'key'

你可以使用字节文字:b'key'

def _generate_signature(data):
    return hmac.new(b'key', data, hashlib.sha256).hexdigest()

In addition to that, make sure data is also bytes. For example, if it is read from file, you need to use binary mode (rb) when opening the file.

除此之外,确保数据也是字节。例如,如果从文件中读取,则在打开文件时需要使用二进制模式(rb)。

#2


15  

Not to resurrect an old question but I did want to add something I feel is missing from this answer, to which I had trouble finding an appropriate explanation/example of anywhere else:

不要复活一个旧问题,但我确实想要添加一些我认为在这个答案中缺少的东西,我无法在其他地方找到合适的解释/示例:

OP Aquiles Carattino was pretty close with his attempt at converting the string to bytes, but was missing the second argument, the encoding of the string to be converted to bytes.

OP Aquiles Carattino与将字符串转换为字节的尝试非常接近,但是缺少第二个参数,即要转换为字节的字符串的编码。

If someone would like to convert a string to bytes through some other means than static assignment (such as reading from a config file or a DB), the following should work:

如果有人想通过静态分配之外的其他方式将字符串转换为字节(例如从配置文件或数据库中读取),则以下内容应该有效:

import hmac, hashlib

def _generate_signature(data):
  key = 'key' # Defined as a simple string.
  key_bytes= bytes(key , 'latin-1')
  data_bytes = bytes(data, 'latin-1') # Assumes `data` is also a string.
  return hmac.new(key_bytes, data_bytes , hashlib.sha256).hexdigest()

print(
  _generate_signature('this is my string of data')
)

#1


23  

You can use bytes literal: b'key'

你可以使用字节文字:b'key'

def _generate_signature(data):
    return hmac.new(b'key', data, hashlib.sha256).hexdigest()

In addition to that, make sure data is also bytes. For example, if it is read from file, you need to use binary mode (rb) when opening the file.

除此之外,确保数据也是字节。例如,如果从文件中读取,则在打开文件时需要使用二进制模式(rb)。

#2


15  

Not to resurrect an old question but I did want to add something I feel is missing from this answer, to which I had trouble finding an appropriate explanation/example of anywhere else:

不要复活一个旧问题,但我确实想要添加一些我认为在这个答案中缺少的东西,我无法在其他地方找到合适的解释/示例:

OP Aquiles Carattino was pretty close with his attempt at converting the string to bytes, but was missing the second argument, the encoding of the string to be converted to bytes.

OP Aquiles Carattino与将字符串转换为字节的尝试非常接近,但是缺少第二个参数,即要转换为字节的字符串的编码。

If someone would like to convert a string to bytes through some other means than static assignment (such as reading from a config file or a DB), the following should work:

如果有人想通过静态分配之外的其他方式将字符串转换为字节(例如从配置文件或数据库中读取),则以下内容应该有效:

import hmac, hashlib

def _generate_signature(data):
  key = 'key' # Defined as a simple string.
  key_bytes= bytes(key , 'latin-1')
  data_bytes = bytes(data, 'latin-1') # Assumes `data` is also a string.
  return hmac.new(key_bytes, data_bytes , hashlib.sha256).hexdigest()

print(
  _generate_signature('this is my string of data')
)