Ethereum Signature Verifier

QR Code of Shareable Link

✅ How Signature Verification Works in Ethereum

When someone signs a message with MetaMask, they produce a cryptographic signature that proves ownership of their Ethereum address — without exposing their private key.

🔍 Step-by-Step Verification:
  1. Hash the message using Ethereum's format:
    keccak256("\x19Ethereum Signed Message:\n" + len + message)
  2. Split the signature into r, s, and v
  3. Use v to recover the public key from the signature and message hash
  4. Convert the public key into an Ethereum address:
    keccak256(pubKey)[-20:]
  5. Compare the recovered address to the one claimed
✅ If they match → the signature is valid!

This is possible because of the elliptic curve digital signature algorithm (ECDSA) and the fact that Ethereum signatures include a recovery ID (v).

🧪 In Code (ethers.js):

const recovered = ethers.utils.verifyMessage(message, signature);
if (recovered.toLowerCase() === expectedAddress.toLowerCase()) {
  console.log("✅ Valid signature");
}
  

🔐 What is keccak256 and Why Ethereum Uses It

Keccak-256 is the hashing function used in Ethereum to securely compress data into a fixed-size fingerprint. It's used for:

🧠 Why use it?
📐 How it works (simplified):
  1. Absorb the input into a fixed-size internal state
  2. Permute (mix) the state with bitwise operations
  3. Squeeze out a 256-bit output
⚠️ Keccak-256 ≠ SHA-3

Although both come from the same family, they differ in internal padding and are not interchangeable.

📦 In Code (ethers.js):

import { keccak256, toUtf8Bytes } from "ethers";

const message = "Hello Ethereum";
const hash = keccak256(toUtf8Bytes(message));

console.log("Message hash:", hash);
  

🔍 How Signature Verification Recovers the Address

When you verify a signature, you're not just checking a hash — you're actually reconstructing the public key that signed a message, and converting it into the Ethereum address.

✅ Inputs:
📐 Verification Steps:
  1. Hash the message:
    H = keccak256("\x19Ethereum Signed Message:\n" + len + M)
  2. Recover public key from the signature:
    publicKey = ecrecover(H, r, s, v)
  3. Convert to Ethereum address:
    A_recovered = keccak256(publicKey)[-20:]
  4. Compare to claimed address:
    A_recovered === A ? ✅ valid : ❌ invalid
⚠️ Important:

The signature is never hashed itself. The signature is used to recover the public key, which proves ownership of the address.

🧪 Code Example (ethers.js):

const recovered = ethers.utils.verifyMessage(message, signature);
if (recovered.toLowerCase() === claimedAddress.toLowerCase()) {
  console.log("✅ Valid signature");
}