在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:
- HTTP方法(例如GET)
- path(例如http://photos.example.net/photos )
-
参数,按字母顺序排列,如(为了便于阅读,换行符):
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')