Coinbase API 标准 python 示例返回"invalid signature"



我正在尝试将Coinbase API与Python一起使用,从Coinbase Developer API页面上的标准示例开始:https://developers.coinbase.com/docs/wallet/api-key-authentication#

这段代码只给了我错误,比如:

TypeError: key: expected bytes or bytearray, but got 'str'

经过一些谷歌搜索,我做了一些调整,让我走得更远,但我仍然不在那里。API文档页面是否给出了一个过时的示例?

现在返回给我的主要消息是:{"id":"authentication_error","message":"invalid signature"}

我正在使用以下代码(用xxxxxx替换我的密钥(:

import json, hmac, hashlib, time, requests
from requests.auth import AuthBase
# Before implementation, set environmental variables with the names API_KEY and API_SECRET
API_KEY = 'xxxxxxx'
API_SECRET = b'xxxxxxx'
def get_timestamp():
return int(time.time() * 1000)

# Create custom authentication for Coinbase API
class CoinbaseWalletAuth(AuthBase):
def __init__(self, api_key, secret_key):
self.api_key = api_key
self.secret_key = secret_key
def __call__(self, request):
timestamp = str(int(time.time()))
print(timestamp)
message = timestamp + request.method + request.path_url + (request.body or b'').decode()
hmac_key = base64.b64decode(self.secret_key)
signature = hmac.new(hmac_key, message.encode(), hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode()

request.headers.update({
'CB-ACCESS-SIGN': signature_b64,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
'Content-Type': 'application/json'
})
return request

api_url = 'https://api.coinbase.com/v2/'
auth = CoinbaseWalletAuth(API_KEY, API_SECRET)
# Get current user
r = requests.get(api_url + 'user', auth=auth)
print(r.json())
# {u'data': {u'username': None, u'resource': u'user', u'name': u'User'...

希望你能帮我解决这个问题。这似乎只是把基本的东西做好了。。。

首先要提到的是,你链接的他们页面中的代码是python2,如果你用它运行他们的代码,它会很好地工作。

我今天遇到了同样的问题,并意识到您的代码有多个问题(因为我认为您已经尽了一切努力来修复它(,所以我为您修复了这些问题,并且截至今天(04/28/21(,python3或API中的请求库有问题。我想出了一个解决办法。

import json, hmac, hashlib, time, requests
from requests.auth import AuthBase
# Before implementation, set environmental variables with the names API_KEY and API_SECRET
API_KEY = 'xxxxxxx'
API_SECRET = 'xxxxxxx'

# Create custom authentication for Coinbase API
class CoinbaseWalletAuth(AuthBase):
def __init__(self, api_key, secret_key):
self.api_key = api_key
self.secret_key = secret_key
def __call__(self, request):
timestamp = str(int(time.time()))
# the following try statement will fix the bug
try:
body = request.body.decode()
if body == "{}":
request.body = b""
body = ''
except AttributeError:
request.body = b""
body = ''
message = timestamp + request.method + request.path_url + body
signature = hmac.new(self.secret_key.encode(), message.encode(), hashlib.sha256).hexdigest()
request.headers.update({
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
})
return request

api_url = 'https://api.coinbase.com/v2/'
auth = CoinbaseWalletAuth(API_KEY, API_SECRET)
# Get current user
r = requests.get(api_url + 'user', auth=auth)
print(r.json())
# {u'data': {u'username': None, u'resource': u'user', u'name': u'User'...

现在将其保存为test.py,并使用python3 test.py运行,前提是您的环境/系统中安装了库。

至于为什么会有bug
故障排除我发现request.body必须为空,API才能喜欢它(空指的是''(,因为它不希望该特定端点有正文。这是关于请求库的一个假设,当您在调用中指定设置为JSON的内容类型或使用json=,并且它看到您有一个空的正文时,它将自动用{}填充正文。这是有道理的,因为你不想说你要发送json但没有发送任何东西来攻击服务器,所以python3中的请求对服务器来说只是很好。在python2中,请求库不会自动执行此操作。这对我们来说成了一个问题,因为如果端点不带主体,API喜欢主体完全为空。

为什么要修复它
我不知道,因为这不是签名身份验证问题。我检查了运行中的python2版本和python3版本,结果签名相同,因此不是身份验证问题。服务器似乎不灵活,因为它们的请求体是一个空的JSON对象。

因此,为了解决这个问题,我们必须在看到body设置为{}时清除请求的body。

TLDR:
服务器错误地认为这是一个签名/身份验证问题,而实际上是一个糟糕的请求。看看代码。

相关内容

最新更新