Python3 и hmac. Как обрабатывать строку, не являющуюся двоичной

У меня был скрипт в Python2, который отлично работал.

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

Где данные были результатом json.dumps.

Теперь, если я попытаюсь запустить такой же код в 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'

Если я попробую что-то вроде преобразования ключа в байты следующим образом:

bytes('key')

я получил

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

Я все еще пытаюсь понять кодировки в Python 3.

Ответ 1

Вы можете использовать байты b'key': b'key'

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

Кроме того, убедитесь, что data также являются байтами. Например, если он читается из файла, вам нужно использовать binary режим (rb) при открытии файла.

Ответ 2

Чтобы не воскресить старый вопрос, но я хотел добавить что-то, чего я чувствую, отсутствует в этом ответе, к которому у меня возникли проблемы с поиском подходящего объяснения/примера где-либо еще:

OP Aquiles Carattino был довольно близок к своей попытке преобразовать строку в байты, но отсутствовал второй аргумент - кодировка строки, которая должна быть преобразована в байты.

Если кто-то хочет преобразовать строку в байты с помощью других средств, кроме статического присваивания (например, чтение из файла конфигурации или БД), должно работать следующее:

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')
)

Ответ 3

попробуйте

codecs.encode()

который можно использовать как в python2.7.12, так и в 3.5.2

import hashlib
import codecs
import hmac

a = "aaaaaaa"
b = "bbbbbbb"
hmac.new(codecs.encode(a), msg=codecs.encode(b), digestmod=hashlib.sha256).hexdigest()

enter image description here enter image description here