3

I've just discovered that with b59c839 geth is now pre-appending the string:

*\x19Ethereum Signed Message:\n<length of message>*

before signing the passed message. I've read here that to use ecrecover on Soldity side it must be pre-appended the same string on the contract. Do you have any working example on how to correctly manage this pre-appending on a Solidity contract?

Thank you

----- ----- ----- UPDATE

I'm trying to pre-append the signature locally in geth with something like this:

test = web3.sha3("hello")
eth.sign(eth.accounts[0], test)
hash_preamble = web3.sha3("\x19Ethereum Signed Message:\n" + test.length + test)

Then on the contract side I'm trying to test something as simple as this:

function test(bytes32 r, bytes32 s, uint8 v, bytes32 hash_preamble) constant returns (address) {
    address signer = ecrecover(hash_preamble, v, r, s);
    return signer;
}

The bytes32 values passed to the contract are in the form of "0x1234" while the uint8 is 27 or 28. The hash passed to the contract is the composed hash with the preamble, length of my message (which is an hash) and my message.

Unfortunately I'm not able to get the same address as the signing one. Can you see some mistakes in my code?

3
  • 1
    Do you really need to do the prepending on the solidity side? It will be quite complicated and expensive. It would be far easier to just pass in the message with the prefix already attached. Apr 3, 2017 at 21:01
  • Yeah right, it can actually be done like that! Thanks you! What's the exact string to append and how if the value to be signed is the digest hashed_messages = web3.Sha3(first message, second message) ? :)
    – gatb27
    Apr 4, 2017 at 5:00
  • Did you ever figure this out? I'm stumped on this myself as well.
    – hextet
    Feb 8, 2018 at 0:11

1 Answer 1

1
+100

Do you have any working example on how to correctly manage this pre-appending on a Solidity contract?

You can check out the Etherdelta smart contract https://github.com/etherdelta/smart_contract/blob/master/etherdelta.sol

function availableVolume(address tokenGet, uint amountGet, address tokenGive, uint amountGive, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s) constant returns(uint) {
    bytes32 hash = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce);
    if (!(
      (orders[user][hash] || ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash),v,r,s) == user) &&
      block.number <= expires
    )) return 0;
    uint available1 = safeSub(amountGet, orderFills[user][hash]);
    uint available2 = safeMul(tokens[tokenGive][user], amountGet) / amountGive;
    if (available1<available2) return available1;
    return available2;
  }

Here the signed message is hash with size 32. Note that they use sha256 to create the message which costs more gas than sha3, I suspect they did it for compatibility with the client side.

ecrecover is described in Solidity docs with example usage:

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address): recover the address associated with the public key from elliptic curve signature or return zero on error (example usage)

You can see more examples in different languages on Github: https://github.com/search?l=&q=%5Cx19Ethereum+Signed+Message&ref=advsearch&type=Code&utf8=%E2%9C%93


From your bounty note:

provide a way to recover the original message from the signed message hash such that the integrity of h can be verified

It's not possible to recover the original message from the hash. All the ecrecover can do is to "recover the address associated with the public key from elliptic curve signature or return zero on error". It basically tells you whether the signature belongs to the given address.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.