python hmac新sha1

2024-06-25 23:54:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图得到与this online API service produces相同的结果。你知道吗

通过输入key作为应用程序密钥,secret作为机密,将生成以下URL:

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

我尝试使用以下代码生成相同的签名:

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

但这会产生:

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

预期签名为

YXWJsGSKnLcENW1vm30EYObbCsA=

但是我的代码输出

W//jgV+xdSbTBG6+i1TCGN/Kbsk=

Tags: keyorgimportwebhttpurlsecretservice
1条回答
网友
1楼 · 发布于 2024-06-25 23:54:46

您的版本在Application=参数之前缺少必需的?组件。但是,如果有其他参数,可能需要添加&,并且需要删除.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])

但是我注意到,当URL包含URL编码元素时,签名似乎应用于URL解码版本(将+解释为空格),因此在签名时确实需要添加urllib.unquote_plus()(Python2)/urllib.parse.unquote_plus()(Python3)调用:

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

我已经确认了这就是他们的PHP example code所做的,并且验证了online signature tool中的示例查询参数,例如,当将路径和参数foo%20bar?foo%20bar输入工具时,CCuMYpCDznH4vIv95+NrN+RHEK0=作为签名生成,但是使用foo+bar?foo+bar生成完全相同的签名,即使+should only be decoded as a space in form data。你知道吗

我将解析出URL,将ApplicationKey参数添加到解析的参数中,然后构造一个新的URL进行签名。你知道吗

这里有一个版本可以做到这一点,它同时适用于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()

相关问题 更多 >