I need to save public keys in many contracts. Despite that this choice costs, I store them as bytes (I know that the best way is to split the key and store it to different bytes32 constants, but that is not the case right now).

I use web3 and EthCrypto.

So, I create the key pair and compress the public key.

keypair = EthCrypto.createIdentity()
compressedPublicKey = EthCrypto.publicKey.compress(keyPair.publicKey) 

The output of the above is this:

Public Key: 766cbaa7e623704f93852e162cc0e3fc9cae211819218e00b5e486376724bd7dbd3c64eb7465ab754cb0ecfbbe7ae65d4ecc8df91b74b65948d1254a0eb389c3

Compressed Public Key: 03766cbaa7e623704f93852e162cc0e3fc9cae211819218e00b5e486376724bd7d

Private Key: ...

If I just concatenate '0x' to the beginning of the public key, I am able to store it in the contract. Without concatenating '0x', it gives me the error that "Public Key is not bytes".

Now, there is the other option. I can use web3's toHex:


This outputs: 0x303339633665306635653264633537626231383332623333613537316230383830343563343031323835356136313935313630333663663839356565343737373136

And, of course, I can save this as well to the contract.

But, there's some questioning. Concatenating '0x' and storing it to the smart contract, is not proper (but it works).

Converting to hex and then passing it to the smart contract, I think that is the proper way, but it "requires" 67 more digits to be saved.

Compressed Public Key (68 digits with '0x'): 0x039c6e0f5e2dc57bb1832b33a571b088045c4012855a619516036cf895ee477716

Conversion to hex (135 digits): 0x303339633665306635653264633537626231383332623333613537316230383830343563343031323835356136313935313630333663663839356565343737373136

What is your opinion on this?

  • "Concatenating '0x' and storing it to the smart contract, is not proper" <-- Why? web3.js generally requires a leading '0x' on hexadecimal data, so adding it seems "proper" to me. – user19510 Oct 6 '19 at 23:16
  • What I want to say is that "I do not find it proper to just take any arbitrary string and just add 0x in front of it, so it can be seen as "bytes" by the EVM". I do not really see it as the "proper way". Of course I may be extremely wrong, but that is the reason why I raised the above question. – GeorgePal Oct 6 '19 at 23:21
  • It's not an arbitrary string. It's hexadecimal that doesn't have a prefix. – user19510 Oct 6 '19 at 23:31
  • Thank you very much for your answers smarx. I just wasn't feeling that concatenating 0x was "okay". – GeorgePal Oct 6 '19 at 23:54
  • An uncompressed public key for Ethereum (or any other blockchain that uses the curve secp256k1) uses 64 bytes. You need to store the x and y coordinates which are both 256 bits.
  • A compressed public key is 33 bytes. A parity byte that is and 32 bytes for the x component.

The several error you mention are due to the lack of a native type in javascript that can store bytes or bytes32

For example in this output

This outputs: 0x303339633665306635653264633537626231383332623333613537316230383830343563343031323835356136313935313630333663663839356565343737373136

You are storing the hexadecimal representation and uses double storage space.

If you have an hexadecimal string and want to send bytes you have to use web3.utils.hexToBytes

const pubKey = "766cbaa7e623704f93852e162cc0e3fc9cae211819218e00b5e486376724bd7dbd3c64eb7465ab754cb0ecfbbe7ae65d4ecc8df91b74b65948d1254a0eb389c3"
const data = web3.utils.hexToBytes(pubKey)
  • Thank you for your answer, Ismael. – GeorgePal Oct 21 '19 at 19:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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