在Python中实现HMAC-SHA1

58 投票
8 回答
81502 浏览
提问于 2025-04-17 07:27

我正在尝试使用一个网站的OAuth认证,这个认证要求签名方法只能用'HMAC-SHA1'。

我想知道怎么在Python中实现这个签名方法?

8 个回答

13

你可以试试下面的方法。

def _hmac_sha1(input_str):
        raw = input_str.encode("utf-8")
        key = 'your_key'.encode('utf-8')
        hashed = hmac.new(key, raw, hashlib.sha1)
        return base64.encodebytes(hashed.digest()).decode('utf-8')
41

为了上天的份儿,如果你要做任何跟oauth有关的事情,务必要使用Python的requests库!我尝试用Python的hmac库来实现HMAC-SHA1,结果真是头疼不已,特别是在创建正确的oauth基础字符串时,简直让人抓狂。直接用requests就简单多了,像这样就可以:

>>> 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认证文档

Requests Oauth库

95

伪代码示例:

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

签名错误通常出现在基础字符串中,确保你理解这一点(正如OAuth1.0规范中所述,具体可以查看这里:https://datatracker.ietf.org/doc/html/draft-hammer-oauth-10#section-3.4.1)。

以下输入用于生成签名基础字符串:

  1. HTTP方法(比如GET)

  2. 路径(例如 http://photos.example.net/photos

  3. 参数,按字母顺序排列,比如(为了更易读,换行显示):

     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
    

把每个部分连接起来并进行URL编码,最后得到的结果是:

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

撰写回答