Author

Topic: getting the address that signed a message (Read 824 times)

kjj
legendary
Activity: 1302
Merit: 1026
November 02, 2012, 11:38:58 PM
#1
This may be unsafe.  Be careful.

Signature verification in ECDSA has an interesting quirk.  When you are validating a message, you end up with the public key of the private key that must have created the signature.  For safety reasons, the bitcoin client requires that you provide an address to the verification function, which then finds the public key from the message and the signature, and then returns true or false depending on whether or not that public key hashes to the address provided.

Because signatures include a random component, an attacker can easily keep trying until they find a valid signature for an address that "looks like" the real address.  For a human typing on the command line, this means that it is very unsafe to take just the message and signature and return the key.  If you do this, sooner or later, you will be fooled and you will think that a signature was valid when it really wasn't.

However, think about this other usage...  You have a website, and you don't want to make people register for it.  You just ask them for a bitcoin address that they will sign their messages with.  You stash that in your database, and then whenever commands come in, you take the command and the signature, and find the address that signed the message, then look that address up in your user database.  If you find a match, you know that the command came from a real user, and you know which user.  Obviously, this system won't be fooled by a second address that merely looks similar.

What would this look like?

Code:
kjj@inana:~$ bitcoind verifymessage "1EB28gbcAXsedys1UYTS8gcAJTiN8MHUSh" "Gy8cnYtUohz3wiUZFg4zqbWGulKWSMU0ady3Cbpvo6qZPFgtX5EJ8aNvnE/Sus51nMadDVbTDqDAmR/2prZGJko=" "bitcoin:15kfzDMX2Gr7hXrwRQQGkxrd5eBveKH777?amount=1&message=donation"
false

kjj@inana:~$ bitcoind verifymessage "19mP9FKrXqL46Si58pHdhGKow88SUPy1V8 ""Gy8cnYtUohz3wiUZFg4zqbWGulKWSMU0ady3Cbpvo6qZPFgtX5EJ8aNvnE/Sus51nMadDVbTDqDAmR/2prZGJko=" "bitcoin:15kfzDMX2Gr7hXrwRQQGkxrd5eBveKH777?amount=1&message=donation"
true

kjj@inana:~$ bitcoind verifymessage "?" "Gy8cnYtUohz3wiUZFg4zqbWGulKWSMU0ady3Cbpvo6qZPFgtX5EJ8aNvnE/Sus51nMadDVbTDqDAmR/2prZGJko=" "bitcoin:15kfzDMX2Gr7hXrwRQQGkxrd5eBveKH777?amount=1&message=donation"
19mP9FKrXqL46Si58pHdhGKow88SUPy1V8

In the third usage, verifymessage takes a literal question mark character where the address should be and returns the address corresponding to the message and signature.  This example was taken from https://ecdsa.org/bitcoin_URIs.html, just the first google result I came across with a valid message and address in it.  The first command is with a bogus key that I made up, and the second is with the correct key.  Together they show the safe (normal) behavior of the client, which is to require a proper address for verification, and return simply true or false if that key matches or not.

This functionality was left out intentionally to avoid users doing unsafe things.  I agree that this can be dangerous, but I don't think that it necessarily has to be.  So I'm just going to drop this here and let it sink quietly into the depths of Google's memory.  If anyone thinks that this would be useful for them, they can contact me for a patch.

Oh, and if you can follow EC math this can be done fairly easily outside of bitcoind too, and several devs have expressed the opinion that it should remain outside of bitcoin.  Someone was nice enough to show me code for it in Javascript, but I'm not sure if that person wants it distributed or not, so I'll let them pop in to provide the link if they want to.
Jump to: