DEV Community

Cover image for Verifying Signature : Using Solidity
Neeraj Choubisa
Neeraj Choubisa

Posted on

Verifying Signature : Using Solidity

How to Sign and Verify

Signing
1. Create message to sign
2. Hash the message
3. Sign the hash (off chain, keep your private key secret)
Enter fullscreen mode Exit fullscreen mode

1. Create message to sign and Hash the message
Call getMessageHash pass this arguments :-

getMessageHash(
        0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C,
        123,
        "coffee and donuts",
        1
    )
Enter fullscreen mode Exit fullscreen mode
function getMessageHash(
        address _to,
        uint _amount,
        string memory _message,
        uint _nonce
    ) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_to, _amount, _message, _nonce));
    }

Enter fullscreen mode Exit fullscreen mode

Get the hash of this transaction message
hash = "0xcf36ac4f97dc10d91fc2cbb20d718e94a8cbfe0f82eaedc6a4aa38946fb797cd"
3. Sign the hash (off chain, keep your private key secret)
using browser
account = "copy paste account of signer here"
ethereum.request({ method: "personal_sign", params: [account, hash]}).then(console.log)

using web3
web3.personal.sign(hash, web3.eth.defaultAccount, console.log)

Signature will be different for different accounts
0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b

Now get the original ethereum Hashed Message :-

function getEthSignedMessageHash(
        bytes32 _messageHash
    ) public pure returns (bytes32) {
        /*
        Signature is produced by signing a keccak256 hash with the following format:
        "\x19Ethereum Signed Message\n" + len(msg) + msg
        */
        return
            keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)
            );
    }
Enter fullscreen mode Exit fullscreen mode

Verify
1. Recreate hash from the original message
2. Recover signer from signature and hash
3. Compare recovered signer to claimed signer

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract VerifySig {
    function getMessageHash(string memory _msg) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_msg));
    }

    function getEthHashedMessage(bytes32 _msg)
        public
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", _msg)
            );
    }

    function verify(
        address _signer,
        string memory _message,
        bytes memory signature
    ) public pure returns (bool success) {
        bytes32  _hashMessage = getMessageHash(_message);
        bytes32 _ethHashMessage = getEthHashedMessage(_hashMessage);

        return recover(_ethHashMessage, signature) == _signer;
    }

    function recover(bytes32 _ethHashMessage , bytes memory _sig) public pure returns(address){
        (bytes32 r , bytes32 s , uint8 v) = _split(_sig);
        return ecrecover(_ethHashMessage, v, r, s);
    }

    function _split(bytes memory _sig) private pure returns(bytes32 r ,bytes32 s , uint8 v) {
        require(_sig.length==65,"Signature is not valid");
        assembly{
            r :=mload(add(_sig,32))
            s := mload(add(_sig,64))
            v :=byte(0,mload(add(_sig,96)))
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Happy Coding

Top comments (0)