9

Given a private key, I can get the uncompressed or compressed version of the public key like so.

EC_KEY* pKey = EC_KEY_new_by_curve_name(NID_secp256k1);

std::vector<unsigned char> getPubKey(EC_KEY* pKey, bool compressed) const {
    if (compressed)
        EC_KEY_set_conv_form(pKey, POINT_CONVERSION_COMPRESSED);
    else
        EC_KEY_set_conv_form(pKey, POINT_CONVERSION_UNCOMPRESSED);

    int nSize = i2o_ECPublicKey(pKey, NULL);
    std::vector<unsigned char> pubKey(nSize, 0)
    unsigned char* pBegin = &pubKey[0];
    i2o_ECPublicKey(pKey, &pBegin)
    return pubKey;
}

But how can I get the uncompressed public key from the compressed public key without knowing the private key?

2

3 Answers 3

2

If you have a compressed octet pubkey, use octet to point, then point to octet.

EC_POINT_oct2point(group, point, data, size, ctx);
EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, data, len, ctx);
2

You could also use the following to get an EC_POINT from a compressed key:

int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
                                             EC_POINT *p,
                                             const BIGNUM *x, int y_bit,
                                             BN_CTX *ctx);

and the following to convert the EC_POINT to an EC_KEY:

 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);

From EC_POINT_new documentation:

Points can also be described in terms of their compressed co-ordinates. For a point (x, y), for any given value for x such that the point is on the curve there will only ever be two possible values for y. Therefore a point can be set using the EC_POINT_set_compressed_coordinates_GFp() and EC_POINT_set_compressed_coordinates_GF2m() functions where x is the x co-ordinate and y_bit is a value 0 or 1 to identify which of the two possible values for y should be used.

and EC_KEY_new documentation:

The functions EC_KEY_get0_group(), EC_KEY_set_group(), EC_KEY_get0_private_key(), EC_KEY_set_private_key(), EC_KEY_get0_public_key(), and EC_KEY_set_public_key() get and set the EC_GROUP object, the private key, and the EC_POINT public key for the key respectively.

0

Sample code using boringssl in c.

EC_KEY  eckey = EC_KEY_new();
EC_GROUP = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
EC_KEY_set_group(eckey, ecgrp);

EVP_PKEY pubkey = EVP_PKEY_new();
EVP_PKEY_set1_EC_KEY(pubkey, eckey);

unsigned char *ptr = raw_data->data;
o2i_ECPublicKey(&eckey, (const uint8_t **)&ptr, raw_data->len);

//pubkey is the required public key

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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