Verificador de assinaturas Ethereum (Ethereum Signature Verifier)
Cole a mensagem, a assinatura e, se você souber, o endereço que deveria ter assinado. O verificador reconstrói exatamente os bytes que entraram no hash, recupera o signatário com ecrecover, verifica v e s e explica uma divergência — hex lido como texto, uma quebra de linha sobrando, personal_sign versus eth_sign. Carteiras inteligentes podem ser verificadas na própria cadeia.
Mensagens e assinaturas são verificadas neste navegador. Só quando você clica em “Verificar on-chain” o endereço da carteira, o digest de 32 bytes e a assinatura são enviados a um nó RPC público da cadeia que você escolher (indicado ao lado do botão). Frases de recuperação e chaves privadas são recusadas, nunca processadas.
Three ways to sign, three different hashes
An Ethereum account signs a 32-byte digest with secp256k1 ECDSA. What matters is which digest. Wallets offer three methods, and a signature made with one never verifies as another:
- personal_sign (EIP-191, version
0x45) hashes"\x19Ethereum Signed Message:\n" + length + message. The prefix makes sure a signed message can never be replayed as a transaction. The length is the number of bytes, written in decimal — and wallets such as MetaMask read a0x-prefixed hex string as the bytes it spells, not as text. - eth_signTypedData_v4 (EIP-712) hashes
0x19 0x01 ‖ domainSeparator ‖ hashStruct(message). The domain binds the signature to an application, a chain and a contract. The EIP-712 inspector explains what such a message allows. - eth_sign signs a raw 32-byte hash with no prefix. The signer cannot see what the hash stands for — it may be a transaction — so wallets warn about it or disable it.
The verifier rebuilds exactly the bytes that went into the hash and shows them: the prefix, the message bytes and how they were read, or every EIP-712 step.
Recovering the signer
An Ethereum signature is r ‖ s ‖ v: the two ECDSA values and a recovery byte. From the digest, r, s and the parity in v, public-key recovery yields the one public key that could have produced the signature; its address is the last 20 bytes of the keccak-256 hash of that key. This is what the EVM's ecrecover does. A signature therefore always "recovers" to some address — a verdict needs the address you expected.
The verifier accepts every encoding in use: 65 bytes with v = 27/28, the raw parity 0/1 that hardware wallets return, an EIP-155 v that carries a chain id, the 64-byte compact form of EIP-2098, and {r, s, v} JSON. It flags a signature whose s lies in the upper half of the curve order: the pair (r, n − s) is equally valid, which makes such signatures malleable, and contracts that use OpenZeppelin's ECDSA.recover reject them. The canonical low-s twin is shown.
Why a signature does not match
Most "invalid signature" reports are not forgeries but mismatches between what was signed and what is being checked. When the recovered address differs from the expected one, the verifier tries the usual mix-ups and says which one reproduces the expected signer:
- the message was signed as text but is being read as hex bytes, or the other way round;
- whitespace changed on the way: a trailing newline lost or added, CRLF instead of LF, spaces trimmed;
- a hash was signed with personal_sign (its 32 bytes, or its 66-character hex string) instead of eth_sign, or the reverse;
- an EIP-712 digest was signed with personal_sign, or the struct hash was signed without the domain — signatures that contracts checking EIP-712 will reject.
Smart-contract wallets
Safe, Argent, Coinbase Smart Wallet and passkey accounts have no private key of their own, so ecrecover cannot verify them. ERC-1271 lets the wallet contract decide: the verifier calls its isValidSignature(hash, signature) and checks for the magic value 0x1626ba7e. A wallet that is not deployed yet signs with an ERC-6492 wrapper — the factory and the deployment call around the inner signature — and is checked by a validator contract that deploys it inside a single simulated eth_call, changing nothing on chain. An EIP-7702 account is an ordinary key with delegated code: its own key still signs, so both paths are tried.
These checks need the chain where the wallet lives. Pick it and press "Check on chain"; the answer names the method that decided — ERC-6492, ERC-1271 or ecrecover — and what the contract returned.
What stays in your browser
Hashing, recovery and the mix-up search run in this page. Seed phrases, extended private keys, WIF keys and anything labelled as a private key are refused before anything is computed: verifying a signature never needs one.
The on-chain check is the only request the page can make, and only when you press the button. It sends the wallet address, the 32-byte digest and the signature — all public once a signature exists — to a public RPC node of the chain you picked, named next to the button; if that node does not answer, another public node of the same chain is tried. Never the message itself.