【问题标题】:Coinbase API standard python example returns "invalid signature"Coinbase API 标准 python 示例返回“无效签名”
【发布时间】:2021-03-13 22:18:26
【问题描述】:

我正在尝试将 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'...

希望你能帮我解决这个问题。看来这只是在掌握基础知识...

【问题讨论】:

  • 我在使用 Coinbase API 时遇到了同样的问题。对于 POST,我一直得到无效签名。我正在使用 PHP 和 Curl。如果你让它工作,那么请发布答案。谢谢。

标签: python api signature coinbase-api


【解决方案1】:

首先要提到的是,您链接的页面中的代码是 python2,如果您使用它运行他们的代码,它可以立即运行。

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

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 运行,前提是您已在环境/系统中安装了这些库。

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

为什么这会解决它?
我不知道,因为这不是签名认证问题。我检查了工作 python2 版本和 python3 版本,并且签名相同,因此不是身份验证问题。看起来服务器不灵活,他们的请求正文是一个空的 JSON 对象。

因此,作为解决此问题的回顾,我们必须在看到正文设置为 {} 时清除请求正文。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 2022-06-19
    • 1970-01-01
    • 2019-01-12
    • 2015-04-21
    • 1970-01-01
    • 2015-10-17
    相关资源
    最近更新 更多