1

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!

1 Answer 1

1

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.

1
  • Makes sense! Thank you for that.
    – Severin
    Commented Nov 23, 2021 at 13:36

Your Answer

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

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