<p><a href="https://github.com/bitcoin-core/secp256k1/blob/0b7024185045a49a1a6a4c5615bf31c94f63d9c4/src/eckey_impl.h#L37" rel="nofollow noreferrer">Here</a> is how Bitcoin Core's libsecp256k1 performs public key serialization, which includes the compression. Here is the relevant parts:</p>

<pre><code>static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) {
    ...
    secp256k1_fe_get_b32(&amp;pub[1], &amp;elem-&gt;x);
    if (compressed) {
        *size = 33;
        pub[0] = secp256k1_fe_is_odd(&amp;elem-&gt;y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
    } else {
        ...
    }
    return 1;
}
</code></pre>

<p>Compression is very simply, if the Y value of the pubkey is odd, place an <code>0x03</code> byte. If it is even, place a <code>0x02</code> byte. Then write out the 32 bytes for the X value. That's it.</p>

CC BY-SA 4.0
2018-06-12T21:48:37.610Z
2018-06-12T21:48:37.610Z
Ava Chow
<p>Check out these two Python methods taken from <a href="https://github.com/mcdallas/cryptotools/blob/master/ECDSA/secp256k1.py#L92" rel="nofollow noreferrer">here</a></p>

<pre><code>class PublicKey

@classmethod
def decode(cls, key: bytes) -&gt; 'PublicKey':
    if key.startswith(b'\x04'):        # uncompressed key
        assert len(key) == 65, 'An uncompressed public key must be 65 bytes long'
        x, y = bytes_to_int(key[1:33]), bytes_to_int(key[33:])
    else:                              # compressed key
        assert len(key) == 33, 'A compressed public key must be 33 bytes long'
        x = bytes_to_int(key[1:])
        root = modsqrt(CURVE.f(x), P)
        if key.startswith(b'\x03'):    # odd root
            y = root if root % 2 == 1 else -root % P
        elif key.startswith(b'\x02'):  # even root
            y = root if root % 2 == 0 else -root % P
        else:
            assert False, 'Wrong key format'

    return cls(Point(x, y))

def encode(self, compressed=False) -&gt; bytes:
    if compressed:
        if self.y &amp; 1:  # odd root
            return b'\x03' + int_to_bytes(self.x).rjust(32, b'\x00')
        else:           # even root
            return b'\x02' + int_to_bytes(self.x).rjust(32, b'\x00')
    return b'\x04' + int_to_bytes(self.x).rjust(32, b'\x00') + int_to_bytes(self.y).rjust(32, b'\x00')
</code></pre>

CC BY-SA 4.0
2018-06-12T21:42:37.673Z
2018-06-12T21:42:37.673Z
Mike D
<p>Hi there I was looking for some code sample on compressing a bitcoin public keys  from the curve secp256k1. Just for me to get a good grasp, I have seen code going from compressed to uncompressed, <em>I'd like to see also code from uncompressed to compressed.</em>
Any language is fine, preferably Java/Js.</p>

<wallet><public-key>
Bitcoin public keys from uncompressed to compressed version with code sample
Eddy
# Bitcoin public keys from uncompressed to compressed version with code sample

(Asked by: username_0 on 2018-06-12)

Hi there I was looking for some code sample on compressing a bitcoin public keys from the curve secp256k1. Just for me to get a good grasp, I have seen code going from compressed to uncompressed, *I'd like to see also code from uncompressed to compressed.*
Any language is fine, preferably Java/Js.

**Tags:** wallet, public-key


---

## 2 answers

### Answer by username_1 on 2018-06-12. Score: 3

[Here](https://github.com/bitcoin-core/secp256k1/blob/0b7024185045a49a1a6a4c5615bf31c94f63d9c4/src/eckey_impl.h#L37) is how Bitcoin Core's libsecp256k1 performs public key serialization, which includes the compression. Here is the relevant parts:

```
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) {
    ...
    secp256k1_fe_get_b32(&pub[1], &elem->x);
    if (compressed) {
        *size = 33;
        pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
    } else {
        ...
    }
    return 1;
}

```

Compression is very simply, if the Y value of the pubkey is odd, place an `0x03` byte. If it is even, place a `0x02` byte. Then write out the 32 bytes for the X value. That's it.


---

### Answer by username_2 on 2018-06-12. Score: 2

Check out these two Python methods taken from [here](https://github.com/mcdallas/cryptotools/blob/master/ECDSA/secp256k1.py#L92)

```
class PublicKey

@classmethod
def decode(cls, key: bytes) -> 'PublicKey':
    if key.startswith(b'\x04'):        # uncompressed key
        assert len(key) == 65, 'An uncompressed public key must be 65 bytes long'
        x, y = bytes_to_int(key[1:33]), bytes_to_int(key[33:])
    else:                              # compressed key
        assert len(key) == 33, 'A compressed public key must be 33 bytes long'
        x = bytes_to_int(key[1:])
        root = modsqrt(CURVE.f(x), P)
        if key.startswith(b'\x03'):    # odd root
            y = root if root % 2 == 1 else -root % P
        elif key.startswith(b'\x02'):  # even root
            y = root if root % 2 == 0 else -root % P
        else:
            assert False, 'Wrong key format'

    return cls(Point(x, y))

def encode(self, compressed=False) -> bytes:
    if compressed:
        if self.y & 1:  # odd root
            return b'\x03' + int_to_bytes(self.x).rjust(32, b'\x00')
        else:           # even root
            return b'\x02' + int_to_bytes(self.x).rjust(32, b'\x00')
    return b'\x04' + int_to_bytes(self.x).rjust(32, b'\x00') + int_to_bytes(self.y).rjust(32, b'\x00')

```


---

