Signing messages in Ethereum
Authentication for web3 ?
If you’ve ever interacted with an Ethereum Dapp you’ve probably been asked to “sign” a message or piece of data to authenticate yourself (well your address). I am assuming that like me you want to develop for web3 and so in this post we will go over the basics of signing data, care to join ?
How does it work ( conceptually )
At the highest level signing a message is a way to verify that you own certain wallet address on the Ethereum Blockchain or rather are in control of your private keys.
There are 5 basic elements to signing a message:
- A Users Wallet address ( also known as account address)
- Private Keys ( These are only known or can be generated by the wallet owner usually behind a UI and password like with MetaMask’s wallet)
- Public Keys ( Can be derived from the account, but only when signing a message or transaction )
- A Message
So now let’s see how the elements work together, let’s say you have a Dapp or web3 site and want to verify that the user owns certain address ( use cases in a minute ), at this point all you know is the user’s account. So you provide a message and the user “signs” it ( usually by clicking a button from their wallet), behind the scenes the “signature” uses the message , the private key and the public key along with some maths.
To validate the signature you use some maths along with the message and you should get the public key which in turn gives you the address ( phew ! ), you might be thinking how on earth is this safe, and the answer is that cryptographically /mathematically you can’t get the validation from the message to be equal to the public key without the private key thus proving ownership.
⚠️ To further expand the relationship between account, private and public key:The public key is generated from the private key using the Elliptic Curve Digital Signature Algorithm, you can then get a public address for your account by taking the last 20 bytes of the Keccak-256 hash (an algorithm ) of the public key and adding 0x to the beginning, but more likely like we will see you can use an utility library or function that does this in the back.
So let’s go once more over the process ( graphically ) before getting into the details of how to implement it.
My take on coding tutorials is the more the merrier because sometimes things don’t “click” until you connect concepts from various sources or teaching styles, signatures and public key Cryptography on Ethereum are a complex topic so here’s a couple of alternative tutorials and explainers :Ethereum signing and validating
The Magic of digital signatures on ethereum
What’s the use case for signing data ?
While you can log into a Dapp by unlocking your wallet, signing a message in Ethereum is an affirmative consensual action, think of anything that needs your users permission but does not require directly interacting with Ethereum’s EVM or transacting with ETH, so no gas costs ( at least for simple messages ) and of course it can serve as a stricter validation that whoever is logged in with a wallet actually owns the wallet/address.
Some specific cases ( more will surely arise with time):
- Gas less transactions: If you want to initiate a transfer or operation on behalf of your users, ( you can’t touch users funds though, for that you’d need a regular transaction, but you could transfer ownership from an account you do own to the users ).
- Off chain account flow: If you have some off chain or site data you need to display just for a certain user you can identify by their wallet you could use a message.
- Authentication for DAOs and other actions : A variation of the first use case, you want your users to vote or contribute in some way to your site/Dapp/project.
How to implement it ?
There are a few ways to implement message signatures in Ethereum, I’ll be using Metamask as it is the de facto wallet to use these days and if you need an introduction well I wrote one the other day :
Intro to Metamask for Dapps
Start to develop for the reigning web3 wallet.
⚠️ Metamask provides a full fledged Test Dapp repo for you to play around: https://github.com/MetaMask/test-dapp This test Dapp uses node and webpack and comes with a ton of calls, I like my examples to be minimal, focused and portable, so I had to substitute node modules (bops for Buffer) and add an utility library (web3) which are included via CDN (not recommended for production). The idea is that you learn and experiment smol here before moving onto their examples and build.
Here’s the code:
This snippet should generate a small UI that serves as a debug screen and provides a way to sign a simple message off chain.
⚠️ Metamasks provides 6 different signing methods, I am using personal_sign as it is somehow easy to use and safe, but if you are doing more complex things you might need signTypedData_v3 or v4, check the docs for more:https://docs.metamask.io/guide/signing-data.html#a-brief-history