Объекты Unicode должны быть закодированы до ошибки хеширования

Вопросы, связанные с похожими проблемами: SO 1, SO 2, SO 3.

Я пробовал их ответы, кодируя практически любую строку в utf-8, но hmac по-прежнему говорит мне кодировать мои символы unicoe. Самая большая проблема заключается в том, что я даже не могу определить вызывающую ошибку переменную; выходные данные печати говорят мне, что они либо strings, либо bytes; в случае первого я прикрепляю .encode(), но это не помогло.

Я пытаюсь запросить API GDAX, а также использую приведенный код на их странице API. Будучи написанным для Python 2.7, я подумал, что могут быть проблемы с кодировкой и всем остальным, но для меня это просто не имеет смысла.

Мой код:

class CoinbaseExchangeAuth(AuthBase):
    def __init__(self, api_key, secret_key, passphrase):
        self.api_key = api_key.encode()
        self.secret_key = secret_key.encode()
        self.passphrase = passphrase.encode()

    def __call__(self, request):
        timestamp = str(time.time())
        message = timestamp + request.method + request.path_url + (request.body or '')
        hmac_key = base64.b64decode(self.secret_key)
    #print(hmac_key, type(hmac_key))
    #print(message, type(message))
    signature = hmac.new(hmac_key, message, hashlib.sha256)

    signature_b64 = signature.digest().encode('base64').rstrip('\n')


    request.headers.update({
        'CB-ACCESS-SIGN': signature_b64,
        'CB-ACCESS-TIMESTAMP': timestamp,
        'CB-ACCESS-KEY': self.api_key,
        'CB-ACCESS-PASSPHRASE': self.passphrase,
        'Content-Type': 'application/json'
    })
    return request

Ошибка:

File "F:\git\knowhere\Private\bitex-crawler\gdax_client\gdaxex\api.py", line 47, in __call__
signature = hmac.new(hmac_key, message, hashlib.sha256)
File "C:\Users\nls\Anaconda3\lib\hmac.py", line 144, in new
return HMAC(key, msg, digestmod)
File "C:\Users\nls\Anaconda3\lib\hmac.py", line 84, in __init__
self.update(msg)
File "C:\Users\nls\Anaconda3\lib\hmac.py", line 93, in update
self.inner.update(msg)
TypeError: Unicode-objects must be encoded before hashing

Когда я печатаю проверку объектов, которые я передаю своему вызову hmac.new(), он говорит мне, что у меня есть объект str и объект bytes.

print(type(hmac_key)) # <bytes>
print(type(message))  # <str>

Естественно, я подумал, что мне нужно закодировать и эту присоску:

signature = hmac.new(hmac_key, message.encode(), hashlib.sha256)

что привело к ошибке в этой строке:

signature_b64 = signature.digest().encode('base64').rstrip('\n')

а именно:

File "F:/git/knowhere/Private/bitex-crawler/gdax_client/client.py",
[..]
File "F:\git\knowhere\Private\bitex-crawler\gdax_client\gdaxex\api.py", line 123, in _query
r = api_query(url, json=req, auth=auth)
File "C:\Users\nls\Anaconda3\lib\site-packages\requests\api.py", line 67, in get
return request('get', url, params=params, **kwargs)
File "C:\Users\nls\Anaconda3\lib\site-packages\requests\api.py", line 53, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Users\nls\Anaconda3\lib\site-packages\requests\sessions.py", line 454, in request
prep = self.prepare_request(req)
File "C:\Users\nls\Anaconda3\lib\site-packages\requests\sessions.py", line 388, in prepare_request
hooks=merge_hooks(request.hooks, self.hooks),
File "C:\Users\nls\Anaconda3\lib\site-packages\requests\models.py", line 297, in prepare
self.prepare_auth(auth, url)
File "C:\Users\nls\Anaconda3\lib\site-packages\requests\models.py", line 490, in prepare_auth
r = auth(self)
File "F:\git\knowhere\Private\bitex-crawler\gdax_client\gdaxex\api.py", line 49, in __call__
signature_b64 = signature.digest().encode('base64').rstrip('\n')
AttributeError: 'bytes' object has no attribute 'encode'

.. Итак, у меня не может быть незакодированных объектов Unicode, но я также не могу иметь байты позже? Как мне это исправить? Признателен за любую помощь в этом, потому что я глубоко запутался.


person deepbrook    schedule 11.06.2016    source источник
comment
Похоже, вы используете библиотеки только для python-2 с python 3. Если нет версии python 3, вам нужно самостоятельно портировать сторонний код (или переключиться на python 2.7). В этом руководстве должно быть объяснено, почему вы получаете эти ошибки и как они можно решить. docs.python.org/3/howto/pyporting. html#text-против-двоичных-данных   -  person Håken Lid    schedule 11.06.2016
comment
Здоровья, мужик! Я не думал об этом!   -  person deepbrook    schedule 11.06.2016


Ответы (2)


"Параметр msg может быть любого типа, поддерживаемого hashlib." .

"Примечание. Передача строковых объектов в не поддерживается, так как хэши работают с байтами, не на символах.".

Таким образом, ваше сообщение должно быть типа bytes. Используйте .encode() в сообщении, которое даст вам объект bytes.

Примечание. Это необходимо только для Python 3!

Чтобы закодировать дайджест в base64, используйте библиотеку base64.

import base64
signature_b64 = base64.b64encode(signature.digest())
person Simon Kirsten    schedule 11.06.2016
comment
все хорошо! Я был слеп к коду, кодирование с помощью base64 теперь работает нормально. За последние два дня я написал 6 таких преобразований, иногда все это немного размыто. - person deepbrook; 11.06.2016

Для Python 3.9 я получал ту же ошибку,

self._inner.update(msg) TypeError: Unicode-объекты должны быть закодированы перед хешированием

Следующее сработало для меня,

signature = hmac.new(key.encode('utf-8'), msg.encode('utf-8'), hashlib.sha256)
auth_token = str(signature.hexdigest())
person Abhijeet Kamble    schedule 16.04.2021