在Python中实现HMAC-SHA1

我试图使用一个网站的OAuth,这需要签名方法是“HMAC-SHA1”。

我想知道如何在Python中实现这个?

Pseudocodish:

def sign_request(): from hashlib import sha1 import hmac # key = CONSUMER_SECRET& #If you dont have a token yet key = "CONSUMER_SECRET&TOKEN_SECRET" # The Base String as specified here: raw = "BASE_STRING" # as specified by oauth hashed = hmac.new(key, raw, sha1) # The signature return hashed.digest().encode("base64").rstrip('\n') 

签名错误通常驻留在基本string中,请确保您理解这一点(如OAuth1.0规范中所述: http ://tools.ietf.org/html/draft-hammer-oauth-10#section-3.4 。 1 )。

以下input用于生成签名基础string:

  1. HTTP方法(例如GET)
  2. path(例如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

对于上帝的爱,如果你用oauth做任何事情,请使用Python的requests库! 我试图在Python中使用hmac库来实现HMAC-SHA1,这很麻烦,试图创build正确的oauth基本string等等。 只要使用请求,就像下面这样简单:

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

请求authentication

请求Oauth图书馆

它已经有消息authentication的键控哈希

在oauth网站上有多个python库可用,但是如果你只是对特定的实现感兴趣,你可以看看其中的一个 。

最后,这里是一个实际工作的解决scheme(用Python 3testing)利用oauthlib 。

我在官方RTF 1中使用了第一个OAuth步骤作为示例:

 Client Identifier: dpf43f3p2l4k3l03 Client Shared-Secret: kd94hf93k423kf44 POST /initiate HTTP/1.1 Host: photos.example.net Authorization: OAuth realm="Photos", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_signature_method="HMAC-SHA1", oauth_timestamp="137131200", oauth_nonce="wIjqoS", oauth_callback="http%3A%2F%2Fprinter.example.com%2Fready", oauth_signature="74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D" 

oauth_signature的值就是我们想要计算的值。

以下定义了我们想要签名的内容:

 # There is no query string present. # In case of http://example.org/api?a=1&b=2 - the value # would be "a=1&b=2". uri_query="" # The oauthlib function 'collect_parameters' automatically # ignores irrelevant header items like 'Content-Type' or # 'oauth_signature' in the 'Authorization' section. headers={ "Authorization": ( 'OAuth realm="Photos", ' 'oauth_nonce="wIjqoS", ' 'oauth_timestamp="137131200", ' 'oauth_consumer_key="dpf43f3p2l4k3l03", ' 'oauth_signature_method="HMAC-SHA1", ' 'oauth_callback="http://printer.example.com/ready"' ) } # There's no POST data here - in case it was: x=1 and y=2, # then the value would be '[("x","1"),("y","2")]'. data=[] # This is the above specified client secret which we need # for calculating the signature. client_secret="kd94hf93k423kf44" 

现在我们开始:

 import oauthlib.oauth1.rfc5849.signature as oauth params = oauth.collect_parameters( uri_query="", body=data, headers=headers, exclude_oauth_signature=True, with_realm=False ) norm_params = oauth.normalize_parameters(params) base_string = oauth.construct_base_string( "POST", "https://photos.example.net/initiate", norm_params ) sig = oauth.sign_hmac_sha1( base_string, client_secret, '' # resource_owner_secret - not used ) 

 from urllib.parse import quote_plus print(sig) # 74KNZJeDHnMBp0EMJ9ZHt/XKycU= print(quote_plus(sig)) # 74KNZJeDHnMBp0EMJ9ZHt%2FXKycU%3D 

你可以尝试下面的方法。

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