This is a just a short article about a question that comes up quite frequently, from people using ethers.js.
How do I verify a signed message in Solidity.
When a message is signed in Ethereum (e.g. using eth_signMessage), it is first prefixed with the header "x19Ethereum Signed Message:n" followed by the length of the message and then finally the message itself. First it is useful to understand why each of these things is done.
All transactions in Ethereum are encoded using Recursive Length Prefix (RLP) encoding. Without getting too deep into the details of RLP, the x19 at the beginning is an intentionally invalid byte for a transaction to begin with. This prevents an application from tricking you into signing what appears to be a message, but is actually a transaction in disguise.
The "Ethereum Signed Message:n" make the contents of the message human readable. Notice that this prefix is 25 characters long, which in hex is 0x19. This allows the string to be properly read as a length-prefixed string, which is bit of legacy from Bitcoin signed messages.
The length included in the prefix is also largely legacy from Bitcoin, but does possibly provide some additional protection in the event of the hashing algorithm is broken, and can also assist in debugging.
Once the header is prepended to the message, the message is hashed using keccak256 and that digest is signed using a secp256k1 private key.
So, now we can create a function which can take a message and a signature, construct the header, compute the hash of the full payload and recover the address. (do not worry if it looks scary, you may skip it and come back to it later)
This code may look a bit complex, and uses inline EVM assembly in a few places. This should generally be frowned upon, but (as far as I know) there is no pure-Solidity way to do this efficiently.
"Code that drops down to inline assembly without any clear reason why will look immediately suspicious." ~Nick Johnson
Once we have our contract deployed, it is quite simple to use from JavaScript.
This is a fairly simple example of this technique, mostly as a toy. But you could use this for example to have a central authority distribute signed messages, which could be redeemed as labels against an ENS registrar for custom sub-names, or to unlock specific named tokens in an ERC-721 contract.
Thanks for reading! Any feedback or suggestions are welcome. Please feel free to follow me on Twitter and chime in on any of my other random thoughts.