Bitcoin Signed Messages
Every time a wallet spends coins, it proves that it holds the right Private Key by producing a Signature over the Transaction. Sometimes we want that proof without spending anything, e.g. to show that we control an Address before someone pays to it, or to log in to a service with a key we already hold.
A Bitcoin Signed Message is exactly that: an ordinary ECDSA Signature, made with the same Private Key and the same curve as a Transaction Signature, but over a piece of text in place of a Transaction. The format comes from the original Bitcoin client, and most wallets can create and check these Signatures. In this section we will look at how a message is signed, how the Signature is checked, and what it does and doesn’t prove.
Signing a message
Section titled “Signing a message”Figure 1 shows how a wallet signs the message hello, world. The values are real ones, for a testnet key used in our library examples.
Referring to Figure 1, we notice a few interesting things:
- The message is not signed as it is. It is first placed behind a fixed magic prefix, the text
Bitcoin Signed Message:followed by a newline. Both the prefix and the message are preceded by their lengths, as variable-length integers:18is 24, the length of the prefix, and0cis 12, the length ofhello, world. - These bytes are hashed twice with SHA-256, as we do with Transactions.
- The hash is signed with ECDSA, using the Private Key. This gives the two numbers that make up every ECDSA Signature, r and s.
- The wallet also works out a recovery id, a number from
0to3that we will need when we check the Signature. It goes into a header byte, as27 + recovery id, plus4if the Public Key is compressed. Our header byte is1f, or 31, i.e. a compressed key with a recovery id of0. - The header byte, r and s make up a 65-byte compact Signature, which is encoded in base64 so that it can be pasted into an email or a web form.
Why the magic prefix? A wallet that will sign any 32 bytes it is given can be tricked into signing the hash of a Transaction, and with it a payment. Because a signed message is always hashed behind the prefix, its hash can never be that of a Transaction, so signing a message can never spend coins.
Verifying a message
Section titled “Verifying a message”To check a Signature, one needs the message, the Signature, and the Address the Signature claims to come from. Figure 2 shows how.
Referring to Figure 2:
- The verifier hashes the message exactly as the signer did, magic prefix and all.
- From the hash, r and s, ECDSA allows us to work backwards to the Public Key that made the Signature. In general up to four Public Keys fit, and the recovery id in the header byte tells us which one is meant. This is called Public Key recovery.
- The recovered Public Key is hashed and encoded into an Address, as we described in Addresses. The header byte tells us whether to use the compressed or uncompressed form of the key.
- If the recovered Address is the same as the claimed Address, the Signature is valid. If the message has been changed by as much as one character, a different Public Key is recovered, and the Addresses don’t match.
This is why the Signature carries a recovery id at all. The signer never has to hand over their Public Key, and an Address is all the verifier needs. Where the verifier does hold the signer’s Public Key, they can of course compare Public Keys directly, or check the Signature with ordinary ECDSA verification.
It should be noted that one Private Key can make many different, equally valid Signatures over the same message. Each ECDSA Signature uses a secret random number, so two wallets signing
hello, worldwith the key of Figure 1 will produce two different Signatures, and both will verify. Don’t compare Signatures to decide whether two messages were signed by the same key. Verify each one.
What a Signature proves
Section titled “What a Signature proves”A valid Signature proves one thing only: that whoever made it held the Private Key behind the Address at the moment they signed. It is worth being careful about what it does not prove:
- It doesn’t prove that the signer still holds any coins. The coins at an Address may have been spent long ago.
- It doesn’t say when, or for whom, it was made. A Signature over
I own this Addresscan be copied and shown to anyone, at any time, by anyone who has seen it. - It doesn’t prove that the signer is a particular person, only that they held a particular key.
The short of it, is that a Signature should be over a message that can’t be reused. A service that asks a wallet to prove control of an Address should hand it a challenge to sign: a fresh random value, together with the name of the service and the date. A Signature over that message is no use to anyone else, and no use tomorrow.
Please note that a user should read a message before their wallet signs it. The magic prefix keeps a signed message from ever spending coins, but the words of the message can still be used against the signer, e.g. a message that says they agree to something they didn’t.
Signed messages in our applications
Section titled “Signed messages in our applications”Bitcoin Signed Messages tie a Signature to an Address, and so they share the limits of Addresses: the same key keeps being used, and nothing in the Signature says who it was meant for. In the BRC-100 ecosystem, wallets sign messages with keys derived for the purpose with BRC-42, as described in BRC-77, and two parties prove their identity to each other with the mutual authentication of BRC-103 in place of signing a challenge by hand. Bitcoin Signed Messages remain the most widely understood way of proving control of an Address, and every wallet that can check one does it the same way.
Both of our libraries implement Bitcoin Signed Messages. You can see how to sign a message, and verify one against an Address or a Public Key, in DartSV and Bitcoin4J.

