1

I have an address named 'verifier' set in a smart contract. A user has a message which is encrypted from verifier's private key. The user send this message in a transaction to contract.

How can we validate this message, that it is encrypted from verifier's private key.

Note: Privacy doesn't matter as the the original payload is a hash value.

1 Answer 1

1

I assume that by "validating", you mean verifying that the message has indeed been signed with the "verifier" address.

There are multiple ways to do this. The most commons are either solidity's ecrecover() or OpenZeppelin's ECDSA library.

Let's see how to do it with the vanilla ecrecover().

You'll need to know in the execution environment :

  • The address of the signer here is address verifier
  • The message that is being signed

For this answer, I'll use a common usage of such concept: whitelisted presale. I guess most StackExchange viewers will look for this case.

The owner of the presale signs a message containing the address of the whitelisted buyer. The buyer can then submit this "password" to get access to the presale. You can generalize it by adding more data in abi.encodePacked()

    function verify(bytes memory signature, address target) public view returns (bool) {
        uint8 v;
        bytes32 r;
        bytes32 s;

        (v, r, s) = splitSignature(signature);
        bytes32 senderHash = keccak256(abi.encodePacked(target));
        
        return (verifier == address(ecrecover(senderHash, v, r, s)));
    }

  // This will process the signature in a readable format for ecrecover()
  function splitSignature(bytes memory sig)
       internal
       pure
       returns (uint8, bytes32, bytes32)
   {
       require(sig.length == 65);
       
       bytes32 r;
       bytes32 s;
       uint8 v;

       assembly {
           // first 32 bytes, after the length prefix
           r := mload(add(sig, 32))
           // second 32 bytes
           s := mload(add(sig, 64))
           // final byte (first byte of the next 32 bytes)
           v := byte(0, mload(add(sig, 96)))
       }

       return (v, r, s);
   }

The tricky part is usually to generate a compatible signature. For this (simple) example, I used the ``eth-crypto``` node.js library. You may find different implementations, depending on the signing lib that you use ("Ethereum Signed Message" standard, for instance)

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.