When interacting with web3 apps, you may have seen a signature request in your wallet that looks like this. This article explains what this signature is and how it's used as authentication.
A cryptographic signature proves that the signer has the private key to a public address. A public address on the Ethereum blockchain is a 42-character hexadecimal address derived from the public key controlling the account with 0x appended in front. e.g., 0x88c78f158cac85f17ecfc063259543c5dc345ef3. Anyone can send money to an account using the public address, or look up the account activity and assets. However, to control the assets in the account, you need to have the private key.
Ethereum wallets, such as MetaMask and Coinbase Wallet, store your public key and private key for you, and protect against apps directly accessing the private key. Instead, apps rely on a cryptographic signature that proves ownership of the address through the Elliptic Curve Digital Signature Algorithm, which allows any external party to verify the signature without knowing the private key.
In web3 apps, a user's Ethereum address is increasingly replacing a username or email to identify a user. And instead of a password to authenticate that a user controls the digital identity, a signature can be used.
Leveraging an existing Ethereum account is a lightweight way to onboard web3 users. It's faster than traditional account creation flows, and doesn't require the user to create and store yet another password. It also allows the user more anonymity, since they don't have to reveal private details like their email.
Unlike blockchain transactions, signature generation and verification can be done off-chain, and therefore requires no gas fees. And while it proves a user's control of an Ethereum address, future blockchain transactions will still require explicit approval through a separate wallet request.
Some apps, such as Snapshot and OpenSea use a hybrid of blockchain data and data from a private database. These apps will use a traditional database to store off-chain actions, such as voting (on Snapshot proposals) or favoriting NFTs (OpenSea stores users' favorited NFTs). Onboarding onto these apps is easy, because a user just has to allow it to connect to their Ethereum wallet. But to store the outcome of these actions, or any off-chain details about the user (such as profile name and photo), these apps must authenticate the user's digital identity.
For example, to change an OpenSea profile's details, the user must authenticate to prove they control this address.
For apps using signature authentication, it's important not to allow the same signature to be used twice. This is why the messages vary, and often include a nonce.
To sign or verify a signature right now, you can use Etherscan's Verified Signature tool.
To request a signature in your web3 app, you can use a library like web3.js on the frontend. The code snippet below shows how to generate a
signatureHash using a web3.js method, then an example of passing it to any signature verification API to your backend.
const signatureHash = await web3.eth.personal.sign(message, address)
someSignatureVerificationAPI(message, address, signatureHash)
As the Ethereum address has replaced the account username, the signature has replaced the password. Because a cryptographic signature proves the user controls the private key to the public address, it is a secure method of authentication. Apps can use this gas-less primitive of Ethereum to verify a user has control over the digital identity provided by the address, and provide authentication to do arbitrary, non-web3 actions.