必须在散列错误之前对Unicode对象进行编码

时间:2016-06-11 11:32:16

标签: python python-3.x encode hmac

处理类似问题的问题:SO 1SO 2SO 3

我已经尝试了他们的答案,几乎将任何字符串编码为utf-8,但hmac仍然告诉我编码我的unicoe字符。最大的问题是我甚至无法识别有问题的变量;打印输出告诉我他们是stringsbytes;在前者的情况下,我附上了.encode(),但这并没有帮助。

我试图查询GDAX API,我也是using the code as given on their API page。为Python2.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对象,但后来我也无法使用字节?我怎么解决这个问题呢?感谢任何帮助,因为我非常困惑。

2 个答案:

答案 0 :(得分:3)

"Parameter msg can be of any type supported by hashlib."

"Note: Feeding string objects into is not supported, as hashes work on bytes, not on characters."

因此,您的邮件必须是bytes类型。在消息上使用.encode(),它将为您提供bytes对象。

注意:这仅适用于python 3!

要将摘要编码为base64,请使用base64 library

import base64
signature_b64 = base64.b64encode(signature.digest())

答案 1 :(得分:0)

对于 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())