如何使用HMAC-SHA512和Python请求库签署POST请求?

Wer*_*hli 11 python hmac python-requests

我正在尝试使用Python来访问poloniex.com上的交易API,这是一种加密货币交换.要做到这一点,我必须遵循这个处方:

所有对交易API的调用都通过HTTP POST发送到https://poloniex.com/tradingApi,并且必须包含以下标题:

密钥 - 您的API密钥.
Sign - 根据HMAC-SHA512方法,由密钥的"秘密"签名的查询的POST数据.

此外,所有查询都必须包含"nonce"POST参数.nonce参数是一个整数,必须始终大于之前使用的nonce.

这是我到目前为止所拥有的.我目前的问题是我不知道如何编译POST网址,以便可以在不先发送未完成请求的情况下对其进行签名.这显然不起作用.

import requests
import hmac
import hashlib
import time

headers = { 'nonce': '',
            'Key' : 'myKey',
            'Sign': '',}
payload = { 'command': 'returnCompleteBalances',
            'account': 'all'}
secret = 'mySecret'

headers['nonce'] = int(time.time())
response = requests.post( 'https://poloniex.com/tradingApi', params= payload, headers= headers )
headers['Sign'] = hmac.new( secret, response.url, hashlib.sha512)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 21

创建准备好的请求 ; 您可以在创建正文后为其添加标题:

import requests
import hmac
import hashlib


request = requests.Request(
    'POST', 'https://poloniex.com/tradingApi',
    data=payload, headers=headers)
prepped = request.prepare()
signature = hmac.new(secret, prepped.body, digestmod=hashlib.sha512)
prepped.headers['Sign'] = signature.hexdigest()

with requests.Session() as session:
    response = session.send(prepped)
Run Code Online (Sandbox Code Playgroud)

我改变了你的params论点data; 对于POST请求,通常在主体中发送参数,而不是URL.

对于nonce,我会使用一个从当前时间播种的itertools.count()对象,因此重启不会影响它.根据Poloniex API文档(您在问题中引用),nonce是POST主体的一部分,而不是标题,因此将其放在payload字典中:

from itertools import count
import time

# store as a global variable
NONCE_COUNTER = count(int(time.time() * 1000))

# then every time you create a request
payload['nonce'] = next(NONCE_COUNTER)
Run Code Online (Sandbox Code Playgroud)

int(time.time())如果您每秒创建多个请求,则使用将重复使用相同的数字.在由Poloniex提供的示例代码使用int(time.time()*1000),以使其能够创建请求每微秒,而不是,而是用自己的单调递增计数器(从种子time.time())是稳健得多.

您还可以将摘要签名过程封装在自定义身份验证对象中 ; 这样的对象在准备好的请求中作为准备的最后一步传递:

import hmac
import hashlib

class BodyDigestSignature(object):
    def __init__(self, secret, header='Sign', algorithm=hashlib.sha512):
        self.secret = secret
        self.header = header
        self.algorithm = algorithm

    def __call__(self, request):
        body = request.body
        if not isinstance(body, bytes):   # Python 3
            body = body.encode('latin1')  # standard encoding for HTTP
        signature = hmac.new(self.secret, body, digestmod=self.algorithm)
        request.headers[self.header] = signature.hexdigest()
        return request
Run Code Online (Sandbox Code Playgroud)

与您的requests通话一起使用:

response = requests.post(
    'https://poloniex.com/tradingApi',
    data=payload, headers=headers, auth=BodyDigestSignature(secret))
Run Code Online (Sandbox Code Playgroud)

传入的论点是HMAC摘要中使用的秘密; 您还可以传入不同的标题名称.