I am struggling with authenticating my websocket connection using the session.logon
call. All my attempts are getting the {code: -1022, msg: 'Signature for this request is not valid.'}
error.
I have successfully implemented the signature signing code in javascript running in my browser, according to this example:
With the same inputs I get the correct signature.
But when I try the call to session.logon
with a properly generated timestamp (and request string) and calculate the signature using my own secretKey, it fails with the error as described.
Diving into all the details, I notice that with the correct signature example, the signing uses HMAC and SHA-256.
However. looking into the websocket api docs here:
I notice the following comment: “Session Authentication. Note: Only Ed25519 keys are supported for this feature.”. If this is correct, the binance signature example is useless for this.
Regardless, I have gone down the rabbit hole and generated the proper private and public Ed25519 key pair, and created a separate API token using Ed25519 (PEM encoded, as Binance insist on). To get this to work in Chrome, I needed to enable “experimental platform features”. In addition to this, there are ways of getting lost in how the secret key is encoded and imported in the browser, and how to tell the browser to use this key for signing.
I’m pasting in some of the code that generates the correct signature for the simpler non-Ed25519 example, where I’ve also commented out some tests I’ve done to get it to use the Ed25519 stuff, but I am still not successful.
Has anybody been able to succeed with this (the websocket session.logon using Ed25519) call at all? Care to share the details on signing etc? Has anybody succeeded using the websocket APIs without the session.logon call (signing every request I guess), and did it then work with a “normal” key (non-Ed25519)?
And finally, it seems the URL for the Futures API endpoint is moving around a bit as well, so in theory I guess I might be calling some wrong endpoint as well (although getting the signature error indicates I may not be that wrong). The URL I’m calling is:
wss://ws-fapi.binance.com/ws-fapi/v1
Thanks.
Code below:
const encoder = new TextEncoder();
const decoder = new TextDecoder('utf-8');
async function sha256(key, message) {
// Step 1
// encode as (utf-8) Uint8Array
const msgUint8_key = encoder.encode(key);
//const msgUint8_key = base64toUint8(key);
//console.log({msgUint8_key});
// encode as (utf-8) Uint8Array
const msgUint8_message = encoder.encode(message);
// Step 2
const importedKey = await crypto.subtle.importKey('raw', msgUint8_key, {
name: 'HMAC',
//name: 'Ed25519',
hash: 'SHA-256'
}, true, ['sign']);
// Step 3
const signedKey = await crypto.subtle.sign('HMAC', importedKey, msgUint8_message);
//const signedKey = await crypto.subtle.sign('Ed25519', 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;
}