How can I verify a cryptographic signature that was produced by an Ethereum address key pair

If I have a cryptographic signature from an Ethereum address key pair, how can I verify that signature?

Solidity and Serpent have `ecrecover` for this purpose.

ecrecover(bytes32 data, uint8 v, bytes32 r, bytes32 s) returns (address)

The function arguments are:

`data` is what was signed. Since it is 32 bytes, that usually means that the initial data is hashed first to 32 bytes, before it was signed.

`v`, `r`, `s` is the signature. (`v` is the recovery id: a 1 byte value specifying the sign and finiteness of the curve point; this value is in the range of [27, 30], however the Ethereum protocol declares the upper two possibilities, representing infinite values, invalid)

Important note with the examples below, sha3 is Keccak-256.

Here is a snippet in Solidity:

``````contract Auth {
function verify(address p, bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant returns(bool) {
// Note: this only verifies that signer is correct.
// You'll also need to verify that the hash of the data
// is also correct.
return ecrecover(hash, v, r, s) == p;
}
}
``````

Here is an example in Serpent:

``````def test_ecrecover(h, v, r, s):
return(ecrecover(h, v, r, s))
``````

The corresponding test code in Python (requires `bitcoin` and `ethereum` packages):

``````import bitcoin as b
from ethereum import tester, utils

class TestECRecover(object):

CONTRACT = """
def test_ecrecover(h, v, r, s):
return(ecrecover(h, v, r, s))
"""

def setup_class(cls):
cls.s = tester.state()
cls.c = cls.s.abi_contract(cls.CONTRACT)
cls.snapshot = cls.s.snapshot()

def setup_method(self, method):
self.s.revert(self.snapshot)

def test_ecrecover(self):
priv = b.sha256('some big long brainwallet password')
pub = b.privtopub(priv)

msghash = b.sha256('the quick brown fox jumps over the lazy dog')
V, R, S = b.ecdsa_raw_sign(msghash, priv)
assert b.ecdsa_raw_verify(msghash, (V, R, S), pub)

result = self.c.test_ecrecover(utils.big_endian_to_int(msghash.decode('hex')), V, R, S)
``````

Under the hood, `ecrecover` uses the `ECDSARECOVER` precompiled contract located at address 1.

Note: Geth and web3.eth.sign will add a prefix to the `data` message before signing.

The sign method calculates an Ethereum specific signature with: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).

By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.

For this case, the second argument to `verify()` must be `keccak256("\x19Ethereum Signed Message:\n", len(message), message)` instead of `keccak256(message)`.

• While already a very thorough answer, can you add what ecrecover returns in case of a good or invalid signature?
– J-B
Commented Jan 28, 2016 at 3:32
• As I understand it, a good signature will return the address which did the signing. A bad signature will return a different address. There's no way to tell if a signature is valid or not without also knowing the address which was supposed to do the signing. Commented Mar 20, 2016 at 22:17
• From the solidity docs on ecrecover: "recover the address associated with the public key from elliptic curve signature or return zero on error" Commented Feb 21, 2017 at 22:00
• Thank you to the anonymous editor who added the important code comment: "You'll also need to verify that the hash of the data is also correct"
– eth
Commented Aug 10, 2017 at 6:45
• If the signature is wrong, you still get a valid address from this. So do you just have to make the signer include the address somewhere in the original message to check for correctness?
– sudo
Commented Jun 3, 2018 at 4:14