Перейти к содержимому
ecdsa.com

Ethereum Signature Verifier — проверка подписей Ethereum

Вставьте сообщение, подпись и, если знаете, адрес, который должен был её создать. Инструмент заново собирает те самые байты, которые хешировались, восстанавливает подписанта через ecrecover, проверяет v и s и объясняет несовпадение: hex, прочитанный как текст, лишний перенос строки, personal_sign вместо eth_sign. Смарт-кошельки можно проверить в их сети.

Сообщения и подписи проверяются в этом браузере. Только когда вы нажимаете «Проверить в блокчейне», адрес кошелька, 32-байтный дайджест и подпись отправляются на публичный RPC-узел выбранной сети (он указан рядом с кнопкой). Seed-фразы и закрытые ключи отклоняются и никогда не обрабатываются.

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 a 0x-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.