Before sending someone a large sum of money on the internet via a irreversible transaction you better make sure you are sending the funds to the right address.
There are a few ways to go about doing this and depending on who you are sending funds to, how accessible their keys are and what the capabilities and behavior of their wallet software is you may need to choose different solutions.
Have the recipient sign a message using their wallet key
If we assume the recipient has the key associated with the target wallet online (aka not in cold storage) and that that the software they use for that wallet supports message signing with wallet keys this can be a viable option.
Unfortunately there is not currently a standard for the format of signatures using bitcoin keys with that said thankfully there appear to only be two common formats in-use today.
The first format being in-essence no formatting; client simply present you the three values you will need to verify a message and you do with them as you see fit, for example:
- Wallet Address: 18neTpQ5MWnXg4n4rpoK5TgxXjEVcg2MYR
- Message: [email protected] – my voice is my passphrase authenticate me
- Signature: G0d6BnQem1gT4nd9esfsEyn1k/GfYAxDkNJmkNvmz8wCOI2Ncw9DvIcyP7OJcEvWbUHQNIBFK3V8wYdnhEFhYHI=
This format leaves a little be desired. For one you have to pass these values independently and then you also have issues around introduction of white-space which can invalidate signatures.
There is another increasingly common format that leverages ASCII armor and some codified rules to address these issues. This style of formatting originated in a project called Privacy Enhanced Mail (PEM), it was one of the first proposals for how to sign and encrypt mail on the Internet and was later adopted by PGP (RFC https://tools.ietf.org/html/rfc4880).
But don’t confuse this format with these other formats they follow some different rules when it comes to encoding.
What this means is that depending on the implementation of the wallet software the recipient uses you may not be able to validate the signature they produce without some manipulation of the text.
As for what this format looks like, its fairly straight forward:
-----BEGIN BITCOIN SIGNED MESSAGE-----
[email protected] - my voice is my passphrase authenticate me
-----BEGIN SIGNATURE-----
18neTpQ5MWnXg4n4rpoK5TgxXjEVcg2MYR
G0d6BnQem1gT4nd9esfsEyn1k/GfYAxDkNJmkNvmz8wCOI2Ncw9DvIcyP7OJcEvWbUHQNIBFK3V8wYdnhEFhYHI=
-----END BITCOIN SIGNED MESSAGE-----
The core differences with this format (as specified in this thread and the PGP rule-set are:
- No “empty-line” delineator between the headers and message;
- Beginning and end whitespace / newlines ignored excluded when verifying the signature;
- Length of rows are not limited to 80 characters;
- No concept of header values (like versions).
The reason I point this out is that since there really isn’t a standard for this signature format and the format diverges from what has been used historically you may still encounter interoperability issues when validating messages between clients that have not been tested with each other.
With that said when you have managed to successfully verify a message like this you know that whoever produced the message owns the key associated with the wallet associated with it.
To address the risk of a message substitution the sender would need to communicate a challenge out of band to the recipient. For example you may notice in my message above I included “my voice is my passphrase authenticate me”. My inclusion of this message (presumably exchanged out of band) helps assure the sender that it was me who signed the message.
To make this process a little easier Andrew Yanovsky and I put together a simple site that can validate both formats, it’s all client side so you can save the files locally and run without the dependency on the website if you like.
NOTE: It is worth noting that this workflow does not accommodate P2SH and multi-signature wallets both of which will see increased use as time progresses.
Do a micro-transaction
The simplest way to verify an address is to simply send a small amount of money to that address and verify out of band with the recipient that they confirm seeing it in their balance. This is what most online payment services but again this requires the keys to be accessible to the sender they can perform the transaction.
There are a few things to keep in mind if you go this way, specifically:
- Don’t send less that .0001 BTC because the transaction may get “stuck” and not be processed.
- Be sure to include some transaction fee even if tiny so it doesn’t stay unprocessed for too long.
Once the transaction has been sent and you use a tool like blockchain.info to see that the transaction has been confirmed you can verify out of band with the address owner again that they see the funds as well.
This approach unlike the wallet signing key approach can also work with multi-signature and P2SH wallets which will be in use increasingly as clients better support these techniques.
Verify the wallet address two times via out of band channel
If they keys are offline (in cold storage) the only viable option is to carefully validate each character of the address via an out of bound secure channel, I would personally not rely on this approach for large sums but if both parties are careful it can work. By doing the check twice you reduce the chance of human error but mistakes can happen and in this case they can not be undone so use this approach with caution.
None of these solutions are perfect and moving forward I expect we will see services like OneName.io and exchanges with authenticated account profiles will become the way that we solve these problems but in the mean time you can reasonably manage the transaction workflow via these two mechanism.