简体   繁体   English

python-hmac新的sha1

[英]python - hmac new sha1

I am trying to get the same result as this online API service produces . 我正在尝试获得与此在线API服务产生的结果相同的结果。

By entering key as the application key, and secret as the secret produces the following URL: 通过输入key的应用程序键和secret的秘密产生以下网址:

http://webservices.esd.org.uk/organisations/barrowbc?ApplicationKey=key&Signature=YXWJsGSKnLcENW1vm30EYObbCsA=

I have tried producing the same signature using the following code: 我尝试使用以下代码产生相同的签名:

import hmac    
import urllib
import base64
from hashlib import sha1


def sign_url(url,key,secret):
    url = url + 'ApplicationKey=' + key
    signature = hmac.new(secret,url,sha1).digest().encode("base64") 
    signature = '&Signature=' + signature
    url = url + signature
    print(url)

sign_url('http://webservices.esd.org.uk/organisations/barrowbc','key','secret')

but this produces: 但这会产生:

http://webservices.esd.org.uk/organisations/barrowbcApplicationKey=key&Signature=W//jgV+xdSbTBG6+i1TCGN/Kbsk=

The expected signature is 预期的签名是

YXWJsGSKnLcENW1vm30EYObbCsA=

but my code outputs 但是我的代码输出

W//jgV+xdSbTBG6+i1TCGN/Kbsk=

Your version is missing the required ? 您的版本缺少必填项? component before the Application= parameter. Application=参数之前的组件。 You probably want to add in a & if there are other parameters, however, and you need to remove the newline that .encode("base64") adds to the end of the value: 但是,如果还有其他参数,则可能要添加& ,并且需要删除.encode("base64")添加到值末尾的换行符:

def sign_url(url, key, secret):
    sep = '&' if '?' in url else '?'
    url = '{}{}ApplicationKey={}'.format(url, sep, key)
    signature = hmac.new(secret, url, sha1).digest().encode("base64") 
    return '{}&Signature={}'.format(url, signature[:-1])

I note however that when the URL contains URL-encoded elements then the signature appears to be applied to the URL-decoded version (with + interpreted as spaces), so you really want to add a urllib.unquote_plus() (Python 2) / urllib.parse.unquote_plus() (Python 3) call when signing: 但是,我注意到,当URL包含URL编码的元素时 ,签名似乎已应用于URL解码的版本(其中+解释为空格),因此您真的想添加urllib.unquote_plus() (Python 2)/ urllib.parse.unquote_plus() (Python 3)调用:

try:
    from urllib.parse import unquote_plus
except ImportError:
    from urlib import unquote_plus

def sign_url(url, key, secret):
    sep = '&' if '?' in url else '?'
    url = '{}{}ApplicationKey={}'.format(url, sep, key)
    signature = hmac.new(secret, unquote_plus(url), sha1).digest().encode("base64") 
    return '{}&Signature={}'.format(url, signature[:-1])

I've confirmed that this is what their PHP example code does and verified sample query parameters in the online signature tool , eg when entering the path and parameters foo%20bar?foo%20bar into the tool, CCuMYpCDznH4vIv95+NrN+RHEK0= is produced as the signature, but using foo+bar?foo+bar produces the exact same signature even though + should only be decoded as a space in form data . 我已经确认这是他们的PHP示例代码所做的工作,并在在线签名工具中验证了示例查询参数,例如,当在工具中输入路径和参数foo%20bar?foo%20bar ,将CCuMYpCDznH4vIv95+NrN+RHEK0=作为签名,但是使用foo+bar?foo+bar会产生完全相同的签名,即使+ 只能在表单data中解码为空格

I'd parse out the URL, add the ApplicationKey parameter to the parsed parameters, and then construct a new URL to sign. 我将解析出URL,将ApplicationKey参数添加到解析的参数中,然后构造一个新的URL进行签名。

Here's a version that does just that, and works both on Python 2 and on Python 3: 这是一个做到这一点的版本,并且可以在Python 2和Python 3上运行:

import hmac
import base64
from hashlib import sha1

try:
    # Python 3
    from urllib.parse import parse_qsl, unquote_plus, urlencode, urlparse
except ImportError:
    # Python 2
    from urlparse import urlparse, parse_qsl
    from urllib import unquote_plus, urlencode

def sign_url(url, key, secret):
    parsed = urlparse(url)
    query = parse_qsl(parsed.query)
    query.append(('ApplicationKey', key))
    to_sign = unquote_plus(parsed._replace(query=urlencode(query)).geturl())

    if not isinstance(secret, bytes):
        secret = secret.encode()
    if not isinstance(to_sign, bytes):
        to_sign = to_sign.encode()
    signature = base64.b64encode(hmac.new(secret, to_sign, sha1).digest())
    if not isinstance(signature, str):
        signature = signature.decode()

    query.append(('Signature', signature))
    return parsed._replace(query=urlencode(query)).geturl()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM