Martin Drozdik Martin Drozdik -4 years ago 220
C Question

How to read an RSA public key from a its PEM format string using the OpenSSL API?

I could use the

function to easily read a PEM file. However, I have a public key that I have built into the executable and I would prefer not to make a temporary file. Reading on this example/tutorial: I came up with the following solution:

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bio.h>

#include <QFile>
#include <QByteArray>

#include <stdexcept>
#include <cassert>
#include <cstring>

RSA* createRSA(const char* key)
RSA *rsa = nullptr;
BIO *keybio ;
keybio = BIO_new_mem_buf(key, -1); // !!!
if (!keybio)
throw std::runtime_error("Failed to create key BIO");
rsa = PEM_read_bio_RSA_PUBKEY(keybio, nullptr, nullptr, nullptr); // !!!
if(!rsa )
throw std::runtime_error("Failed to create RSA");
BIO_free(keybio); // !!!
return rsa;

int main()
QFile publicKeyFile(":/public.pem");;
auto data = publicKeyFile.readAll();

RSA* rsa = createRSA(;

EVP_PKEY* verificationKey = EVP_PKEY_new();
auto rc = EVP_PKEY_assign_RSA(verificationKey, RSAPublicKey_dup(rsa));
assert(rc == 1);


return 0;

However I have a lot of doubts:

  1. The
    takes a
    const void*
    parameter, can I just pass a
    const char*
    ? I did not figure it out even from the docs.

  2. When calling the
    function, the original example calls it like this:
    rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);

    which I do not understand even after reading the docs. I believe that I should pass
    as the second argument.

  3. Should I call
    on the returned
    does not see a memory leak whether I do it or not.

  4. Should I call
    after I am done with the
    sees a memory leak if I do not, and in the tutorial this call was missing. If I call
    it would imply that
    copied the data from the
    rather than just linking to it. But if that were the case, shouldn't I free the

Any advice is warmly appreciated. I do not know what is real anymore.

Answer Source

Answers to each of your questions:

  1. Yes, you can pass a const char*, it is cast.
  2. PEM_read_bio_RSA_PUBKEY creates allocates the RSA structure for you. The argument (if not null) is used to store the pointer to it, which will be the same as the return value. It is used for simplified coding: if (!PEM_read_bio_RSA_PUBKEY(keybio, &rsa, nullptr, nullptr)) { /* error */ }

  3. Yes, you have to release it using RSA_free.

  4. Yes, you have to release it too.

P.S.: OpenSSL documentation is a bit tricky because there are many similar functions that only vary in algorithm, structures or data format. At the end of the man page there is a Description section where they are explained, removing the specifics of each variation. But yes, it is quite difficult to find it out with out a good tutorial or examples.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download