Are there any libraries to get a public key from a signature in a smart contract? The ecrecover method returns an address, not a public key, and to do computations that need to derive a public key from a signature, where the public key is not known and not passed into the contract by other means, while the signature is known, it would be good to have a library that gets the public key from a signature.

Partial libraries would also be helpful here.

3 Answers 3


There's a library https://github.com/jbaylina/ecsol that implement some operations over elliptic curves in solidity.

I didn't try but it appears to have enough to implement public key recovery. But I'm not sure if the gas limit will allow such operation.

In any case the problem seems interesting, but it is equivalent to obtaining a preimage from keccak.


There isn't a built in way to do this in Solidity and I don't believe there exists a library to do it either. Out of curiosity, what is your reason for needing to get the public key instead of the address?

  • a third version of this bounty, etherscan.io/address/… where a symmetric key is passed into the contract instead of a public key, and the public key (used to solve another cipher) is derived from a signature of an account identifier
    – schnorr
    Feb 28, 2018 at 14:02
  • a signature scheme using one-time keys, calling it "teikhos", from the Greek for "fortification", it hides the asymmetric cryptography behind an unbreakable symmetric cipher (only breakable by brute forcing all possible combinations)
    – schnorr
    Feb 28, 2018 at 14:34

a new library is available to recover public key from ECDSA signed message https://github.com/0xcyphered/secp256k1-solidity


//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "@0xcyphered/secp256k1-solidity/contracts/SECP256K1.sol";
contract Example {
    function recoverPersonalSignPublicKey(
        bytes32 message,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public pure returns (bytes memory) {
        string memory header = '\x19Ethereum Signed Message:\n32';
        bytes32 _message = keccak256(abi.encodePacked(header, message));
        (uint256 x, uint256 y) = SECP256K1.recover(uint256(_message), v - 27, uint256(r), uint256(s));
        return abi.encodePacked(x, y);

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.