Search code examples
pythonunicodehmacresthashlib

Typer Error : Unicode-objects must be encoded before hashing


I want to work with RestAPI from kaufland.de website. I followed the instruction to sign a request from : this website .

Here is the code, they gave me as an example to run to sign a request by a SHA-256 HMAC in base64 encoding:

import hmac
import hashlib
import time

def sign_request(method, uri, body, timestamp, secret_key):
    plain_text = "\n".join([method, uri, body, str(timestamp)])

    digest_maker = hmac.new(secret_key, '', hashlib.sha256)
    digest_maker.update(plain_text)
    return digest_maker.hexdigest()

method = "POST"
uri = "https://www.kaufland.de/api/v1/units/"
body = ""
timestamp = time.time()
secret_key = "83cfe0909f4e57f05dd403"

print(sign_request(method, uri, body, timestamp, secret_key))

But the code above threw an error :

TypeError: key: expected bytes or bytearray, but got 'str'

I found a solution from SO1, added b in front of secret_key :

secret_key = b'83cfe0909f4e57f05dd403'

However, it still threw an error when I run :

TypeError: Unicode-objects must be encoded before hashing

So I followed the solution from SO2 by importing base64 package :

import hmac
import hashlib
import time
import base64

def sign_request(method, uri, body, timestamp, secret_key):
    plain_text = "\n".join([method, uri, body, str(timestamp)])

    digest_maker = hmac.new(secret_key, '', hashlib.sha256)
    digest_maker.update(plain_text)
    return base64.b64encode(digest_maker.hexdigest())

method = "POST"
uri = "https://www.kaufland.de/api/v1/units/"
body = ""
timestamp = time.time()
secret_key = b"a7d0cb1da1ddbc86c96ee5fedd341b7d8ebfbb2f5c83cfe0909f4e57f05dd403"

print(sign_request(method, uri, body, timestamp, secret_key))

But it still threw an error :

Traceback (most recent call last):

  File "<ipython-input-54-83e727ea1edf>", line 22, in <module>
    print(sign_request(method, uri, body, timestamp, secret_key))

  File "<ipython-input-54-83e727ea1edf>", line 10, in sign_request
    digest_maker = hmac.new(secret_key, '', hashlib.sha256)

  File "C:\ProgramData\Anaconda3\lib\hmac.py", line 153, in new
    return HMAC(key, msg, digestmod)

  File "C:\ProgramData\Anaconda3\lib\hmac.py", line 88, in __init__
    self.update(msg)

  File "C:\ProgramData\Anaconda3\lib\hmac.py", line 96, in update
    self.inner.update(msg)

TypeError: Unicode-objects must be encoded before hashing

Anyone can help me in this case ?


Solution

  • Try to encode your secret_key parameter on assign or in hmac.new.

    Example:

    secret_key = "83cfe0909f4e57f05dd403".encode('utf-8')
    

    Or like I wrote above:

    digest_maker = hmac.new(secret_key.encode('utf-8'), '', hashlib.sha256)
    

    Upd:

    import hmac
    import hashlib
    import time
    
    def sign_request(method, uri, body, timestamp, secret_key):
        plain_text = "\n".join([method, uri, body, str(timestamp)])
    
        digest_maker = hmac.new(secret_key.encode('utf-8'), msg=''.encode('utf-8'), digestmod=digestmod)
        digest_maker.update(plain_text.encode('utf-8'))
        return digest_maker.hexdigest()
    
    method = "POST"
    uri = "https://www.kaufland.de/api/v1/units/"
    body = ""
    timestamp = time.time()
    secret_key = "a7d0cb1da1ddbc86c96ee5fedd341b7d8ebfbb2f5c83cfe0909f4e57f05dd403"
    digestmod = hashlib.sha256
    
    print(sign_request(method, uri, body, timestamp, secret_key))