1

I am trying to extract the publickey from a certificate using OpenSSL in C and then convert it to .der format, but I cannot manage to do it.

The goal is to extract to extract to public key to implement pinning, like here: https://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html (public key extraction)

I am using the code from this tutorial.

BIO *certbio = NULL;
X509 *cert = NULL;
ret = BIO_read_filename(certbio, cert_path);
cert = PEM_read_bio_X509(certbio, NULL, 0, NULL));
EVP_PKEY *pkey = X509_get_pubkey(cert));

How can I convert from EVP_PKEY* to an unsigned char* in .der format? Or perhaps get it in .pem format and then convert it? Thanks

Taw
  • 479
  • 3
  • 15

1 Answers1

4

You can use the function i2d_PUBKEY() for this purpose:

https://www.openssl.org/docs/man1.1.0/crypto/i2d_PUBKEY.html

 int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp);

Note this important statement on the man page:

d2i_PUBKEY() and i2d_PUBKEY() decode and encode an EVP_PKEY structure using SubjectPublicKeyInfo format. They otherwise follow the conventions of other ASN.1 functions such as d2i_X509().

And this important note on the d2i_X509() man page:

int i2d_TYPE(TYPE *a, unsigned char **ppout);

i2d_TYPE() encodes the structure pointed to by a into DER format. If ppout is not NULL, it writes the DER encoded data to the buffer at *ppout, and increments it to point after the data just written. If the return value is negative an error occurred, otherwise it returns the length of the encoded data.

So call it once with a NULL second parameter to discover the required length of the buffer. Call it again with a pointer to your buffer to fill in the data - but note that your pointer will be incremented afterwards (a common source of confusion).

Matt Caswell
  • 8,167
  • 25
  • 28
  • Thanks for highlighting that the pointer is incremented afterwards - this caused some problems for us. – guglhupf Jul 16 '20 at 15:39