Signature Validation via Node.js

Hi,

I’m trying to validate a message signed on the client side using the backend (Node.js). Specifically, I’m using utils.validateSignature, but I’m encountering the following error:
Invalid byte sequence

Here’s a sample of the data being sent:

Message: test

Signature: a74fe44a023fecc6bfdc39e9161ef2e83102990ade9ee731184fae59aea60487b8d5b65fbf8a4bd26b9b90f42a19973f2a2413642d59e42537e3bdc44ec9b70f

Address: klv159vrgc50hqnr44zn25cdndmdwgrqvdsajax58asmslmqhcjfunwqktvupu

The signature appears to be valid. I successfully verified it on KleverScan’s Verify Signature tool.

Has anyone run into this issue? Could this be an encoding mismatch, or am I using the wrong format for utils.validateSignature?

Thanks in advance!

2 Likes

Hello @shymelon!

You’re encountering two distinct problems. Let me walk you through both and their solutions:

Problem 1: Invalid Byte Sequence

The “Invalid byte sequence” error occurs because you need to pass a byte array to the method instead of a string.

Instead of:

utils.validateSignature("test"...

Use:

utils.validateSignature(new TextEncoder().encode("test")...

This ensures you’re passing bytes to the signature function, which will resolve the invalid bytes error.

Problem 2: Client vs Backend Signature Differences

After fixing the first issue, you’ll notice that the signature validation still fails. This happens because client-side signatures are not directly compatible with backend verification.

Here’s why:

  • Client-side signatures are designed for on-chain message signing
  • Backend signatures can sign any message for general use

The key difference: Client-side signatures format the message before signing by adding a prefix:

Format: <Klever Prefix><MessageLength><Actual Message>

Example: When you sign “test” client-side, it actually signs:

\x17Klever Signed Message:\n4test

Solution: Message Hash Function

To validate client-side signatures on the backend, you need to apply the message hash function. Here’s a proof of concept using your parameters:

Since the SDK-node doesn’t currently include the message hash function, I’ve created an implementation to unblock your development:

import sha3 from "js-sha3";

// MessageHash returns hash of message to sign
function messageHash(message) {
  const signPrefix = "\x17Klever Signed Message:\n"
  const messageLength = message.length.toString();
  const messageLengthBytes = new TextEncoder().encode(messageLength);
  
  // Create array to hold all bytes
  const toSign = new Uint8Array(signPrefix.length + messageLengthBytes.length + message.length);
  
  // Copy signPrefix
  toSign.set(new TextEncoder().encode(signPrefix), 0);
  
  // Copy message length bytes
  toSign.set(messageLengthBytes, signPrefix.length);
  
  // Copy message
  toSign.set(new TextEncoder().encode(message), signPrefix.length + messageLengthBytes.length);
  // Return keccak256 hash
  return new Uint8Array(sha3.keccak256.arrayBuffer(toSign));
}

Note: I’ll request that the SDK team include this message hash function in future releases.

Hope this helps! Feel free to ask anything if you need further clarification.

5 Likes

Hey Nicollas,
Thanks a lot for the detailed response, everything’s working perfectly now! :fire:

Just a small note: the docs at klever.gitbook.io mention that the method accepts a string, not a Uint8Array. Thought I’d point it out in case it causes confusion for others.

If PRs are welcome, I’d be happy to help update the docs and add an example to the Node.js section.

Cheers!

2 Likes

Hello @shymelon nice to see you solve your question.

So, the docs at gitbook isn’t used anymore. Please use the https://docs.klever.org/ instead. And yes, PR are always welcome. You can create one and send to us at klever-io/klever-docs

TY again and have a nice week, bro

2 Likes