user73342: 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.

user76567: Check out these two Python methods taken from here
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')


user48884: Here 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.

73342: <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>
 76567: <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>
 48884: <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>
