<p>The public key format that OpenSSL and Bitcoin use is described in <a href="http://www.secg.org/index.php?action=secg,docs_secg" rel="nofollow">SEP 1</a>, published by the Standards for Efficent Cryptography Group on page 10.</p>

<blockquote>
  <ol>
  <li>Convert the field element x<sub>P</sub> to an octet string X of length ceil([log<sub>2</sub> q]/8) octets using the conversion routine specified in Section
  2.3.5.  </li>
  <li>Derive from y<sub>P</sub> a single bit ȳ<sub>P</sub> as follows (this allows the y-coordinate to be represented compactly using a single bit):  </li>
  <li>If q = p is an odd prime, set ȳ<sub>P</sub> = y<sub>P</sub> mod 2.  </li>
  <li>If q = 2m, set ȳ<sub>P</sub> = 0 if x<sub>P</sub> = 0, otherwise compute z = z<sub>m-1</sub>x<sup>m-1</sup> + · · · + z<sub>1</sub>x + z<sub>0</sub> such that z = y<sub>P</sub>x<sub>P</sub> and set ȳ<sub>P</sub> = z<sub>0</sub>.  </li>
  <li>Assign the value 02<sub>16</sub> to the single octet Y if ȳ<sub>P</sub> = 0, or the value 03<sub>16</sub> if ȳ<sub>P</sub> = 1.</li>
  <li>Output M = Y || X.</li>
  </ol>
</blockquote>

<p>... and page 53 ...</p>

<blockquote>
  <ul>
  <li>If C is an octet string and the leftmost octet of C is 02<sub>16</sub> or 03<sub>16</sub>, parse the leftmost ceil([log<sub>2</sub> q]/8)+1 octets of C as an octet string R, the rightmost <em>maclen</em> octets of C as an octet string D, and the remaining octets of C as an octet string <em>EM</em>. </li>
  <li>If the leftmost octet of C is 04<sub>16</sub>, parse the leftmost 2 * ceil([log<sub>2</sub> q]/8) + 1 octets of C as an octet string R, the rightmost <em>maclen</em> octets of C as an octet string D, and the remaining octets of C as an octet string <em>EM</em>.</li>
  <li>If the leftmost octet of C is not 02<sub>16</sub>, 03<sub>16</sub>, or 04<sub>16</sub>, output “invalid” and stop.</li>
  </ul>
</blockquote>

<p>So, in plain English: </p>

<ul>
<li>It can be 0x04 too. That's is the 'uncompressed' key. If you generate a key today, it won't create one of these. However, if you have an old wallet, you might have some. They are equivalent in security to compressed keys.</li>
<li>Whether it's 0x02 or 0x03 depends on on the value of ȳ<sub>P</sub>. We can generate ȳ<sub>P</sub> instead of including the full y coordinate, which saves us a nice bit of space. That's what compressed keys are.</li>
</ul>

<p>I'm not sure what q is in this context, if somebody wants to tell me in comments, it'd be appreciated.</p>

CC BY-SA 3.0
2013-05-28T22:08:42.283Z
2013-05-28T22:13:47.353Z
2013-05-28T22:13:47.353Z
Nick ODell
<p>Parity determines if its 0x02 or 0x03</p>

<p>Node.JS: </p>

<pre><code>if (y.isEven()) {
    publicKeyBytesCompressed.unshift(0x02)
} else {
    publicKeyBytesCompressed.unshift(0x03)
}
</code></pre>

CC BY-SA 4.0
2020-05-08T17:56:12.780Z
2020-05-08T17:56:12.780Z
Albert Renshaw
<p>I've noticed that compressed public keys are always either 0x02 or 0x03, but what exactly determines whether it's 0x02 or 0x03? I can go look at the OpenSSL code to answer this, but I'm hoping someone already knows the answer and can tell me :P</p>

CC BY-SA 3.0
2013-05-28T21:50:21.440Z
Nevermind, I figured it out myself looking at the source. For those that want to know, the first byte of an OpenSSL EC public key has three bitflags. They have these semantics:

bit0 - tells you which y coordinate to use, bit1 - compressed, bit2 - uncompressed

So compressed public keys will always be 2 or 3 in the first byte, depending on which y coord is being used.
user2387532
CC BY-SA 3.0
2013-05-29T14:50:24.590Z
Could you elaborate and post it as a response, then accept it? That way we the question gets marked as complete.
cdecker
<cryptography>
The compressed public key byte header
user2387532
# The compressed public key byte header

(Asked by: username_0 on 2013-05-28)

I've noticed that compressed public keys are always either 0x02 or 0x03, but what exactly determines whether it's 0x02 or 0x03? I can go look at the OpenSSL code to answer this, but I'm hoping someone already knows the answer and can tell me :P

**Tags:** cryptography

> **Comments:**
> **username_0**: Nevermind, I figured it out myself looking at the source. For those that want to know, the first byte of an OpenSSL EC public key has three bitflags. They have these semantics:  bit0 - tells you which y coordinate to use, bit1 - compressed, bit2 - uncompressed  So compressed public keys will always be 2 or 3 in the first byte, depending on which y coord is being used.  
> **username_1**: Could you elaborate and post it as a response, then accept it? That way we the question gets marked as complete.  

---

## 2 answers

### Answer by username_2 on 2013-05-28. Score: 3

The public key format that OpenSSL and Bitcoin use is described in [SEP 1](http://www.secg.org/index.php?action=secg,docs_secg), published by the Standards for Efficent Cryptography Group on page 10.

> 1. Convert the field element xP to an octet string X of length ceil([log2 q]/8) octets using the conversion routine specified in Section
>    2.3.5.
> 2. Derive from yP a single bit ȳP as follows (this allows the y-coordinate to be represented compactly using a single bit):
> 3. If q = p is an odd prime, set ȳP = yP mod 2.
> 4. If q = 2m, set ȳP = 0 if xP = 0, otherwise compute z = zm-1xm-1 + · · · + z1x + z0 such that z = yPxP and set ȳP = z0.
> 5. Assign the value 0216 to the single octet Y if ȳP = 0, or the value 0316 if ȳP = 1.
> 6. Output M = Y || X.

... and page 53 ...

> * If C is an octet string and the leftmost octet of C is 0216 or 0316, parse the leftmost ceil([log2 q]/8)+1 octets of C as an octet string R, the rightmost *maclen* octets of C as an octet string D, and the remaining octets of C as an octet string *EM*.
> * If the leftmost octet of C is 0416, parse the leftmost 2 \* ceil([log2 q]/8) + 1 octets of C as an octet string R, the rightmost *maclen* octets of C as an octet string D, and the remaining octets of C as an octet string *EM*.
> * If the leftmost octet of C is not 0216, 0316, or 0416, output “invalid” and stop.

So, in plain English:

* It can be 0x04 too. That's is the 'uncompressed' key. If you generate a key today, it won't create one of these. However, if you have an old wallet, you might have some. They are equivalent in security to compressed keys.
* Whether it's 0x02 or 0x03 depends on on the value of ȳP. We can generate ȳP instead of including the full y coordinate, which saves us a nice bit of space. That's what compressed keys are.

I'm not sure what q is in this context, if somebody wants to tell me in comments, it'd be appreciated.


---

### Answer by username_3 on 2020-05-08. Score: 0

Parity determines if its 0x02 or 0x03

Node.JS:

```
if (y.isEven()) {
    publicKeyBytesCompressed.unshift(0x02)
} else {
    publicKeyBytesCompressed.unshift(0x03)
}

```


---

