2

Trying to follow this documentation on verifying a signature: https://goethereumbook.org/signature-verify/

Where I am a bit confused is this line:

publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)

How do you get publicKeyECDSA from a given public key such as:

0x99877b0ab19d67ec313842df746Ce7Cd99BAADfD

At the top of the documentation it reads you need "3 things to verify the signature: the signature, the hash of the original data, and the public key of the signer." However the publicKeyECDSA is not the public key as shown above. How can I get the provided public key into the publicKeyBytes?

There is an example a bit lower on the page that does this:

publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)

but you need the private key initially to get this. But if I am trying to verify a signature of some unknown address, I wont have their private key.

2

You only need the public key in bytes format which means you don't need the private key at all and don't need the key in ecdsa type either.

For example:

publicKeyBytes, err := hex.DecodeString("049a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05")

sigPublicKey, err := crypto.Ecrecover(hashBytes, signatureBytes)

matches := bytes.Equal(sigPublicKey, publicKeyBytes)

To derive the public address from the public key bytes, you'll need to take the last 20 bytes from the keccack256 hash of the public key:

var buf []byte
hash := sha3.NewKeccak256()
hash.Write(publicKeyBytes[1:]) // remove EC prefix 04
buf = hash.Sum(nil)
publicAddress := hexutil.Encode(buf[12:])
fmt.Println(publicAddress) // 96216849c49358b10257cb55b28ea603c874b05e

Put it in a function that returns an address type:

func PublicKeyBytesToAddress(publicKey []byte) common.Address {
    var buf []byte

    hash := sha3.NewKeccak256()
    hash.Write(publicKey[1:]) // remove EC prefix 04
    buf = hash.Sum(nil)
    address := buf[12:]

    return common.HexToAddress(hex.EncodeToString(address))
}

If you don't have a the user's public key then convert the signature public key to an address and compare them:

sigPubAddress := PublicKeyBytesToAddress(sigPublicKey)
userPubAddress := common.HexToAddress("0x96216849c49358B10257cb55b28eA603c874b05E")
matches := sigPubAddress.Hex() == userPubAddress.Hex()

Imports

github.com/ethereum/go-ethereum/common
github.com/ethereum/go-ethereum/common/hexutil
github.com/ethereum/go-ethereum/crypto/sha3
  • Thankyou for your answer. One thing I am confused on however. How do I get from a given public address to the public key bytes? If someone were not too crypto savvy and gave their public address such as: 0x99877b0ab19d67ec313842df746Ce7Cd99BAADfD How do I take that and get it to bytes format? – Chipe Jan 5 at 16:21
  • @Chipe convert convert the derived signature public key to an address and then compare the provided public address. See updated answer. – Miguel Mota Jan 7 at 3:28

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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