How to encode Unicode objects in Python?

I've been trying to find a solution here for my problem for a long time but nothing seems to work. I am trying to authenticate with the Coinbase Pro API in Python but I am getting

"Unicode-Objects must be encoded before hashing" error.

Please see the code below for your reference.

import json, hmac, hashlib, time, requests, base64
from requests.auth import AuthBase

# Create custom authentication for Exchange
class CoinbaseExchangeAuth(AuthBase):
    def __init__(self, api_key, secret_key, passphrase):
        self.api_key = api_key
        self.secret_key = secret_key
        self.passphrase = passphrase

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

api_url = 'https://api.pro.coinbase.com/'
auth = CoinbaseExchangeAuth(api_key='XXXX',
                            secret_key='XXXX',
                            passphrase='XXXX')

# Get accounts
r = requests.get(api_url + 'accounts', auth=auth)

It would be great if someone can point me to the right direction. I couldn't find the correct solution after searching.

hashlib takes bytes or bytearray. Try this -

...
message = message.encode('UTF-8')
hmac_key = self.secret_key.encode('UTF-8')
signature = hmac.new(hmac_key, message, hashlib.sha256)

How to correct TypeError: Unicode-objects must be encoded before , Since you are encoding simple strings I deduce that you are running Python 3 where all strings are unicode objects, you have two options:. A better way to deal with the encoding is to use the encode() function. As you can see, we have obtained the same result as before. Keep in mind that by default Python 3 uses utf-8 for encoding.

After some debugging I found that the following solution worked for me:

def __call__(self, request):
    print(request.body)
    timestamp = str(time.time())
    message = (timestamp + (request.method).upper() + request.path_url + (request.body or ''))
    message = message.encode('UTF-8')
    hmac_key = base64.b64decode(self.secret_key)
    signature = hmac.new(hmac_key, message, hashlib.sha256).digest()
    signature_b64 = base64.b64encode(signature)

hashlib.md5() TypeError: Unicode-objects must be encoded before , Create a Unicode object from an UTF-8 encoded null-terminated char buffer u. PyObject* PyUnicode_FromFormat(const char *format, )�. Take a� Since Python 3.0, the language’s str type contains Unicode characters, meaning any string created using "unicode rocks!", 'unicode rocks!', or the triple-quoted string syntax is stored as Unicode. The default encoding for Python source code is UTF-8, so you can simply include a Unicode character in a string literal:

Here is how I solved it, message.encode('utf-8')

   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)
    signature = hmac.new(hmac_key, message.encode('utf-8'), hashlib.sha256)
    signature_b64 = base64.b64encode(signature.digest())

Unicode Objects and Codecs — Python 3.4.10 documentation, The rules for converting a Unicode string into the ASCII encoding are simple; for giving the encoding to use; if it's left as None , a regular Python file object that� Encode the Py_UNICODE buffer s of the given size and return a Python bytes object. encoding and errors have the same meaning as the parameters of the same name in the Unicode encode() method. The codec to be used is looked up using the Python codec registry. Return NULL if an exception was raised by the codec.

Unicode HOWTO — Python 2.7.18 documentation, Encode a Unicode object and return the result as Python string object. encoding and errors have the same meaning as the parameters of the� Python 3: All-In on Unicode. Python 3 is all-in on Unicode and UTF-8 specifically. Here’s what that means: Python 3 source code is assumed to be UTF-8 by default. This means that you don’t need # -*- coding: UTF-8 -*-at the top of .py files in Python 3. All text (str) is Unicode by default.

Unicode Objects and Codecs — Python 2.7.18 documentation, print("The hash given does not correspond to any supplied word in the wordlist.") input(). sys.exit(). python � cli� Create a Unicode object by decoding size bytes of the encoded string s. encoding and errors have the same meaning as the parameters of the same name in the unicode () built-in function. The codec to be used is looked up using the Python codec registry. Return NULL if an exception was raised by the codec.

1453967, At the moment presumably under Python 2 we're using strings here, rather than unicode - Will one encoding or another change the resultant hashes for the� Unicode Literals in Python Source Code ¶ In Python source code, specific Unicode code points can be written using the \u escape sequence, which is followed by four hex digits giving the code point. The \U escape sequence is similar, but expects eight hex digits, not four:

Comments
  • what line triggers the error? Post a trace.
  • @t.stv I am actually getting this error now: File "/Users/asanga/Documents/python_projects/coinbasepro/main.py", line 22, in call hmac_key = base64.b64decode(self.secret_key) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/base64.py", line 87, in b64decode return binascii.a2b_base64(s) binascii.Error: Invalid base64-encoded string: number of data characters (85) cannot be 1 more than a multiple of 4
  • so your secret_key contains some strange stuff. Have you tried to call encode on the secret_key?
  • @t.stv I've created a new pair of keys and tried to run the code again but now I am getting the "Unicode-objects must be encoded before hashing" error again
  • @t.stv stacetrack below: File "/Users/asanga/Documents/python_projects/coinbasepro/main.py", line 23, in call signature = hmac.new(hmac_key, message, hashlib.sha256) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/hmac.py", line 153, in new return HMAC(key, msg, digestmod) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/hmac.py", line 93, in init self.update(msg) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/hmac.py", line 102, in self.inner.update(msg)
  • @Nant, did you follow this one? developers.coinbase.com/docs/wallet/api-key-authentication
  • That's for authenticating to the coinbase wallet not the coinbase pro exchange. I've seen that article but unfortunately that's not quite what I want
  • @Nant, updated the solution. Try now :-) hope it helps!
  • I am getting this error now: File "/Users/asanga/Documents/python_projects/coinbasepro/main.py", line 31, in call signature_b64 = signature.digest().encode('base64').rstrip('\n') AttributeError: 'bytes' object has no attribute 'encode'
  • Yes, it should work fine as well. Because both converts to bytes, base64 and UTF-8 and the hmac takes bytes like objects.