I'm trying to verify ownership of a Bitcoin address using the public key, signature, and the address (P2PKH, P2SH, P2WPKH, P2WSH, P2TR) as input. However, the code below does not work for Bech32 addresses.

import BitCoinLib from 'bitcoinjs-lib';
import BitCoinMessage from 'bitcoinjs-message';

BitCoinMessage.verify(message, address, signature);

As another attempt, I tried using bitcore-lib, but it doesn't support address verification. It only accepts public key and signature as inputs.

import bitcore from 'bitcore-lib';

export function verifyMessage(publicKey, sig, text) {
    const message = new bitcore.Message(text);
    var signature = bitcore.crypto.Signature.fromCompact(
      Buffer.from(sig, "base64")
    var hash = message.magicHash();
    // recover the public key
    var ecdsa = new bitcore.crypto.ECDSA();
    ecdsa.hashbuf = hash;
    ecdsa.sig = signature;
    const pubkeyInSig = ecdsa.toPublicKey();
    const pubkeyInSigString = new bitcore.PublicKey(
      Object.assign({}, pubkeyInSig.toObject(), { compressed: true })
    if (pubkeyInSigString != publicKey) {
      return false;
    return bitcore.crypto.ECDSA.verify(hash, signature, pubkeyInSig);

What I want to achieve is similar to https://www.verifybitcoinmessage.com/, but that site also has limitations as it cannot verify P2WPKH addresses.

Is it possible to verify all types of addresses? If so, please provide guidance on how to do it.

1 Answer 1


bitcoinjs-message uses traditional signing process which simply sign message with prefix(if not given) \x18Bitcoin Signed Message:\n. This kind of signing schema has been common but has limitation as it only supports p2pkh. There are implementations which support other type of address with this schema(bitcoinjs-message also supports p2wpkh and p2sh-p2wpkh, but not p2tr), but there's no strict standard for it.

BIP322 suggests a new way of signing schema, in which virtual transaction is required to sign and verify all types of addresses while p2pkh uses traditional signing process. However, it's still in development and not yet implemented in bitcoin-core as I know.

I was also looking for bip322 message signing library, and just end up implementing it by myself. If you need you can use it. My open source bitcoin-sdk-js has a feature of bip322 signing and verifying message with javascript, which support p2pkh, p2wpkh and p2tr. It's verified with bip322 test vector so you can use it. I would try to follow development of bitcoin-core. Be careful as BIP322 itself is in transition.

Below is how to implement.

import * as bitcoin from 'bitcoin-sdk-js'

const keyPair = await bitcoin.wallet.generateKeyPair();
const privkey = keyPair.privateKey;
const pubkey = keyPair.publicKey;
const legacyAddress = await bitcoin.address.generateAddress(
const segwitAddress = await bitcoin.address.generateAddress(
const tapAddress = await bitcoin.address.generateAddress(
    await bitcoin.tapscript.getTapTweakedPubkey(
      await bitcoin.tapscript.getTapTweak(pubkey.slice(2)),
const msg = 'message you want to sign';
// When
const sigLegacy = await bitcoin.crypto.signMessage(
const sigSegwit = await bitcoin.crypto.signMessage(
const sigTap = await bitcoin.crypto.signMessage(msg, privkey, tapAddress);
// Then
  await bitcoin.crypto.verifyMessage(msg, sigLegacy, legacyAddress),
  await bitcoin.crypto.verifyMessage(msg, sigSegwit, segwitAddress),
  await bitcoin.crypto.verifyMessage(msg, sigTap, tapAddress),

p.s. I think the website you refer might have an issue with non-ASCII encoding, I recommend this website to test traditional message signing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.