Verify message signature

Signature verification depends on the type of address the message was signed with

Ordinals Address P2TR

Message signing for P2TR addresses conform to the BIP-322 standard. The following options are available for message verification. Note that due to the experimental nature of BIP-322 none of the following options are officially endorsed or audited. Use at your own risk.

Payment Address p2sh(p2wpkh)

function magicHash (message, messagePrefix) {
messagePrefix = messagePrefix || '\u0018Bitcoin Signed Message:\n'
if (!Buffer.isBuffer(messagePrefix)) {
messagePrefix = Buffer.from(messagePrefix, 'utf8')
}
if (!Buffer.isBuffer(message)) {
message = Buffer.from(message, 'utf8')
}
const messageVISize = varuint.encodingLength(message.length)
const buffer = Buffer.allocUnsafe(
messagePrefix.length + messageVISize + message.length
)
messagePrefix.copy(buffer, 0)
varuint.encode(message.length, buffer, messagePrefix.length)
message.copy(buffer, messagePrefix.length + messageVISize)
return hash256(buffer)
}
function verify (message, address, signature, messagePrefix, checkSegwitAlways) {
if (!Buffer.isBuffer(signature)) signature = Buffer.from(signature, 'base64')
const parsed = decodeSignature(signature)
if (checkSegwitAlways && !parsed.compressed) {
throw new Error('checkSegwitAlways can only be used with a compressed pubkey signature flagbyte')
}
const hash = magicHash(message, messagePrefix)
const publicKey = secp256k1.recover(
hash,
parsed.signature,
parsed.recovery,
parsed.compressed
)
const publicKeyHash = hash160(publicKey)
let actual, expected
if (parsed.segwitType) {
if (parsed.segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
actual = segwitRedeemHash(publicKeyHash)
expected = bs58check.decode(address).slice(1)
} else {
// parsed.segwitType === SEGWIT_TYPES.P2WPKH
// must be true since we only return null, P2SH_P2WPKH, or P2WPKH
// from the decodeSignature function.
actual = publicKeyHash
expected = decodeBech32(address)
}
} else {
if (checkSegwitAlways) {
try {
expected = decodeBech32(address)
// if address is bech32 it is not p2sh
return bufferEquals(publicKeyHash, expected)
} catch (e) {
const redeemHash = segwitRedeemHash(publicKeyHash)
expected = bs58check.decode(address).slice(1)
// base58 can be p2pkh or p2sh-p2wpkh
return (
bufferEquals(publicKeyHash, expected) ||
bufferEquals(redeemHash, expected)
)
}
} else {
actual = publicKeyHash
expected = bs58check.decode(address).slice(1)
}
}