02, 03 or 04? So What Are Compressed and Uncompressed Public Keys?

Elliptic Curve Cryptography (ECC) is King of the Hill just now. You will find it in the handshake your browser has with this Medium page…

Photo by Maria Ziegler on Unsplash

02, 03 or 04? So What Are Compressed and Uncompressed Public Keys?

Elliptic Curve Cryptography (ECC) is King of the Hill just now. You will find it in the handshake your browser has with this Medium page (with ECDH) and blockchain methods. One special little curve, in fact, has become a standardized method for public-key encryption, and that’s secp256k1. It was selected by Satoshi Nakamoto and has since created the foundation for encryption for both Bitcoin and Ethereum.

At the core of secp256k1 is the creation of a 256-bit private key (sk). This key should always be random. Next, we create a public key by first using a base point (G) on the curve. After this, we create our public key by adding the point G, sk times. This gives us nG, and which is the public key (pk). And, so, as pk is a point on the curve, and where each axis has 256-bit values. We thus end up with a 512-bit point. The public key — in its purest form — is thus 512 bits long. But, why do we need to store both the x and the y coordinate values?

Overall, with secp256k1, we define the points on the curve as:

y=𝑥³+7 (mod 2²⁵⁶−2³²−977)

As we can easily determine the y axis-value if we know the x-axis value, there is no need to store the y-axis value. But in this elliptic curve, there are two points which are always possible for every x coordinate value, so all we need to do, is to point to the correct one. For this one of these points is an even value and the other has an odd value.

In the following example, we see that the private key has 64 hex characters. This represents 256 bits. The public key has 128 hex characters, and thus has 512 bits [here]:

Private key: f91d8f3a49805fff9289769247e984b355939679f3080156fe295229e00f25af
Public key: 52972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab288742f4dc97d9edb6fd946babc002fdfb06f26caf117b9405ed79275763fdb1c

We can reduce our public key point by compressing it. With a compressed point, we get a 32 byte compressed value (64 hex characters), and then add a 02 or a 03 to represent when y is even (02) or odd (03). This can be seen when we compress our public key here [here]:

Private key: f91d8f3a49805fff9289769247e984b355939679f3080156fe295229e00f25af
Public key: 52972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab288742f4dc97d9edb6fd946babc002fdfb06f26caf117b9405ed79275763fdb1c
Compressed public key 0252972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab2

In this case, we can see that we have a 02 at the start of the compressed public key point, and followed by the x-coordinate. This means that our y-coordinate value is even. Now let’s look at another one [here]:

Private key: ac609e0cc9681f8cb63e968be20e0f19721751561944f5b4e52d54d5f27ec57b
Public key: 18ed2e1ec629e2d3dae7be1103d4f911c24e0c80e70038f5eb5548245c475f504c220d01e1ca419cb1ba4b3393b615e99dd20aa6bf071078f70fd949008e7411
Compressed public key 0318ed2e1ec629e2d3dae7be1103d4f911c24e0c80e70038f5eb5548245c475f50

We can see that we now have a 03 at the start, followed by the x-coordinate value from the point. But how do we get the 02 or 03? Well in the first case the y-axis co-ordinate ends with a hex value of ‘c’ (1100), and which is even. In this case, we append a 02. In the second case, the y-coordinate ends with a hex value of ‘1’ (0001), and is then odd. In this case, we add a 03. The compressed key is then:

02 (x-co-ordinate) // if y is even
03 (x-co-ordinate) // if y is odd

When we need to uncompress, we can easily compute the y-coordinate value again from the x-coordinate value, and examine whether y is odd or even. This will recover the uncompressed point. Typically an uncompressed point will start with a 04.

In Ethereum, we also identify a user with their Ethereum address. This is a 160-bit (40 hex characters) address, and is derived from a Keccak 256 bits hash of the uncompressed x and y coordinate values. A sample run of this is [here]:

Private key: f91d8f3a49805fff9289769247e984b355939679f3080156fe295229e00f25af
Public key: 52972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab288742f4dc97d9edb6fd946babc002fdfb06f26caf117b9405ed79275763fdb1c
Compressed public key 0252972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab2
Signer address 0x6eDBe1F6D48FbF1b053D6c9FA7997C710B84f55F

The code used in this example is here:

and a running demo is here:

https://asecuritysite.com/ethereum/js_ethereum2

Conclusions

So, the next time you see an Ethereum public key, have a look to see if it has a 02, a 03 or a 04, and hopefully you will spot how it is represented. Go Ethereum!