I've seen many instances of verifying signed messages in which the hash to be verified gets passed as an argument. I need to first recreate the hash on-chain, before running ecrecover on it. However, when I keccak256 hash the same thing I hashed off-chain, I'm getting a non-match.

Here's my web3 code, where I create the hash off-chain:

let prepend = keccak256(ethers.utils.defaultAbiCoder.encode(
      [ 'string' ],
      [ "\x19Ethereum Signed Message:\n32" ]

    let message = ethers.utils.defaultAbiCoder.encode(
        'address', 'string', 'uint256'

        contracts.accessControls.address, 'Generate authorization code', this.state.spaceId

    let msg = keccak256(prepend, message);
    await accessControlContract.commitSignatureHash(indexOfUser, this.state.spaceId, msg);

    web3.eth.sign(msg, context.account, (err, res) => {
      } else{
        this.setState({userSecretCode: "register " + this.state.spaceId + context.account + res});

And here's my solidity code where I try to recreate the same hash on chain and then run ecrecover on the sending address:

    function commitSignatureHash(uint256 index, uint256 space, bytes32 hashToVerify) public {
        require(whitelistForSpace[space][index] == msg.sender);
        latestCommittedHashByAddressBySpace[space][msg.sender] = hashToVerify;
        timeStampByAddressBySpace[space][msg.sender] = now;

    function verifySignature(address userRegisteringSpace, uint256 space, uint8 v, bytes32 r, bytes32 s) public view returns (bool){
        bytes32 hashToVerify = keccak256(
                'Generate authorization code', 

        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, hashToVerify));

        //making sure it recreates a previously committed hash
        require (prefixedHash == latestCommittedHashByAddressBySpace[space][userRegisteringSpace]);

        return userRegisteringSpace == ecrecover(prefixedHash, v, r, s);

msg (created off-chain) doesn't seem to be matching prefixedHash (created on-chain)


It looks like off-chain you're doing something like this:

keccak256(keccak256(abiEncode("\x19Ethereum Signed Message:\n32")), keccak256(message))

when it should be:

keccak256("\x19Ethereum Signed Message:\n32", keccak256(message))

The prefix shouldn't be ABI encoded and shouldn't be hashed.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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