1

I want to create a smart contract that contains the public key of a party (the key is generated outside the blockchain) and contains a function to verify signed data. How can we implement this function in solidity? I took a look at ecrecover but I think it needs an ethereum address instead of a public key.

[UPDATE]: the public key isn't related to any Ethereum address.

3 Answers 3

1

As long as the public key is a point on the secp256k1 elliptic curve, their ECDSA signatures can be verified via Ethereum's ecrecover precompile.

Note that an Ethereum address is just the rightmost 160 bit of the keccak256 hash of the concatenation of the hex-encoded x and y coordinates of the public key, see Appendix F: Signing Transactions" §134 in the Yellow Paper.

Example function to compute the address of a public key:

function toAddress(uint x, uint y) public view returns (address) {
    return address(uint160(uint(keccak256(abi.encode(x, y)))));
}
0

When you need to verify public key, just use

address addrfrompub = address(bytes20(keccak256(pubkeyPart1, pubkeyPart2) << 96)));

address addrrecovered = ecrecover(hash, v, r, s);

Then compare them:

require(addrfrompub == addrrecovered);

Hope it helps.

1
  • thank u for your answer. but what I need is to verify a signature that it is generated outside the ethereum context using a private key. in other words I want to create a smart contract that will be able to verify old signatures made outside the blockchain, and the public key isn't related to any ethereum address
    – maroodb
    Apr 12, 2018 at 15:48
0

you can use the ecrecover function in Solidity. The ecrecover function will return Ethereum address associated with the public key that signed the data, but you can then compare this address with the one derived from the public key you provided.

smart contract code that contains a public key and verify function:


contract SignatureVerifier {
    bytes32 public publicKey;

    constructor(bytes32 _publicKey) {
        publicKey = _publicKey;
    }

    function verify(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public view returns (bool) {
        address recoveredAddress = ecrecover(hash, v, r, s);

        address publicKeyAddress = address(uint160(uint256(publicKey)));
 key
        return recoveredAddress == publicKeyAddress;
    }
}

The verify function takes the hash of the message that was signed, and the signature components v, r, and s. The ecrecover function is used to recover the Ethereum address associated with the public key that was used to sign the data. Then, the function compares this recovered address with the one derived from the provided public key.

Please note that this example assumes that the provided public key is indeed related to an Ethereum address.

Offchain code to sign the data:

async function signData() {
  const accounts = await web3.eth.getAccounts();
  const account = accounts[0];

  const data = 'your data';

  // Hash the data
  const dataHash = web3.utils.keccak256(data);

  web3.eth.personal.sign(dataHash, account, (error, signature) => {
    if (error) {
      console.error('Error signing data:', error);
    } else {
      console.log('Signature:', signature);

      const r = signature.slice(0, 66);
      const s = '0x' + signature.slice(66, 130);
      const v = '0x' + signature.slice(130, 132);
      const v_decimal = web3.utils.toDecimal(v);

      console.log('v:', v_decimal);
      console.log('r:', r);
      console.log('s:', s);
    }
  });
}

If you are looking for typed data signature verification, you can refer to my this answer Verifying signed typed message hash on-chain.

Please accept and upvote if it helps

1
  • The formula to calculate the address from the public key is wrong publicKeyAddress = address(uint160(uint256(publicKey))). See the correct formula in this answer ethereum.stackexchange.com/a/29480.
    – Ismael
    Apr 18, 2023 at 0:22

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.