Question

I would like to programmatically generate a certificate that contain only the public key using openssl.

So I basically need to do the following but using code.

openssl x509 -in certificate.crt -pubkey

Digging a bit it seem that I need to create a new certificate and copy all the information except the private key in it.

X509 * pNewKey = X509_new();
... Copy all the needed information ...

PEM_write_bio_X509(bioKey, &pNewKey, NULL, NULL);

Does someone have a better method?

Was it helpful?

Solution

I would like to programmatically generate a certificate that contain only the public key

To set the public key, take your public key in EVP_PKEY format and call X509_set_pubkey. Building upon your example code:

X509* x509 = X509_new();
EVP_PKEY* pkey = /***/;

int rc = X509_set_pubkey(x509, pkey);
ASSERT(rc == 1);

BIO* bio = BIO_new_file("filename.txt", "w");
ASSERT(bio != NULL);

rc = PEM_write_bio_X509(bio, x509, NULL, NULL);
ASSERT(rc == 1);

...
BIO_free(bio);
EVP_PKEY_free(pkey);
X509_free(x509);

For completeness, OpenSSL will save a certificate with no attributes, no version, no public key, and no signature.


So I basically need to do the following but using code.

openssl x509 -in certificate.crt -pubkey

OK, this is a different question. The above command will print the public key.

Use x509_get_pubkey:

EVP_PKEY* pkey = X509_get_pubkey(X509* x509);

Once you have the EVP_PKEY, you can get the type. You need to supply this function because OpenSSL does not provide it:

int EVP_PKEY_get_type(EVP_PKEY *pkey)
{
    AC_ASSERT(pkey);
    if (!pkey)
        return NID_undef;

    return EVP_PKEY_type(pkey->type);
}

Then, depending on the type, you can print the key:

if(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2)
{
    RSA* rsa = EVP_PKEY_get1_RSA(pkey);
    RSA_print_fp(stdout, rsa, 0);
    RSA_free(rsa);
}
...

You have to break out the keys by type and then call the respective XXX_print_fp because OpenSSL does not provide an EVP_PKEY_print_fp.

The get1 in EVP_PKEY_get1_RSA means the reference count on the key is bumped. So you have to call a *_free on it. A get0 does not bump the reference count, and does not need a call to *_free.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top