Bitcoin

Message signing – How to check if a signature is signed by Pubkey? Taproot and BIP0322

Wallets like XVerse allow users to sign messages using an ordinal BTC address (let’s say bc1XXX), and the messages are hashed based on BIP0322.

So I have:

  • User Wallet: bc1XXX
  • Message hash: YYY
  • Signed by bc1XXX: ZZZ

So this data is sent to my backend server, and I want to check that ZZZ is actually signed by bc1XXX (and contains YYY as the message).

I’m using this so far:

    const msgHash = bip0322Hash(message);
    const signatureBuffer = Buffer.from(signatureStr, 'base64');

    const decodedSignature = signatureBuffer.slice(2, 66);
    const recoveryId = signatureBuffer(0);

    // Extract public key from the signature
    const recoveredPublicKeyBuffer = secp.recoverPublicKey(
        msgHash,
        decodedSignature,
        recoveryId, // Recovery ID (0 or 1)
        false
    );
    console.log(publicKeyToTaprootAddress(recoveredPublicKeyBuffer)); //no match with my original pubkey that signed the message

But it’s difficult to get the exact address. recoveredPublicKeyBuffer It cannot match the public key address in my test set.

I’m trying to use this function, but the output doesn’t match my public key.

    function publicKeyToTaprootAddress(publicKey: Uint8Array) 
        // Compute the SHA-256 hash of the public key
        const hash = sha256(Buffer.from(publicKey));

        // Construct the human-readable part and the data part of the Bech32m string
        const hrp = 'bc';
        const data = sha256(Buffer.from((0x01).concat(Array.from(hash))));
        const data2 = bech32m.toWords(Buffer.from(data));

        // Encode the Bech32m string
        return bech32m.encode(hrp, data2);
     

Related Articles

Back to top button