1

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.

2

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')
2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.