Solidity ecrecover – Using Geth and web3.eth.sign

cryptographyecrecovergo-ethereumsolidityweb3js

I have tried to use ecrecover() to verify the signature of a message.

I have looked at lots of references here and elsewhere, like:

and others.

But I still cannot get ecrecover() to return the signing address. So I am hoping that someone can point out some stupid mistake I am making.

Here is my code:

pragma solidity ^0.4.0;

contract test {

  function test() {
  }

  function verify(bytes32 _message, uint8 _v, bytes32 _r, bytes32 _s) constant returns (address) {
   address signer = ecrecover(_message, _v, _r, _s);
   return signer;
  }
}

Then in geth, I do:

> var msg = web3.sha3("hello")
"0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8"

> eth.accounts[0] -->
"0x7156526fbd7a3c72969b54f64e42c10fbb768c8a"

> var sig = eth.sign(eth.accounts[0], msg)
"0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac80388256084f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada1c"

> var r = sig.substr(0,66)
"0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608"

> var s = "0x" + sig.substr(66,64)
"0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada"

> var v = 28
28

> test.verify(msg,v,r,s)
"0x33692ee5cbf7ecdb8ca43ec9e815c47f3db8cd11"

…which of course, is NOT eth.accounts[0]

I am totally stumped. Is there anyone who can see what I am doing wrong?

Best Answer

I was stuck on this issue as well for a very long time.

So the solution is: Add this prefix string to your Solidity smart contract.

function verify(bytes32 hash, uint8 v, bytes32 r, bytes32 s) constant returns(bool) {

    bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    bytes32 prefixedHash = keccak256(prefix, hash);
    return ecrecover(prefixedHash, v, r, s) == (Your Address);
}
Related Topic