Verify Signatures with Solidity – How to Sign with Web3 and Verify in Solidity

ecrecoversignaturesolidityweb3js

I have been trying, debugging, and crying, for a few days now. I simply for the life of me cannot figure out how to verify a signature that I've created with web3, in Solidity. I am sure I am just missing something very fundamental here, but I cannot figure out what it is.

I am struggling with a few different problems. All guides that show how I can verify in Solidity have a check like: require(sig.length == 65), but the signature I get from web3 is 132 chars long, so it already fails there.

JS code I generate signature with:

var hash = "0x" + ethereumjs.soliditySHA3(
    ["uint256"],
    [1000000]
).toString("hex");

this.web3.eth.personal.sign(hash, "0x8809465617E09405a1af06C2d93C2bcE0Ce5Ac80").then(console.log);

>>0x564f8b7ca4a729a34aedf3b065e20b5eaa129fd663243697025a428f27db086e6a7d6dc429c95a44143117a9ea02cd452bce4242b1adb2742b02a4a44e6d389b1c

Solidity code I use to verify:

function prefixed(bytes32 hash) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}

function checkIt () public {
    bytes memory signature = "0x564f8b7ca4a729a34aedf3b065e20b5eaa129fd663243697025a428f27db086e6a7d6dc429c95a44143117a9ea02cd452bce4242b1adb2742b02a4a44e6d389b1c";
    
    //require(signature.length == 65, "invalid signature length");
    
    bytes32 r;
    bytes32 s;
    uint8 v;
    
    assembly {
        r := mload(add(signature, 32))
        s := mload(add(signature, 64))
        v := byte(0, mload(add(signature, 96)))
    }
    
    uint256 message = 1000000;
    address signerAddress = 0x8809465617E09405a1af06C2d93C2bcE0Ce5Ac80;
    
    Assert.equal(ecrecover(prefixed(keccak256(abi.encodePacked(message))), v, r, s), signerAddress, "Not equal!");
}

Result of test:
https://imgur.com/a/qpO6Yaq

As mentioned in the beginning, I know that I am just missing something very basic here, but wanted to share what I've tried anyway. I hope someone can point me in the right direction!

Best Answer

The problem is that you are passing the signature as a string and you need to pass it as a byte array

function checkIt () public {

    bytes memory signature = hex"564f8b7ca4a729a34aedf3b065e20b5eaa129fd663243697025a428f27db086e6a7d6dc429c95a44143117a9ea02cd452bce4242b1adb2742b02a4a44e6d389b1c";

    require(signature.length == 65, "invalid signature length");

The require statement is to validate the signature has the appropriate length.

Related Topic