6

I am trying to make a twitter auth with the help of django middleware, where I calculate the signature of a request like this (https://dev.twitter.com/oauth/overview/creating-signatures):

    key = b"MY_KEY&"
    raw_init = "POST" + "&" + quote("https://api.twitter.com/1.1/oauth/request_token", safe='')

    raw_params = <some_params>
    raw_params = quote(raw_params, safe='')

    #byte encoding for HMAC, otherwise it returns "expected bytes or bytearray, but got 'str'"
    raw_final = bytes(raw_init + "&" + raw_params, encoding='utf-8')

    hashed = hmac.new(key, raw_final, sha1)

    request.raw_final = hashed

    # here are my problems: I need a base64 encoded string, but get the error "'bytes' object has no attribute 'encode'"
    request.auth_header = hashed.digest().encode("base64").rstrip('\n')

As you can see, there is no way to base64 encode a 'bytes' object.

The proposed solution was here: Implementaion HMAC-SHA1 in python

2
  • did you try: base64.encodestring(str(raw_final)) ? Commented Aug 26, 2016 at 9:46
  • @Jean-FrançoisFabre why would I encode raw_final? I need a HMAC object converted to base64 string... All of this according to twitter documentation - dev.twitter.com/oauth/overview/creating-signatures at the very bottom of the page Commented Aug 26, 2016 at 9:54

2 Answers 2

10

The trick is to use base64 module directly instead of str/byte encoding, which supports binary.

You can fit it like this (untested in your context, should work):

import base64
#byte encoding for HMAC, otherwise it returns "expected bytes or bytearray, but got 'str'"
raw_final = bytes(raw_init + "&" + raw_params, encoding='utf-8')

hashed = hmac.new(key, raw_final, sha1)

request.raw_final = hashed

# here directly use base64 module, and since it returns bytes, just decode it
request.auth_header = base64.b64encode(hashed.digest()).decode()

For test purposes, find below a standalone, working example (python 3 compatible, Python 2.x users have to remove the "ascii" parameter when creating the bytes string.):

from hashlib import sha1
import hmac
import base64

# key = CONSUMER_SECRET& #If you dont have a token yet
key = bytes("CONSUMER_SECRET&TOKEN_SECRET","ascii")


# The Base String as specified here:
raw = bytes("BASE_STRING","ascii") # as specified by oauth

hashed = hmac.new(key, raw, sha1)

print(base64.b64encode(hashed.digest()).decode())

result:

Rh3xUffks487KzXXTc3n7+Hna6o=

PS: the answer you linked to does not work anymore with Python 3. It's python 2 only.

Sign up to request clarification or add additional context in comments.

Comments

1

Just thought I'd adjust the answer for Python3.

from hashlib import sha512
import hmac
import base64


key = b"KEY"
path = b"WHAT YOU WANT TO BE SIGNED"

hashed = hmac.new(key, path, sha512).digest()

print(base64.b64encode(hashed))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.