<p>You could also use the following to get an <code>EC_POINT</code> from a compressed key:</p>

<pre><code>int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
                                             EC_POINT *p,
                                             const BIGNUM *x, int y_bit,
                                             BN_CTX *ctx);
</code></pre>

<p>and the following to convert the <code>EC_POINT</code> to an <code>EC_KEY</code>:</p>

<pre><code> int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
</code></pre>

<p>From <a href="https://www.openssl.org/docs/man1.0.2/crypto/EC_POINT_new.html" rel="nofollow noreferrer">EC_POINT_new documentation</a>:</p>

<blockquote>
  <p>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.</p>
</blockquote>

<p>and <a href="https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html" rel="nofollow noreferrer">EC_KEY_new documentation</a>:</p>

<blockquote>
  <p>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.</p>
</blockquote>

CC BY-SA 4.0
2018-10-10T21:15:33.367Z
2018-10-10T21:15:33.367Z
JBaczuk
<p>If you have a compressed octet pubkey, use octet to point, then point to octet.</p>

<pre><code>EC_POINT_oct2point(group, point, data, size, ctx);
EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, data, len, ctx);
</code></pre>

CC BY-SA 4.0
2018-08-13T13:43:46.793Z
2018-08-13T13:43:46.793Z
Erik Aronesty
<p>Sample code using boringssl in c.</p>
<pre><code>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-&gt;data;
o2i_ECPublicKey(&amp;eckey, (const uint8_t **)&amp;ptr, raw_data-&gt;len);

//pubkey is the required public key
</code></pre>

CC BY-SA 4.0
2022-12-05T12:07:09.327Z
2022-12-05T12:07:09.327Z
nick
<p>Given a private key, I can get the uncompressed or compressed version of the public key like so.</p>

<pre><code>EC_KEY* pKey = EC_KEY_new_by_curve_name(NID_secp256k1);

std::vector&lt;unsigned char&gt; 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&lt;unsigned char&gt; pubKey(nSize, 0)
    unsigned char* pBegin = &amp;pubKey[0];
    i2o_ECPublicKey(pKey, &amp;pBegin)
    return pubKey;
}
</code></pre>

<p>But how can I get the uncompressed public key from the compressed public key without knowing the private key?</p>

CC BY-SA 3.0
2014-07-09T17:59:34.223Z
I answered the same question here, but with an answer in Python: https://bitcointalk.org/index.php?topic=644919.msg7205689#msg7205689 If a language-agnostic answer is suitable, I can post this as an answer.
Tim S.
CC BY-SA 3.0
2014-07-09T19:39:32.610Z
Thanks for the solution, but I'm looking fora a canonical solution using openssl.
user299648
<public-key>
How can I get the uncompressed public key from the compressed public key in openssl?
user299648
# How can I get the uncompressed public key from the compressed public key in openssl?

(Asked by: username_0 on 2014-07-09)

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?

**Tags:** public-key

> **Comments:**
> **username_1**: I answered the same question here, but with an answer in Python: https://bitcointalk.org/index.php?topic=644919.msg7205689#msg7205689 If a language-agnostic answer is suitable, I can post this as an answer.  
> **username_0**: Thanks for the solution, but I'm looking fora a canonical solution using openssl.  

---

## 3 answers

### Answer by username_2 on 2018-10-10. Score: 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](https://www.openssl.org/docs/man1.0.2/crypto/EC_POINT_new.html):

> 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](https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html):

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


---

### Answer by username_3 on 2018-08-13. Score: 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);

```


---

### Answer by username_4 on 2022-12-05. Score: 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

```


---

