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.