With the OpenSSL command line tools the standard pattern for creating a valid certificate is to generate a Certificate Signing Request with openssl req
and then sign it with an issuer to create a certificate with openssl x509
. Like so:
openssl req -new -key privatekey.pem -subj '/CN=examplehost.exampledomain.com' -out examplehost.csr
openssl x509 -req -in examplehost.csr -days 365 -sha256 -CA issuer.pem -CAkey issuer_priv.key -CAserial serial.file -out examplehost.pem
In the examples I've found for the C API the pattern appears to be to use X509_new()
to instantiate a blank X509 object, then use various methods to fill out the metadata and key manually within the X509 object. After that X509_sign()
is used to sign it with the the issuer private key.
I haven't found any examples of using an X509_REQ
as an input to creating a certificate even being possible with the C API. Is this a correct read? Or is there some call in this API that links Certs to CSRs by more than just manually copying fields over?
If you look at the source code of the OpenSSL C client, it will copy the fields manually (the corresponding locations in the current OpeNSSL source code are linked) using the following logic:
X509_REQ_get0_pubkey
.There is no official single routine that does this kind of operation directly in the API. However, if you're doing this to implement a CA-like functionality it is considered best practice to actually manually copy values over so that you can fully control what the resulting certificate contains. For example, you probably want to restrict the generation of certificates that are themselves CAs and only do that in cases where you explicitly want a sub-CA. (The X509v3 extension can be used to indicate this.)
That said, I hope the links to the source code of the command line utility are helpful in telling you what kind of operations you'd need to perform yourself to sign a CSR using OpenSSL's C API.
Finally: there's an undocumented function called X509_REQ_to_X509()
that automatically signs a CSR. DO NOT USE IT, as it doesn't support most modern certificate features (it only copies some things over) and it still uses the broken MD5 (!) algorithm for signing. (Remember that SHA-1 isn't accepted universally anymore?) Plus since the function is not documented, so there's no guarantee how long that routine will remain part of OpenSSL in the future. I'm only mentioning it for completeness sake and to warn against its usage.