首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何使用Vanilla Javascript:{"code":-2014,"msg":" API -key格式无效“在Binance API上生成有效签名。

如何使用Vanilla Javascript:{"code":-2014,"msg":" API -key格式无效“在Binance API上生成有效签名。
EN

Stack Overflow用户
提问于 2021-12-19 05:04:53
回答 1查看 1.2K关注 0票数 0

我花了几个小时试图从端点获得正确的响应。为此,我需要发送一个由SHA-256函数生成的签名字符串,该字符串附加到我发送到服务器的查询字符串。

我尝试过不同的方法来获得签名,如本文在文档化:数据和边缘端点安全性中所描述的那样,但是似乎没有什么效果。

我尝试过几种使用不同库和函数生成有效签名的方法,但它们都不起作用(我甚至尝试使用Web Crypto API文档)

当我打电话时,我会收到这个错误:

代码语言:javascript
代码运行次数:0
运行
复制
{"code":-2014,"msg":"API-key format invalid."}

这就是号召:

代码语言:javascript
代码运行次数:0
运行
复制
https://testnet.binance.vision/api/v3/account?timestamp=my_timestamp&signature=my_signature

我猜想这是获取的一个问题,但在我的应用程序中的其他自定义函数中,它不会引起任何问题。

这是我的密码:

代码语言:javascript
代码运行次数:0
运行
复制
export async function getAccountInfo() {
    const apiSecret = pub.TESTNET_SECRETKEY; // Your secret key

    const timestamp = await serverTimestamp()
        .then(timestamp => {
            return timestamp;
        });

    let signature = sha256(apiSecret, timestamp);

    const testnet = 'https://testnet.binance.vision/api';

    // {{url}}/api/v3/account?timestamp={{timestamp}}&signature={{signature}}

    const fullUrl = testnet + '/v3/account?timestamp=' + timestamp + '&signature=' + signature;

    retrieveInformation(fullUrl);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-19 05:04:53

我只是将不正确的时间戳字符串发送到哈希函数,在下面一行中:

代码语言:javascript
代码运行次数:0
运行
复制
let signature = sha256(apiSecret, timestamp); // Keep reading and you'll understand why.

香草JS溶液

虽然我使用了依赖项,但我认为这仍然是一个完全有效的解决方案。

https://www.npmjs.com/package/jhash.js --这些函数非常简单,可以直接使用。

问题

问题是在我发送给哈希函数的queryString中。

正如Binance API文档所解释的那样,尽管是模糊的:

  • 端点使用HMAC SHA256签名。HMAC SHA256签名是一个键控的HMAC SHA256操作。使用您的secretKey作为键,totalParams作为HMAC操作的值。
  • totalParams被定义为与请求体连接的查询字符串。

最后一点我真的很困惑。

现在,解决方案是将正确的字符串(queryString)发送到sha256函数中。API所需的内容是:

代码语言:javascript
代码运行次数:0
运行
复制
https://testnet.binance.vision/api/v3/account?timestamp=my_timestamp&signature=my_signature

timestamp=子字符串是解决我的问题的方法。我不得不将这段小代码发送到hex_hmac_sha256函数中,这是Binance所需的格式。

完整的解决方案。

代码语言:javascript
代码运行次数:0
运行
复制
async function serverTimestamp() {
    const url = 'https://testnet.binance.vision/api/v3/time';
    const timeServer = await getJson(url);
    return timeServer.serverTime;
}

不是本地时间,而是必须在签名内发送时间服务器。这就是解决问题的办法。

代码语言:javascript
代码运行次数:0
运行
复制
export async function getAccountInfo() {
    const apiSecret = pub.TESTNET_SECRETKEY; // Your secret key

    const timestamp = await serverTimestamp()
        .then(timestamp => {
            return timestamp;
        });

    const queried_timestamp = 'timestamp=' + timestamp;

    // https://www.npmjs.com/package/jhash.js
    let signature = JHash.hex_hmac_sha256(apiSecret, queried_timestamp);
    // let signature = await sha256(apiSecret, queried_timestamp); // This one is not library dependant.

    const testnet = 'https://testnet.binance.vision/api';

    // {{url}}/api/v3/account?timestamp={{timestamp}}&signature={{signature}}
    const fullUrl = testnet + '/v3/account?timestamp=' + timestamp + '&signature=' + signature; // + '&recvWindow=60000';
    retrieveInformation(fullUrl);
}

注意,在下面的代码行中,我将包含在URL中的字符串作为queryString发送。

代码语言:javascript
代码运行次数:0
运行
复制
let signature = JHash.hex_hmac_sha256(apiSecret, queried_timestamp);
// This is the same line than the one I wrote above,
// but using another version of the function.

这就是引导我走向正确方向的例子:https://developers.binance.com/docs/binance-api/spot/index/#example-1-as-a-request-body

正如您在正式文档示例中所看到的,它们呼应了制作签名的完整queryString。

现在,您可能需要更好地理解问题的其他功能:

代码语言:javascript
代码运行次数:0
运行
复制
async function retrieveInformation(url = null) {
    const apiKey = pub.TESTNET_APIKEY; // Your ApiKey
    let httpHeaders = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'X-MBX-APIKEY': apiKey
    }

    let myHeaders = new Headers(httpHeaders);
    var requestOptions = {
        headers: myHeaders
    };
    console.log(url);
    console.log(requestOptions);
    const data = await getJson(url, requestOptions);
    console.log(data);
    return data;
}

data显示为以下JSON对象:

代码语言:javascript
代码运行次数:0
运行
复制
{
  "makerCommission": 15,
  "takerCommission": 15,
  "buyerCommission": 0,
  "sellerCommission": 0,
  "canTrade": true,
  "canWithdraw": true,
  "canDeposit": true,
  "updateTime": 123456789,
  "accountType": "SPOT",
  "balances": [
    {
      "asset": "BTC",
      "free": "4723846.89208129",
      "locked": "0.00000000"
    },
    {
      "asset": "LTC",
      "free": "4763368.68006011",
      "locked": "0.00000000"
    }
  ],
  "permissions": [
    "SPOT"
  ]
}

您可以在API文档中看到同样的信息:数据

我使用的其他函数(这只是对这个答案的一个奖励,您可能会发现它们很有用)

下面是我使用的fetch函数:

代码语言:javascript
代码运行次数:0
运行
复制
async function getJson(url = null, requestOptions = null) {
    return fetch(url, requestOptions)
        .then((response) => {
            if (!response.ok) {
                throw Error(response.statusText);
            } else {
                const jsoned = response.json();
                return jsoned;
                // NOTE:
                //  response.json().then(data => {
                //      → do something with your data
                //  });
                //
            }
        })
        .catch(function (error) {
            console.log(error);
        });
}

下面是我能够使用sha256上的一些Mozilla文档(Crypto )的SubtleCrypto对象函数。它返回与依赖项相同的结果。

代码语言:javascript
代码运行次数:0
运行
复制
async function sha256(key, message) {
    
    // Step 1
    // encode as (utf-8) Uint8Array
    const msgUint8_key = new TextEncoder().encode(key);
    // encode as (utf-8) Uint8Array
    const msgUint8_message = new TextEncoder().encode(message);
    
    // Step 2
    const importedKey = await crypto.subtle.importKey('raw', msgUint8_key, {
        name: 'HMAC',
        hash: 'SHA-256'
    }, true, ['sign']);
    
    // Step 3
    const signedKey = await crypto.subtle.sign('HMAC', importedKey, msgUint8_message);
    // convert buffer to byte array
    const hashArray = Array.from(new Uint8Array(signedKey));
    // convert bytes to hex string    
    const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    return hashHex;
}

对于那些寻找更100 %香草解决方案的人来说,这是最后一个功能:

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70409091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档