openssl ca vs openssl x509 comparison
Here's a table that compares the key features and functionalities of the openssl ca
and openssl x509
commands:
Feature/Functionality | openssl ca |
openssl x509 |
---|---|---|
Primary Purpose | To sign certificate requests and manage a CA database. | To display, convert, and manage certificates. |
Handling CSRs | Specifically designed to sign CSRs. | Can convert a CSR to a certificate but does not sign it. |
Managing Extensions | Can include extensions from a CSR in the signed certificate. Uses openssl.cnf for configuration. |
Limited support for handling extensions. Extensions must be specified manually if required. |
Certificate Authority (CA) Operations | Manages a CA database, handling multiple certificate signings, revocations, and renewals. | Does not manage CA operations. |
Certificate Conversion | Not intended for format conversion. | Converts certificates between various formats (e.g., PEM, DER). |
Certificate Display | Limited display capabilities. Mainly shows details of the signing process. | Extensive display options for certificate contents. |
Configuration File Dependency | Heavily relies on openssl.cnf for CA configurations and extension handling. |
Can use openssl.cnf for certain operations, but generally less dependent on the configuration file. |
Use in Automation/Scripts | Commonly used in automated CA environments for signing batches of CSRs. | Often used in scripts for certificate conversion and information extraction tasks. |
Let us understand the comparison with some examples
Generate RootCA Certificate
We would need a rootCA certificate to sign the certificates so first let use create one rootCA certificate.
Create directory structure
We will create our directory structure to keep all our rootCA related certificates.
Here index.txt is used to keep a track of all the certificates which will be signed by our RootCA certificate. The serial and crlnumber file will be used to keep the serial number for every certificate which is either signed or revoked respectively.
[root@controller tls]# mkdir /root/tls/{certs,private,crl} [root@controller tls]# touch serial crlnumber index.txt [root@controller tls]# echo 01 > serial [root@controller tls]# echo 1000 > crlnumber
You can add any number into the serial
and crlnumber
file to start with, now going forward every time we sign or revoke a certificate, respective file's entry will be incremented by 1.
List the available files under our /root/tls
directory:
[root@controller tls]# ls -l total 28 drwxr-xr-x 2 root root 4096 Aug 28 17:23 certs drwxr-xr-x 2 root root 4096 Aug 28 17:23 crl -rw-r--r-- 1 root root 5 Aug 28 17:25 crlnumber -rw-r--r-- 1 root root 0 Aug 28 17:25 index.txt drwxr-xr-x 2 root root 4096 Aug 28 17:23 private -rw-r--r-- 1 root root 3 Aug 28 17:25 serial
Sample openssl.cnf
Below is our sample openssl.cnf file which we have created under /root/tls
directory:
[root@controller tls]# cat openssl.cnf
Sample Output:
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = /root/tls # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
new_certs_dir = $dir/certs # default place for new certs.
certificate = $dir/certs/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem # The private key
x509_extensions = v3_ca # The extensions to add to the cert
default_days = 3650 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha512 # use SHA-256 by default
preserve = no # keep passed DN ordering
policy = policy_match
## This section is used to generate CSR for RootCA
[ policy_match ]
countryName = match ## Must match RootCA CSR and any certificate this RootCA signs
stateOrProvinceName = match ## Must match RootCA CSR and any certificate this RootCA signs
organizationName = match ## Must match RootCA CSR and any certificate this RootCA signs
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
default_md = sha512
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = IN
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
localityName_default = BANGALORE
0.organizationName = Organization Name (eg, company)
0.organizationName_default = GoLinuxCloud
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your servers hostname)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
## Extensions used for RootCA certificate
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:true
nsComment = "OpenSSL Generated Certificate"
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
Generate private key
Generate a private key for the rootCA certificate:
[root@controller tls]# openssl genrsa -out private/cakey.pem 4096 Generating RSA private key, 4096 bit long modulus (2 primes) ......................................................................++++ ...............++++ e is 65537 (0x010001)
Generate RootCA certificate
Next we will create our RootCA certificate using openssl x509
command. We have explicitly defined v3_ca
extension to be used for the rootCA certificate. We have already defined v3_ca
field with the x509 extensions required for RootCA.
[root@controller tls]# openssl req -new -x509 -days 3650 -config openssl.cnf -extensions v3_ca -key private/cakey.pem -out certs/cacert.pem You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [IN]: State or Province Name (full name) [Some-State]:Karnataka Locality Name (eg, city) [BANGALORE]: Organization Name (eg, company) [GoLinuxCloud]: Organizational Unit Name (eg, section) []:RootCA Common Name (eg, your name or your server's hostname) []:rootca.com Email Address []:
Following are the list of files available under /root/tls
at this stage:
[root@controller tls]# tree .
Sample Output:
Verify RootCA certificate X509 Extensions
Verify the x509 extensions from the rootca certificate:
[root@controller tls]# openssl x509 -noout -text -in certs/cacert.pem | grep -A10 "X509v3 extensions:" X509v3 extensions: X509v3 Subject Key Identifier: 61:01:DC:7C:C2:5D:41:BF:2B:BE:B2:D8:33:69:23:7A:15:C2:B1:A5 X509v3 Authority Key Identifier: keyid:61:01:DC:7C:C2:5D:41:BF:2B:BE:B2:D8:33:69:23:7A:15:C2:B1:A5 X509v3 Basic Constraints: critical CA:TRUE Netscape Comment: OpenSSL Generated Certificate Signature Algorithm: sha512WithRSAEncryption
Generate and sign certificate using openssl x509 command
In this section we will generate and sign certificates using openssl x509
command. I will use /certs_x509
directory to store the certificates we create in this section.
Generate private key
First let us generate the private key for the server certificate:
[root@controller certs_x509]# openssl genrsa -out server.key.pem 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
....................................................................................................................................++++
................................................................................................................................++++
e is 65537 (0x010001)
Generate Certificate Signing request
Next we will generate CSR for the server certificate:
[root@controller certs_x509]# openssl req -new -key server.key.pem -out server.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:IN State or Province Name (full name) []:KARNATAKA Locality Name (eg, city) [Default City]:BENGALURU Organization Name (eg, company) [Default Company Ltd]:GOLINUXCLOUD Organizational Unit Name (eg, section) []:ADMIN Common Name (eg, your name or your server's hostname) []:controller.example.com Email Address []:admin@golinuxcloud.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
openssl ca
command to generate and sign certificates
Generate and sign certificate using openssl x509 command
Next we will use openssl x509
command to sign and generate our server certificate:
[root@controller certs_x509]# openssl x509 -req -in server.csr -CA /root/tls/certs/cacert.pem -CAkey /root/tls/private/cakey.pem -out server.cert.pem -CAcreateserial -CAserial serial -days 365 -sha256
Signature ok
subject=C = IN, ST = KARNATAKA, L = BENGALURU, O = GOLINUXCLOUD, OU = ADMIN, CN = controller.example.com, emailAddress = admin@golinuxcloud.com
Getting CA Private Key
Here,
- -CA specifies the CA certificate to be used for signing.
- -CAkey sets the CA private key to sign a certificate with.
- -out specifies the output filename to write to or standard output by default.
- -CAcreateserial with this option the CA serial number file is created if it does not exist.
- -CAserial serial sets the CA serial number file to use.
- -days specifies the number of days to make a certificate valid for.
Verify if the certificate and the serial file have been created in the current working directory:
[root@controller certs_x509]# ls -l
total 16
-rw-r--r-- 1 root root 41 Aug 28 17:51 serial
-rw-r--r-- 1 root root 2009 Aug 28 17:51 server.cert.pem
-rw-r--r-- 1 root root 1781 Aug 28 17:45 server.csr
-rw------- 1 root root 3243 Aug 28 17:44 server.key.pem
Check the content of the serial file:
[root@controller certs_x509]# cat serial
7E107B565C51DFD2F24B279953215D2AAF689F16
You can also check the serial of the certificate using following command:
[root@controller certs_x509]# openssl x509 -in server.cert.pem -noout -serial
serial=7E107B565C51DFD2F24B279953215D2AAF689F16
What would happen if I sign the same certificate again?
Let us try to sign the same certificate again using the rootCA:
[root@controller certs_x509]# openssl x509 -req -in server.csr -CA /root/tls/certs/cacert.pem -CAkey /root/tls/private/cakey.pem -out server.cert.pem -CAcreateserial -CAserial serial -days 365 -sha256
Signature ok
subject=C = IN, ST = KARNATAKA, L = BENGALURU, O = GOLINUXCLOUD, OU = ADMIN, CN = controller.example.com, emailAddress = admin@golinuxcloud.com
Getting CA Private Key
As you case see, the openssl x509 has again signed the certificate without any issues. It has also updated the serial number of the certificate:
[root@controller certs_x509]# cat serial 7E107B565C51DFD2F24B279953215D2AAF689F17 [root@controller certs_x509]# openssl x509 -in server.cert.pem -noout -serial serial=7E107B565C51DFD2F24B279953215D2AAF689F17
This is because openssl x509 does not maintain a database of the certificate it signs using the root CA certificate. So it can sign the same certificate multiple times without the need of revocation.
Generate and sign certificate using openssl ca command
Now in this section we will generate and sign certificates using openssl ca
command. This should give you a basic idea of the difference between both the command.
I will store all the certificates generated at this section under /certs_ca
directory.
Generate private key
First of all let us generate a private key for the server certificate:
[root@controller certs_ca]# openssl genrsa -out server.key.pem 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
.......................................................................................++++
.....................++++
e is 65537 (0x010001)
Generate CSR
Next we will generate the Certificate Signing Request. Here also we will intentionally provide a different value for respective fields compared to what we provided with RootCA CSR:
[root@controller certs_ca]# openssl req -new -key server.key.pem -out server.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:IN State or Province Name (full name) []:Karnataka Locality Name (eg, city) [Default City]:Bengaluru Organization Name (eg, company) [Default Company Ltd]:Some Company Organizational Unit Name (eg, section) []:Admin Common Name (eg, your name or your server's hostname) []:controller.example.com Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Generate and sign server certificate
Now let us use openssl ca
to generate and sign the certificate. With openssl we must provide a valid openssl.cnf file which will contain all the details such as location of certificates, serial and index.txt files etc. We will use the openssl.cnf
which we had created for rootCA certificate.
[root@controller certs_ca]# openssl ca -config /root/tls/openssl.cnf -days 2650 -notext -batch -in server.csr -out server.crt
Using configuration from /root/tls/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'IN'
stateOrProvinceName :ASN.1 12:'Karnataka'
localityName :ASN.1 12:'Bengaluru'
organizationName :ASN.1 12:'Some Company'
organizationalUnitName:ASN.1 12:'Admin'
commonName :ASN.1 12:'controller.example.com'
The organizationName field is different between
CA certificate (GoLinuxCloud) and the request (Some Company)
As expected the openssl ca
command failed to sign the certificate because the State Name is different in the rootCA CSR compared to the CSR which we generated for our server certificate.
This is another difference between openssl ca
and openssl x509
commands. The openssl x509
command doesn't aggressively match the Subject details between Issuer and the consumer while openssl ca
command follows the policy section of openssl.cnf
to match these values.
I had already explained this part in Things to consider when creating CSR with OpenSSL
You can check the policy section used for RootCA in our openssl.cnf
:
[ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional
So the rootCA expects that countryName
, stateOrProvinceName
and organizationName
is exactly the same between RootCA and certificate which wants to get signed from this rootCA.
You may also modify the policy and generate your RootCA accordingly.
But for now, we will re-generate our CSR for the server certificate with the same values as used for RootCA:
[root@controller certs_ca]# openssl req -new -key server.key.pem -out server.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:IN State or Province Name (full name) []:Karnataka Locality Name (eg, city) [Default City]:BANGALORE Organization Name (eg, company) [Default Company Ltd]:GoLinuxCloud Organizational Unit Name (eg, section) []:Dev Common Name (eg, your name or your server's hostname) []:controller.example.com Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Next re-attempt to sign and generate a server certificate using openssl ca
command:
[root@controller certs_ca]# openssl ca -config /root/tls/openssl.cnf -days 2650 -notext -batch -in server.csr -out server.crt
Using configuration from /root/tls/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'IN'
stateOrProvinceName :ASN.1 12:'Karnataka'
localityName :ASN.1 12:'BANGALORE'
organizationName :ASN.1 12:'GoLinuxCloud'
organizationalUnitName:ASN.1 12:'Dev'
commonName :ASN.1 12:'controller.example.com'
Certificate is to be certified until Nov 29 13:15:29 2028 GMT (2650 days)
Write out database with 1 new entries
Data Base Updated
We have successfully signed and generated a server certificate.
Verify the index.txt
and serial
file content inside /root/tls
:
[root@controller certs_ca]# cat /root/tls/index.txt V 281129131529Z 01 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Dev/CN=controller.example.com [root@controller certs_ca]# openssl x509 -in server.crt -noout -serial serial=01 [root@controller certs_ca]# cat /root/tls/serial 02
As you can see, serial=01
is assigned to the certificate which we just created and the same has been updated in /root/tls/index.txt
file. Since 01
serial number is assigned to a certificate so the serial number has automatically been incremented to 02
.
This proves what I mentioned earlier, openssl ca
command maintains a database of all the certificates signed.
What would happen if I sign the same certificate again?
But let us try to re-sign the same certificate again. If you remember this had worked with openssl x509
command in the previous section:
[root@controller certs_ca]# openssl ca -config /root/tls/openssl.cnf -days 2650 -notext -batch -in server.csr -out server.crt
Using configuration from /root/tls/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'IN'
stateOrProvinceName :ASN.1 12:'Karnataka'
localityName :ASN.1 12:'BANGALORE'
organizationName :ASN.1 12:'GoLinuxCloud'
organizationalUnitName:ASN.1 12:'Dev'
commonName :ASN.1 12:'controller.example.com'
ERROR:There is already a certificate for /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Dev/CN=controller.example.com
The matching entry has the following details
Type :Valid
Expires on :281129131529Z
Serial Number :01
File name :unknown
Subject Name :/C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Dev/CN=controller.example.com
So unlike openssl x509
command, the openssl ca
command will not allow you to sign the same certificate again as the database already contains an entry for this Common Name.
To sign the same certificate again, you must first revoke this certificate and then you can sign it again.
Summary
In this article I have explained and covered the similarities and difference between openssl ca and openssl x509 commands. You must choose your command only based on your requirement. As for lab use cases when we may want to have a common certificate for multiple servers, then we may choose openssl x509 to sign the certificate but if you want to maintain a proper database of all the certificates signed then in such case you should go for openssl ca command to sign the certificates.
I hope I have covered all the scenarios related to this topic, let me know if you have any questions or feedback using the comments section below.
Further Reading
man page for openssl ca command
man page for openssl x509 command