Implementation HMAC-SHA1 in python

I am trying to use the OAuth of a website, which requires the signature method to be 'HMAC-SHA1' only.

I am wondering how to implement this in Python?


Solution 1:

Pseudocodish:

def sign_request():
    from hashlib import sha1
    import hmac

    # key = b"CONSUMER_SECRET&" #If you dont have a token yet
    key = b"CONSUMER_SECRET&TOKEN_SECRET" 


    # The Base String as specified here: 
    raw = b"BASE_STRING" # as specified by OAuth
       
    hashed = hmac.new(key, raw, sha1)
    
    # The signature
    return hashed.digest().encode("base64").rstrip('\n')

Signature errors usually reside in the base-string, make sure you understand this (as stated by the OAuth1.0 spec here: https://datatracker.ietf.org/doc/html/draft-hammer-oauth-10#section-3.4.1).

The following inputs are used to generate the Signature Base String:

  1. HTTP Method (for example GET)

  2. Path (for example http://photos.example.net/photos)

  3. Parameters, alphabetically, such as (line breaks for readability):

     file=vacation.jpg
     &oauth_consumer_key=dpf43f3p2l4k3l03
     &oauth_nonce=kllo9940pd9333jh
     &oauth_signature_method=HMAC-SHA1
     &oauth_timestamp=1191242096
     &oauth_token=nnch734d00sl2jdk
     &oauth_version=1.0
     &size=original
    

Concatenate and URL encode each part and it ends up as:

GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26 oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26 oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26 oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal

Solution 2:

For the love of God, if you do ANYTHING with oauth, use the requests library for Python! I tried to implement HMAC-SHA1 using the hmac library in Python and it's a lot of headaches, trying to create the correct oauth base string and such. Just use requests and it's as simple as:

>>> import requests
>>> from requests_oauthlib import OAuth1

>>> url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
>>> auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET', 'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')

>>> requests.get(url, auth=auth)

Requests Authentication

Requests Oauth Library

Solution 3:

It's already there Keyed-Hashing for Message Authentication