2

I want to store a Public Key of an Ethereum address in a contract. What is the advisable primitive datatype to store a Public Key?

  1. Should I store as String or Bytes32?
  2. Is it secure to store a Public Key in a contract? I know it is PUBLIC key, but still...I want to know any pitfalls that I should be mindful of.

Thanks!

etherfaces
  • 1,153
  • 1
  • 9
  • 11

2 Answers2

5

Always store keys as bytes since strings in some languages are known to be terminated by null value bytes. You can use a bytes32 attribute to store the key and a getter method to retrieve it from the deployed (instantiated) contract:

contract PubKey {
         bytes32 pubKey;

         function PubKey(bytes32 initKey) {
             pubKey = initKey;
         }

         function getPubKey() constant returns (bytes32) {

            return pubKey;

         }
    }

Edit:

The public key is 64 bytes long excluding its prefix:

contract PubKey {
    uint8[] pubKeyBytes;

    function PubKey(uint8[] initKey) {
       for(uint i = 0; i < initKey.length; i++) {
          pubKeyBytes.push(initKey[i]);
       }
}

function getPubKeyByte(uint i) constant returns (uint) {
    return pubKeyBytes[i];
}

This is expensive since each retrieval of the public key must be called 64 times. using two 32 byte chunks is cheaper (but uglier):

contract PubKey {
     bytes32 pubKeyHalf1, pubKeyHalf2;

     function PubKey(bytes32 initKeyHalf1, bytes32 initKeyHalf2) {
         pubKeyHalf1 = initKeyHalf1;
         pubKeyHalf2 = initKeyHalf2;
     }

     function getPubKeyHalf1() constant returns (bytes32) {
        return pubKeyHalf1;
     }

     function getPubKeyHalf2() constant returns (bytes32) {
        return pubKeyHalf2;
     }
}
Sebi
  • 5,294
  • 6
  • 27
  • 52
  • Thanks for your response. I also have a follow up question. How would the accessor function look like? Let's say...function getPubKey() returns (bytes32), should we reconstruct into bytes32 before returning back the PubKey? – etherfaces Aug 02 '16 at 13:53
  • @etherfaces ask additional questions as new threads. Thats the recommended way, – niksmac Aug 02 '16 at 15:49
  • I've updated the answer. – Sebi Aug 02 '16 at 15:55
  • In the getPubKey function, the line: (byte) (key[i]) = pubKey[i] gives error. Looks like the syntax is invalid. I'll post a new question on how to convert byte array to bytes32 in solidity. – etherfaces Aug 03 '16 at 09:29
  • When you call the constructor of the contract, pass the argument as a string of the form "0x1234...". – Sebi Aug 03 '16 at 15:17
  • Surely I'm missing something right in front of me, but isn't 32 bytes 1 byte short? Don't you need to store the 32 byte x-coordinate and also the sign? – jMyles Jun 04 '18 at 06:08
  • This answer is out of date. "The private key must be 32 bytes and not begin with 0x00 and the public one must be uncompressed and 64 bytes long or 65 with the constant 0x04 prefix. More on that in the next section." https://kobl.one/blog/create-full-ethereum-keypair-and-address/ . PubKey is 64 bytes long. – Sebi Jun 04 '18 at 10:29
  • This might be a stupid question but what's wrong with the address datatype? – jasper Jun 04 '18 at 11:10
  • 1
    But you can still store public key compressed, no? Is there really no better way to do this than two bytes32's? @jasper: Addresses are only 20 bytes. Not enough room. – jMyles Jun 04 '18 at 20:20
0

You can also store the public key in bytes variable, but that will consume more gas. In my simple test, storing a public key in two bytes32 variables uses ~ 67,000 gas, and storing it in one bytes variable uses ~85,000 gas

Andrey
  • 1,147
  • 1
  • 12
  • 19