Websocket API signatures broken?

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:



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);
  // 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;

FWIW, I tested account.status as well as it has no note about Ed25519 and uses the same parameter (timestamp). Still can not get past the signature error.

I’ve also tested session.status which doesn’t require a signature. Works fine.

I’ve also verified that my own code generates the same signatures for my actual requests using my live key (HMAC) as in Binance’s own Node.js example here:

I’m seriously struggling to believe the websocket signature stuff on Binance’s side is even working.

I also verified my Ed25519 signing attempts using openssl for the timestamp=1578963600000 example (inside my text.txt file, without any newline) by making sure my own code using the same private key and input data generates the identical signature as:

openssl pkeyutl -in test.txt -rawin -sign -inkey .ssh/ed25519-priv.pem -hexdump

Needless to say by now, the Binance API server isn’t accepting these kinds of signatures either.

If anyone is having success with these signatures, just knowing you do would be helpful.

Another datapoint. I managed to successfully do HTTPS “rest style” signed API calls successfully using Ed25519 keys and signatures. For testing I found two API calls that only require the timestamp parameter. Using the same API call and signature building code, my test now outputs the following lines:

400 {"code":-1022,"msg":"Signature for this request is not valid...
200 {"makerCommission":10,"takerCommission":10,"buyerCommission"...

In short, it first tries to call the fapi end point with a signed request that fails. The second similar call to the regular api end point demonstrates it working. This is just regular HTTPS rest style API calls. But it is another indication that fapi isn’t quite behaving as expected (according to it’s own documentation).