<p>with a little bit help from arubi, I came to draw this picture. The blue part is the ECDSA logic. WIF keys and privkeys are linked via base58check en-/decoding. Depending on how you provide the privkey (compressed or uncompressed), the software decides how to create the pubkey and the bitcoin address. Obviously the bitcoin address will differ for compressed/uncompressed keys. With uncompressed keys you have the 512bit pub key with the x/y components, whereas the compressed pub key can be represented as only the x-component. The software would add the prefix 04 for uncompressed, or 02 (if even y) or 03 (if uneven y), and use it as input to sha256/ripemd160 to create the pubkey hash. With the last step there is again base58check encoding, with a checksum involved. </p>

<p><a href="https://i.sstatic.net/9XUI9.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/9XUI9.png" alt="privkey - ECDSA - bitcoin address"></a></p>

<p><strong>Example (testnet):</strong></p>

<pre><code>privkey Hex:   18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
privkey WIF:   91msh178DnLBqFhbuYqazuUwWpKBkRQvgj8bggdWMp81nVp9PfM
privkey WIF-c: cNR4jZU2sR5goytD4wXT4aeKcbqGSekbxLxY69v8aryxTU1SMnJZ
</code></pre>

<p><strong>pubkey hex uncompressed (04 + x + y):</strong></p>

<p>04 50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352
     2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6 </p>

<p><strong>pubkey hex compressed (02 + x, y=even):</strong> </p>

<p>02 50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352</p>

<p><strong>coresponding bitcoin addresses:</strong></p>

<pre><code>  (pubkey uncompressed): mfcSEPR8EkJrpX91YkTJ9iscdAzppJrG9j
  (pubkey compressed):   n3svudhm7bt6j3nTT9uu1A57Cs9pKK3iXW
</code></pre>

CC BY-SA 3.0
2018-01-24T18:55:01.783Z
Nice diagram!  For completeness, there is another valid public key type other than compressed and uncompressed, which is called 'Hybrid'.  It encodes both the `x` and `y` coordinates, and its length is 1 + 64 bytes (like an uncompressed pubkey), but the prefix byte could be either `0x07` or `0x06`.
arubi
CC BY-SA 3.0
2018-01-24T18:55:08.197Z
Basically, the even-ness or odd-ness of the prefix byte hints at the even-ness or odd-ness of the `y` coordinate encoded in the key.  I don't think a hybrid key has ever been used on mainnet, but still it is a valid pubkey and can appear in a script.  There is no WIF encoding of a hybrid private key, but anyone could sign and redeem a p2pkh script using such a key, and we would not know until it is relayed for spending.  Incorporating it into your diagram, the pubkey would be an input to the thrid step.
arubi
CC BY-SA 3.0
2018-01-24T22:00:52.490Z
never heard of these hybrid keys, just wondering what happens to be the privkey in hex representation. Any links you know of? Of course I want to give it a try on testnet/regtest. Btw.: a similiar diagram was in Ken Shirriff's famous "http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html". It just was counter clockwise - and counter intuitive for me :-). I flattened it out, and added the compressed logic.
pebwindkraft
CC BY-SA 3.0
2018-01-25T18:40:03.837Z
The private key as a number in hexadecimal is just the same.  There's no interface to any wallet that can handle hybrid keys, as far as I know so you'd have to build the raw transaction yourself.  It should be just the same as spending any other script containing a checksig.
Also, I don't know if even testnet\regtest policy of nodes will allow such a spend.  You might have to tweak the policy on your own node and mine it yourself.
arubi
CC BY-SA 3.0
2018-01-24T08:53:37.970Z
2018-01-24T08:53:37.970Z
pebwindkraft
<p>There is no algorithm for generating compressed pubkeys from private keys keys specifically.  In fact, all internal calculations involving points are done using the both the <code>x</code> <strong>and</strong> <code>y</code> coordinates of the points involved.  There is no other way to operate on points other than using the <code>(x,y)</code> coordinates.
A compressed representation of the point is useful in data transmission and storage because it only takes 33 bytes as opposed to 65 bytes to convey the point.  It's very easy to go from <code>compressed -&gt; uncompressed</code> when the need arise to perform point related operations, and even easier to go from <code>uncompressed -&gt; compressed</code> representation.
To answer your question, you would generate the public key as you normally would with an uncompressed pubkey, and when you're done, look for even-ness or odd-ness of the <code>y</code> corrdinate.
If it is even, encode only the <code>x</code> coordinate with a prefix <code>0x02</code> byte, and if it's odd the prefix is <code>0x03</code>.
To go back from <code>compressed -&gt; uncompressed</code> (really I just mean find the original <code>y</code> coordinate), you would just solve the curve's equation :</p>

<p><code>y^2 = x^3 + a*x + b</code></p>

<p>Specifically for secp256k1, the curve used in Bitcoin, <code>a</code> is zero, which makes this calculation easier, <strong>and</strong> there is a shortcut: due to a property of the curve's parameter <code>p</code>, where <code>p ≡ 3 mod 4</code> we are able to derive the <code>y</code> coordinate from an <code>x</code> coordinate simply by calculating:</p>

<pre><code>q = (p+1) * invmod(4)  mod p
y = powmod(y^2,q)      mod p
</code></pre>

<p>And there we have the original <code>y</code> coordinate back.</p>

CC BY-SA 3.0
2018-01-23T23:06:28.883Z
"it takes 33 bytes as opposed to 65 bytes to convey the point" - does it include the prefixes for the point calculations?
pebwindkraft
CC BY-SA 3.0
2018-01-24T06:44:23.463Z
The prefix is only used by software reading and writing the point as data.
It hints the software at what type of key is being read, and if it's a compressed key, which of the two possible `y` coordinates it should choose when uncompressing the point.
arubi
CC BY-SA 3.0
2018-01-23T18:37:53.403Z
2018-01-24T17:42:42.860Z
2018-01-24T17:42:42.860Z
arubi
<p>Just read this: <a href="https://bitcoin.stackexchange.com/a/1715/">https://bitcoin.stackexchange.com/a/1715/</a></p>

<p>What is the process to generate compressed pub keys via ECDSA?</p>

CC BY-SA 3.0
2018-01-23T17:57:01.860Z
interested to hear the responses - I thought the privkey and pubkey were only linked via ECDSA. Both are simply hex numbers... (of points on the curve tralala). And using the privkey base58encoded, goes to the WIF privkey. Added an additional hex "01" before encoding, I have a WIF-c (compressed) privkey, from which I derive compressed pubkey. Waiting for the answers...
pebwindkraft
<address><ecdsa>
How are compressed PubKeys generated?
MCCCS
# How are compressed PubKeys generated?

(Asked by: username_0 on 2018-01-23)

Just read this: <https://bitcoin.stackexchange.com/a/1715/>

What is the process to generate compressed pub keys via ECDSA?

**Tags:** address, ecdsa

> **Comments:**
> **username_1**: interested to hear the responses - I thought the privkey and pubkey were only linked via ECDSA. Both are simply hex numbers... (of points on the curve tralala). And using the privkey base58encoded, goes to the WIF privkey. Added an additional hex "01" before encoding, I have a WIF-c (compressed) privkey, from which I derive compressed pubkey. Waiting for the answers...  

---

## 2 answers

### Answer by username_2 on 2018-01-23. Score: 6 | Accepted answer

There is no algorithm for generating compressed pubkeys from private keys keys specifically. In fact, all internal calculations involving points are done using the both the `x` **and** `y` coordinates of the points involved. There is no other way to operate on points other than using the `(x,y)` coordinates.
A compressed representation of the point is useful in data transmission and storage because it only takes 33 bytes as opposed to 65 bytes to convey the point. It's very easy to go from `compressed -> uncompressed` when the need arise to perform point related operations, and even easier to go from `uncompressed -> compressed` representation.
To answer your question, you would generate the public key as you normally would with an uncompressed pubkey, and when you're done, look for even-ness or odd-ness of the `y` corrdinate.
If it is even, encode only the `x` coordinate with a prefix `0x02` byte, and if it's odd the prefix is `0x03`.
To go back from `compressed -> uncompressed` (really I just mean find the original `y` coordinate), you would just solve the curve's equation :

`y^2 = x^3 + a*x + b`

Specifically for secp256k1, the curve used in Bitcoin, `a` is zero, which makes this calculation easier, **and** there is a shortcut: due to a property of the curve's parameter `p`, where `p ≡ 3 mod 4` we are able to derive the `y` coordinate from an `x` coordinate simply by calculating:

```
q = (p+1) * invmod(4)  mod p
y = powmod(y^2,q)      mod p

```

And there we have the original `y` coordinate back.

> **Comments:**
> **username_1**: "it takes 33 bytes as opposed to 65 bytes to convey the point" - does it include the prefixes for the point calculations?  
> **username_2**: The prefix is only used by software reading and writing the point as data. It hints the software at what type of key is being read, and if it's a compressed key, which of the two possible `y` coordinates it should choose when uncompressing the point.  

---

### Answer by username_1 on 2018-01-24. Score: 3

with a little bit help from username_2, I came to draw this picture. The blue part is the ECDSA logic. WIF keys and privkeys are linked via base58check en-/decoding. Depending on how you provide the privkey (compressed or uncompressed), the software decides how to create the pubkey and the bitcoin address. Obviously the bitcoin address will differ for compressed/uncompressed keys. With uncompressed keys you have the 512bit pub key with the x/y components, whereas the compressed pub key can be represented as only the x-component. The software would add the prefix 04 for uncompressed, or 02 (if even y) or 03 (if uneven y), and use it as input to sha256/ripemd160 to create the pubkey hash. With the last step there is again base58check encoding, with a checksum involved.

[![privkey - ECDSA - bitcoin address](https://i.sstatic.net/9XUI9.png)](https://i.sstatic.net/9XUI9.png)

**Example (testnet):**

```
privkey Hex:   18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
privkey WIF:   91msh178DnLBqFhbuYqazuUwWpKBkRQvgj8bggdWMp81nVp9PfM
privkey WIF-c: cNR4jZU2sR5goytD4wXT4aeKcbqGSekbxLxY69v8aryxTU1SMnJZ

```

**pubkey hex uncompressed (04 + x + y):**

04 50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352
2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6

**pubkey hex compressed (02 + x, y=even):**

02 50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352

**coresponding bitcoin addresses:**

```
  (pubkey uncompressed): mfcSEPR8EkJrpX91YkTJ9iscdAzppJrG9j
  (pubkey compressed):   n3svudhm7bt6j3nTT9uu1A57Cs9pKK3iXW

```

> **Comments:**
> **username_2**: Nice diagram!  For completeness, there is another valid public key type other than compressed and uncompressed, which is called 'Hybrid'.  It encodes both the `x` and `y` coordinates, and its length is 1 + 64 bytes (like an uncompressed pubkey), but the prefix byte could be either `0x07` or `0x06`.  
> **username_2**: Basically, the even-ness or odd-ness of the prefix byte hints at the even-ness or odd-ness of the `y` coordinate encoded in the key.  I don't think a hybrid key has ever been used on mainnet, but still it is a valid pubkey and can appear in a script.  There is no WIF encoding of a hybrid private key, but anyone could sign and redeem a p2pkh script using such a key, and we would not know until it is relayed for spending.  Incorporating it into your diagram, the pubkey would be an input to the thrid step.  
> **username_1**: never heard of these hybrid keys, just wondering what happens to be the privkey in hex representation. Any links you know of? Of course I want to give it a try on testnet/regtest. Btw.: a similiar diagram was in Ken Shirriff's famous "http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html". It just was counter clockwise - and counter intuitive for me :-). I flattened it out, and added the compressed logic.  
> **username_2**: The private key as a number in hexadecimal is just the same.  There's no interface to any wallet that can handle hybrid keys, as far as I know so you'd have to build the raw transaction yourself.  It should be just the same as spending any other script containing a checksig. Also, I don't know if even testnet\regtest policy of nodes will allow such a spend.  You might have to tweak the policy on your own node and mine it yourself.  

---

