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
.