跳到主要内容
ecdsa.com

比特币消息验证工具

粘贴地址、与签名时完全一致的消息及其签名。验证工具会识别格式——BIP-137 紧凑签名,或 BIP-322 简单签名或完整签名——并按花费该地址时的方式检查签名,全程在你的浏览器中完成。

100% 本地运行——所有操作都在你的浏览器中完成,不会向任何服务器发送数据

正在加载验证工具…

填写地址、消息和签名,或加载示例。签名会在你输入时直接在此页面上检查。

此验证工具不评估的内容

  • 时间锁:如果完整签名的脚本需要锁定时间或序列号(CLTV、CSV),结果会报告为“不支持”,既不算有效,也不算无效。
  • Taproot 脚本路径:只检查密钥路径签名;花费脚本路径的情况会报告为“不支持”。
  • 其他脚本:当脚本是单个密钥或裸多签时,会检查 P2SH 和 P2WSH;凡是需要完整脚本解释器的情况都会报告为“不支持”。
  • 资金证明:BIP-322 的“pof”签名同时会花费真实的币,此处不验证。

Two formats for one question

A signed message answers a simple question — does the person who sent this control that address? — and Bitcoin has two answers. The older one, standardised as BIP-137, is the "Bitcoin Signed Message" that Bitcoin Core's signmessage, Electrum, Trezor and Ledger produce. The newer one, BIP-322, proves control the way a real spend would, so it works for every kind of address, Taproot and multisig included. The verifier tells them apart from the signature itself; the comparison BIP-137 vs BIP-322 and the article on Bitcoin message signing explain when to use which.

BIP-137: a recoverable signature

The message is prefixed with "\x18Bitcoin Signed Message:\n" and its length, and hashed twice with SHA-256. The 65-byte signature is a compact ECDSA signature with a header byte in front. The header carries the recovery id, which lets the verifier compute the signer's public key from the signature alone (public key recovery), and the address type it was made for: 27–30 for P2PKH with an uncompressed key, 31–34 compressed, 35–38 nested SegWit (P2SH-P2WPKH), 39–42 native SegWit (P2WPKH). The recovered key is turned into an address of that type and compared with the one you entered.

Electrum writes the P2PKH header (31–34) for SegWit addresses too. The verifier accepts such a signature when the recovered key matches the SegWit address, and says so: Bitcoin Core would reject it, because Core verifies P2PKH addresses only (its "Address does not refer to key" error). A key that matches under another address type than the header names is accepted with the same caveat; a key that matches no type is reported together with the address it does belong to. BIP-137 cannot express Taproot or P2WSH addresses at all — for those, only BIP-322 exists.

BIP-322: a spend that never happens

BIP-322 hashes the message with the tagged hash "BIP0322-signed-message" and puts it into a virtual transaction, to_spend, whose single output pays the address's script. A second virtual transaction, to_sign, spends that output to an OP_RETURN. The signature is the proof that to_sign is a valid spend:

  • a simple signature (smp…, or the bare base64 that older verifiers wrote) is just the witness stack, for native SegWit and Taproot addresses;
  • a full signature (ful…) is the whole to_sign transaction, which also covers legacy and P2SH addresses.

The verifier rebuilds both transactions, checks that the full signature spends exactly the right output, and evaluates the spend with the consensus signature hashes: legacy, BIP-143 for SegWit v0 and BIP-341 with Schnorr signatures (BIP-340) for Taproot key paths. Single-key scripts and bare multisig (OP_m … OP_n OP_CHECKMULTISIG, in key order, with the empty NULLDUMMY element) are checked in P2SH, P2WSH and nested forms. Strict DER (BIP-66) is enforced; a high-s signature or an unusual sighash type is accepted with a note, as consensus does.

What it does not evaluate

The verifier evaluates the scripts it can check without a full script interpreter, and says "unsupported" — neither valid nor invalid — for the rest:

  • time locks — scripts with OP_CHECKLOCKTIMEVERIFY or OP_CHECKSEQUENCEVERIFY, whose full signatures set a lock time or sequence;
  • Taproot script paths — only key-path spends are checked;
  • other scripts — hash locks, miniscript policies and anything beyond a single key or bare multisig;
  • proof of funds (pof…) — a BIP-322 variant that also spends real coins, which needs the UTXO set.

Unsupported is not a failure: it means this page cannot decide, and a node with a full interpreter (or the signer's own wallet) must.

What runs locally

Everything: parsing, key recovery, the virtual transactions and every signature check run in your browser with @noble/curves and @scure/btc-signer, and the page sends nothing anywhere. A signature never needs a private key; if a WIF key or a seed phrase is pasted by mistake, it is refused before anything is processed. Wallets that export the armored "BEGIN BITCOIN SIGNED MESSAGE" block can paste it whole into the message field. To inspect a transaction that spends real coins, use the PSBT inspector; to see which addresses an extended public key derives, the xpub inspector.