Signing Certificates With OpenSSL
For environments where you don't have control over client systems, always use a recognized, independent CA to sign certificates. OS and software vendors negotiate with independent CAs to include CA validation certificates, along with the software that they distribute. Obtaining validation certificates from major CA providers means that most users don't have to manage their own trusted CA certificate list. Any browser visiting a website over HTTPS can validate the site's public certificate by matching the CA signature to the CA certificates that it has in its own store.
If you have control over client systems, you can either provide the clients with the self-signed certificate directly, or you can set up private CA certificate to sign all the certificates that are used within the organization and then distribute the CA certificate to clients. Using the second approach validates all certificates that are signed within the organization, which results in tighter control over the security of the certificates within the organization, which can result in reduced infrastructure costs.
Creating Self-Signed Certificates for Testing and Development
Self-signed certificates are often created for development and testing purposes. Because these certificates aren't validated by trusted CAs, trust for these certificates must be configured manually. If the private key is compromised it can't be revoked but must be manually removed from the trust allow list. Never use these certificates in production environments. A CA-signed certificate is always preferable to a self-signed certificate. However, using self-signed certificates can be less costly and useful for testing and development, without the hassle of managing private CA or obtaining CA-signed certificates for every test platform.
With the openssl
command, you can generate self-signed certificates that
can be used immediately. This command creates a CSR for the private key and then generates an
X.509 certificate directly from the CSR, signing the certificate with itself.
For this reason, the command is similar to the command that you would run to create a private key and CSR, with the exception that you must also specify the period of validity. As a good practice, only generate a self-signed certificate for the duration needed for testing purposes. This way, if the private key is compromised, the validity period is limited, and a new certificate can be generated when the old certificate expires.
For example, you would use the following command to create a self-signed X.509 certificate that's valid for 30 days:
sudo openssl req -new -x509 -days 30 -nodes -newkey rsa:2048 -keyout private.key \ -out public.cert -subj '/C=US/ST=Ca/L=Sunnydale/CN=www.example.com'
The generated private.key file contains the private key and the public.cert file contains the self-signed certificate. Typically, you name these files with the same value as the Common Name so that you can track which certificates and keys apply to which host and domain name.
Note that you can set the -newkey
value to suit custom algorithm and key
size requirements. In this example, the algorithm is set to RSA and the key size is set at
2048 bits.
You can copy the self-signed certificate file to the trusted certificate store for any client system and the client system validates the certificate as a match whenever it makes a connection to the host that serves it.
You can also use the keytool
command to generate self-signed certificates,
but this command's primary purpose is to install and manage JSSE (Java Secure Socket
Extension) digital certificates for use with Java applications. See Java for more
information.
Creating a Private Certification Authority
By creating a private Certification Authority (CA), you can process CSRs for all the certificates within the organization. You're also capable of managing the Certificate Revocation List (CRL), which client systems can use to detect whether a certificate is still valid or if it has been revoked.
This approach is better than using self-signed certificates because you can control revocation. However, the CA certificate must still be distributed to all the client systems that need to validate public certificates within the organization.
Create the CA Root
The CA Root is the fundamental certificate for a CA and isn't often used to sign server or client certificates. The CA Root is typically used to sign one or more intermediary certificates to grant them power to sign other certificates. This model means that if a CA Intermediary private key is compromised, the CA Intermediary can be added to a certificate revocation list and all the certificates that are signed by the Intermediary are automatically invalidated.
This model helps to protect the integrity of the entire public key infrastructure. Without a CA Root there's no public key infrastructure, as the CA Root is used to create the chain of trust that validates all certificates in the hierarchy. We recommend that the CA Root is created and maintained on a system that's fully isolated with minimal or no network access and no direct access to the Internet. The security measures that are implemented around the CA Root are critical to the security of the entire public key infrastructure. If the CA Root private key is compromised, every certificate that's ever signed by the entire chain might also be compromised.
To create a CA Root for the organization, you must create a root key pair according to a defined configuration that OpenSSL can use to manage the CA configuration and the database of metadata for issued certificates.
Several steps are involved in creating the CA Root, which are described in the following procedures and examples.
Create a CA Directory Structure
All certificates and metadata that are managed by the CA Root are stored in a specific directory structure within some preconfigured files. Create the structure according to specific requirements, but follow these general steps:
Create a CA Root Configuration File
Create the CA Root configuration in the directory where all the CA related content is
stored. For example, create a file in /etc/pki/ca/ca-root.conf
and populate
it with the following content:
[default]
name = root-ca
domain_suffix = example.com
aia_url = http://$name.$domain_suffix/$name.crt
crl_url = http://$name.$domain_suffix/$name.crl
ocsp_url = http://ocsp.$name.$domain_suffix:9080
default_ca = ca_default
name_opt = utf8,esc_ctrl,multiline,lname,align
[ca_dn]
countryName = "AU"
organizationName = "Example Org"
commonName = "Root CA"
[ca_default]
home = .
database = $home/db/index.txt
serial = $home/db/serial
crlnumber = $home/db/crlnumber
certificate = $home/$name.crt
private_key = $home/private/$name.key
RANDFILE = $home/private/random
new_certs_dir = $home/certs
unique_subject = no
copy_extensions = none
default_days = 3650
default_crl_days = 30
default_md = sha256
policy = policy_strict
[policy_strict]
# The root CA should only sign intermediary certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = optional
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[policy_loose]
# Allow the intermediary CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` manual page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[req]
# Standard Req options
default_bits = 4096
encrypt_key = yes
default_md = sha256
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = ca_dn
req_extensions = ca_ext
[ca_ext]
# Extensions for a the CA root (`man x509v3_config`).
basicConstraints = critical,CA:true
keyUsage = critical,keyCertSign,cRLSign
subjectKeyIdentifier = hash
[intermediary_ext]
# Extensions for an intermediary CA.
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[server_ext]
# Extensions for server certificates.
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[client_ext]
# Extensions for client certificates.
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[crl_ext]
# Extension for CRLs.
authorityKeyIdentifier=keyid:always
[ocsp]
# Extension for OCSP signing certificates.
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
The previous example shows a configuration that contains many optional entries that can help when performing different operations with OpenSSL. Most importantly, the configuration defines the extensions that can be applied to different certificate types to validate the types of operations the are valid for the certificate. This configuration also defines different policies that can be applied when signing certificates. For example, you can use a strict policy to ensure that a particular metadata is specified; and, that it matches the CA values within a CSR, if the certificate is to be signed. This policy is important for generating intermediary CA certificates. A less restrictive policy can be applied for other certificates that are signed, either by the CA Root or any intermediary.
The following are descriptions of the various sections within this configuration file:
- [default]
-
The default section defines some basic configuration information such as URLs where information such as the root certificate and the published revocation list for this CA might be published. Note that the
name
anddomain_suffix
entries here are used as variables to help construct some of these URLs and are also used to name and reference key files and certificates. You might want to use the system hostname and the system domain for these values. This configuration entry also references the location of the default CA configuration entry atca_default
. - [ca_dn]
-
This section defines some default values for certificates that are generated for this CA's distinguished name. These values are written into the CSR and the self-signed certificate that's generated from it for the CA Root certificate.
- [ca_default]
-
This section provides the configuration that controls the entire CA. This information provided maps the directories that were created for this CA to the configuration so that OpenSSL can correctly update files and store certificates and keys in the correct places. This section also defines some default values such as how many days a certificate is valid for and how many days the certificate revocation list is valid. Because this configuration is for a root CA, the number of days that the certificate is valid for can be set to 10 years, because a change to the root CA would mean that all later certificates in the infrastructure would also need to be reissued. You can view all the configuration file options in the
CA(1)
manual pages. - [policy_strict]
-
This section describes a strict policy that must be followed when signing some certificates, such as the intermediary CA certificates. The policy defines rules around the metadata within the certificate. For example, rules that the country name and organizational name match the CA certificate. Other fields are optional, but a common name must be supplied.
- [policy_loose]
-
This section is used for other certificates that are signed by this CA and its intermediaries, where a less restrictive policy is allowed. This policy entry makes most fields optional and only requires that the common name is supplied.
- [req]
-
This section is used one time to create the CA certificate request and defines the default options to use when the certificate request is generated, for example, a key length of 4096 bits for the root CA. Another option points to the CA distinguished name that references the
ca_dn
section of this configuration file for obtaining the default values to use within the certificate request. - [ca_ext]
-
This extensions section defines those operations for which a certificate is valid. For the root CA, this certificate must be valid to sign all the intermediary CA certificates and effectively has full rights. For more information about extensions, see the
X509V3_CONFIG(5)
manual page. - [intermediary_ext]
-
This section is separate extension configuration for certificates that are signed as intermediary CAs. This certificate has the same rights as the root CA, but is unable to sign certificates for further intermediary CAs, controlled with the
pathlen:0
within the certificate'sbasicConstraints
option. - [server_ext]
-
This section includes typical extension options for server-side certificates, which are often used for services such as HTTPS and server-side mail services, and so on. These certificates are issued for validation and encryption purposes, they don't have signing rights. The configuration entry can be referenced when signing a certificate for this purpose.
- [client_ext]
-
This section includes client-side certificates, which are often used for remote authentication, where a user may provide a certificate to validate and authenticate access to a system. These certificates also have specific extensions that control usage. This configuration entry can be used when signing a certificate for client side certificates to ensure that the correct extensions are applied to the certificate.
- [crl_ext]
-
This extension is automatically applied when creating a CRL, but this extension is provided for completeness. See Manage a Certificate Revocation List
- [ocsp]
-
The Online Certificate Status Protocol (OCSP) is a different approach to CRLs. An OCSP server can be set up to handle requests by client software to obtain the status of a certificate from a resource that's referenced in a signed certificate. Special extensions exist for this purpose. The
OCSP(1)
manual page can provide more information. See also Configure and Run an OCSP Server.
Create and Verify the CA Root Key Pair
This task shows how to create a private key and a certificate signing request for the CA
root using the configuration values specified in the ca-root.conf
file and
save the private key to private/root-ca.key
.
Because this is the most valuable key in the entire infrastructure, ensure that you use a lengthy and suitable passphrase to protect it:
sudo openssl req -new -config ca-root.conf -out root-ca.csr -keyout private/root-ca.key
Then, create a self-signed certificate by using the CSR and the ca-root.conf
file. Take care to specify that the certificate must use the extensions defined in the
ca_ext
section of the configuration.
sudo openssl ca -selfsign -config ca-root.conf -in root-ca.csr -out root-ca.crt -extensions ca_ext Using configuration from ca-root.conf Enter pass phrase for ./private/root-ca.key: Check that the request matches the signature Signature ok Certificate Details: Certificate: Data: Version: 3 (0x2) Serial Number: 8f:75:11:1a:8e:33:b2:d1:09:a8:bf:07:9c:67:c8:3e Issuer: countryName = AU organizationName = Example Org commonName = Root CA Validity Not Before: Oct 29 12:23:04 2019 GMT Not After : Oct 26 12:23:04 2029 GMT Subject: countryName = AU organizationName = Example Org commonName = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: 00:b9:41:d6:10:36:d4:12:d3:5d:52:29:60:fc:e0: 90:34:f6:fb:3e:99:10:33:a1:1d:54:77:3c:11:37: 2d:78:c3:3c:3f:40:69:37:fc:de:59:20:c1:1c:07: 83:f7:ae:2b:19:03:a7:e8:c6:d6:88:03:b4:ec:60: 36:3d:f6:da:59:58:cc:18:18:3e:43:c9:79:11:5b: cf:9e:15:a7:29:fe:dc:4f:7b:0b:93:f0:9a:2b:97: 0f:ab:3e:38:7c:e7:c7:d3:5e:34:e2:40:d0:fd:f2: e4:5e:2c:8a:8e:11:83:de:6b:c4:5c:b8:ec:4b:9c: d2:3f:06:3d:53:a6:4b:a6:e3:c6:f6:24:a2:8c:fb: bf:9e:19:d7:60:4b:c5:b6:48:e4:5d:60:4f:2c:47: ca:4a:31:79:bc:7b:5a:25:90:fc:d2:44:a1:79:73: 2e:e1:88:a0:73:1f:82:d3:63:3e:67:94:20:f8:be: 21:9b:c3:14:4d:3e:9b:19:33:be:9b:cb:e5:54:9f: a7:3f:05:d1:64:56:5f:43:62:65:5b:89:f4:f1:e3: 24:e8:1c:d5:03:36:86:ce:9e:76:c7:52:dc:88:f5: d9:87:62:00:82:4d:14:de:a3:60:21:54:12:83:da: 8e:8e:5f:63:c3:93:5a:e2:b9:60:16:74:06:c7:46: 49:6d:c2:7e:6c:3a:50:3b:bf:c5:d6:20:65:bd:21: a9:ad:b2:1c:4c:13:bf:fd:b8:e1:04:b8:46:c9:6c: 29:db:f3:a6:50:3d:2b:9b:83:49:bb:61:c2:8e:94: 08:52:84:f2:6d:33:4b:1f:e0:90:ea:a8:ec:d6:ff: 97:b8:3d:74:9a:64:d0:f7:22:7d:22:fc:93:47:68: 54:63:7c:10:0a:82:2f:84:3f:56:28:cf:8a:03:76: 77:b9:db:af:02:6d:b9:36:7e:63:da:f5:d2:a5:6d: 54:86:e1:be:f0:e1:54:13:dd:63:0a:53:8e:55:24: 90:40:af:f6:38:47:d3:00:0c:ba:66:6a:cc:4b:df: 28:fe:02:74:eb:28:15:11:ca:da:a7:86:0f:1f:bd: c4:ac:b9:b1:c7:cc:2a:2a:db:6e:fd:e6:8e:7b:02: 17:5e:a7:7d:08:53:e2:a4:69:ca:6b:1f:f1:74:5b: ac:86:2a:f2:b0:80:ea:b7:30:c5:14:c8:12:1e:66: 5e:2f:f5:d5:a8:09:39:b4:23:25:fc:ca:35:d5:c0: 73:79:a0:8a:12:25:27:ee:f5:ce:9a:97:c0:27:31: ac:21:98:8f:34:25:a5:7a:42:5c:a0:a1:5d:64:39: aa:6a:5e:54:50:5e:ad:c4:fe:c7:93:b1:c0:f7:c9: 91:43:93 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Subject Key Identifier: 3C:D9:C3:56:BD:C0:45:83:C8:2B:C7:0F:96:30:CF:2A:55:23:B5:9D Certificate is to be certified until Oct 26 12:23:04 2029 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
You're prompted for the private key passphrase to continue. After being shown the values of the certificate, you're prompted to sign the certificate. After signing the certificate, you can commit it to the CA database. The database files are updated to track this certificate within the public key infrastructure.
You can view the db/index.txt
file to see the CA root certificate entry:
sudo cat db/index.txt V 291026122304Z 8F75111A8E33B2D109A8BF079C67C83E unknown /C=AU/O=Example Org/CN=Root CA
The values that are displayed on each line within the database index include:
-
Status (
V
for valid,R
for revoked,E
for expired). -
Expiry date in
YYMMDDHHMMSSZ
format. -
Revocation date or empty if not revoked (in this example output, the field is empty).
-
Hexadecimal serial number.
-
File location or
unknown
, if not known. -
Distinguished name.
Create an Intermediary CA
The next step in creating the infrastructure is to create an intermediary CA that can process all the server and client certificates. This is important because if the intermediary CA private key is compromised, the root CA can revoke its certificate and invalidate any other certificate that has been issued by that intermediary.
We recommend that the intermediary CA is hosted on a different server with wider access as it handles most certificate requests. The intermediary CA is an exact model of the root CA, with the exception that its own certificate is signed by the root CA and is configured with the appropriate extensions to process signing requests.
Create a CA Directory Structure
On the intermediary CA host, perform the same operations that you performed to create the root CA directory structure, but name the parent directory appropriately so that it's clear that the configuration is for an intermediary, for example:
sudo mkdir /etc/pki/ca-intermediary
sudo cd /etc/pki/ca-intermediary/
sudo mkdir certs db crl newcerts private
sudo chmod 700 private
sudo touch db/index.txt
sudo openssl rand -hex 16 > db/serial
sudo echo 1001 |sudo tee db/crlnumber
Create the Intermediary CA Configuration
The intermediary CA configuration is almost identical to the configuration that you created for the CA root, with a few modifications that make it specific to the intermediary. Modifications are indicated in bold text in the following example:
[default] name = sub-ca domain_suffix = example.com aia_url = http://$name.$domain_suffix/$name.crt crl_url = http://$name.$domain_suffix/$name.crl ocsp_url = http://ocsp.$name.$domain_suffix:9080 default_ca = ca_default name_opt = utf8,esc_ctrl,multiline,lname,align [ca_dn] countryName = "AU" organizationName = "Example Org" commonName = "Intermediary CA" [ca_default] home = . database = $home/db/index.txt serial = $home/db/serial crlnumber = $home/db/crlnumber certificate = $home/$name.crt private_key = $home/private/$name.key RANDFILE = $home/private/random new_certs_dir = $home/certs unique_subject = no copy_extensions = none default_days = 3650 default_crl_days = 30 default_md = sha256 policy = policy_strict [policy_strict] # The root CA should only sign intermediary certificates that match. # See the POLICY FORMAT section of `man ca`. countryName = match stateOrProvinceName = optional organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [policy_loose] # Allow the intermediary CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the `ca` manual page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [req] # Standard Req options default_bits = 4096 encrypt_key = yes default_md = sha256 utf8 = yes string_mask = utf8only prompt = no distinguished_name = ca_dn req_extensions = intermediary_ext [ca_ext] # Extensions for a the CA root (`man x509v3_config`). basicConstraints = critical,CA:true keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash [intermediary_ext] # Extensions for an intermediary CA. subjectKeyIdentifier = hash # authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [server_ext] # Extensions for server certificates. basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth [client_ext] # Extensions for client certificates. basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [crl_ext] # Extension for CRLs. authorityKeyIdentifier=keyid:always [ocsp] # Extension for OCSP signing certificates. basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning
Note that in the intermediary_ext
section, the line containing
authorityKeyIdentifier
has been commented out because the intermediary
doesn't have the issuer certificate available. The intermediary is unaware of the certificate
issuer until the certificate is signed. If you try to create the CSR while this line is still
included in the configuration, it fails.
Save the configuration file as intermediary.conf
.
Create a CSR for the Intermediary CA
Create a CSR for the intermediary certificate:
sudo openssl req -new -config intermediary.conf -out sub-ca.csr -keyout private/sub-ca.key
This certificate is also a signing certificate, so it's important to protect it with a passphrase to help prevent its unauthorized use and maintain the security of the infrastructure. Enter the passphrase when prompted.
Create a Signed Certificate for the Intermediary CA
Copy the sub-ca.csr
that you generated in the previous step to the
/etc/pki/ca
directory on the system where the root CA is hosted. On the
root CA host, run the following commands to generate a signed certificate from the CSR and
apply the intermediary signing extension:
sudo cd /etc/pki/ca sudo openssl ca -config ca-root.conf -in sub-ca.csr -out newcerts/sub-ca.crt \ -extensions intermediary_ext
You're prompted for the root CA passphrase, then presented with the certificate content and prompted to sign it. Check that the certificate contents make sense before you sign it. You can see that the certificate is issued by the Root CA and contains the Intermediary CA in the Subject. You can also see that the correct extensions are applied to the certificate.
After the certificate is signed, you're prompted to update the database.
The newly signed certificate is created as newcerts/sub-ca.crt
.
Create a Certificate Chain File
Because no systems are aware of the root CA certificate, we recommend creating a certificate chain that includes the public certificate for the root CA with the newly created intermediary CA certificate. In this way, hosts only need a copy of the chained certificate to validate any certificates that are issued by the intermediary CA. To create the certificate chain, join the two public certificates by running the following command on the root CA host:
sudo cat root-ca.crt newcerts/sub-ca.crt > newcerts/chained-sub-ca.crt sudo chmod 444 newcerts/chained-sub-ca.crt
Copy the newcerts/sub-ca.crt
and
newcerts/chained-sub-ca.crt
certificate
back to the /root/ca-intermediary/
directory on the intermediary CA host. You can now use
this certificate to process server and client CSRs and to
generate CRLs.
When you return a signed certificate for a specific CSR, include the
chained-sub-ca.crt
certificate so that it can be installed on the host
where the certificate is used and distributed to any client that needs to validate the signed
certificate.
Process CSRs and Sign Certificates
As systems generate CSRs using the process that's described in Creating Certificate Signing Requests With OpenSSL, they must submit them to a CA to be signed.
All later CSR processing for server and client-side certificates should be performed by an intermediary CA that's configured within the environment or by an external third-party CA.
To process a CSR, copy it to the /root/ca-intermediary directory on the
intermediary CA host and then use the openssl ca
command to sign it with
the appropriate extension configuration.
For example, to sign a server-side certificate for a CSR
named
www.example.com.csr
,
run the following command:
sudo openssl ca -config intermediary.conf -extensions server_ext -days 375 \ -in www.example.com.csr -out newcerts/www.example.com.crt
Note that we specify the number of days for which the certificate is valid. For a server-side certificate, the number of days should be limited to a value much less than a CA certificate's validity. It's important to select the correct extensions to apply to the certificate. These extensions map to definitions that are within the configuration file.
You're prompted for the intermediary CA key passphrase and then prompted to sign the certificate and update the database.
Return the certificate, along with the chained CA certificate, so that these can be distributed to validate the certificate.
Manage a Certificate Revocation List
The certificate revocation list is used to identify certificates that have been issued by a signing CA and revoked. The list also tracks the reason that a certificate was revoked.
Generate the CRL
On each CA host, you should create an empty CRL that can be updated as you need to revoke certificates. For example, on an intermediary CA, you would use the following command:
sudo cd /etc/pki/ca-intermediary sudo openssl ca -config intermediary.conf -gencrl -out crl/sub-ca.crl
Note that the CRL should be published to the URL that's defined in the configuration file to
track certificates that are revoked by the CA. You should configure a web service to serve the
sub-ca.crl
, if possible.
You can check the contents of a CRL as follows:
sudo openssl crl -in crl/sub-ca.crl -noout -text
If the CRL was just created, it's empty. A new CRL should be created periodically, based on
the configuration value that's set in the CA configuration file for
default_crl_days
. By default, it's set for every 30 days.
Revoke a Certificate
Every signed certificate contains the serial number that's issued by the signing CA. You can view this serial number within a certificate as follows:
sudo openssl x509 -serial -noout -in server.crt
This serial number identifies the certificate within the CA signing database and can also be used to identify the certificate stored by the CA that signed it so that the CA can revoke it.
On the CA where the certificate was issued, you can find the certificate with the matching
serial number in the certs
directory. For example, on an intermediary host,
for a certificate with serial number 8F75111A8E33B2D109A8BF079C67C83F, it
would be as follows:
sudo cd /etc/pki/ca-intermediary
sudo ls certs/8F75111A8E33B2D109A8BF079C67C83F*
certs/8F75111A8E33B2D109A8BF079C67C83F.pem
You can also check the details for the certificate in the CA database:
sudo grep 8F75111A8E33B2D109A8BF079C67C83F db/index.txt
To revoke this certificate, the signing CA must issue the following command:
sudo openssl ca -config intermediary.conf -revoke certs/8F75111A8E33B2D109A8BF079C67C83F.pem \ -crl_reason keyCompromise
Note that you should specify the reason for revoking the certificate, as this reason is used
in the certificate revocation list. Options include the following:
unspecified
, keyCompromise
, CACompromise
,
affiliationChanged
, superseded
,
cessationOfOperation
, certificateHold,
and
removeFromCRL
. For more information, see the CA(1)
manual
page.
When a certificate is revoked, the CA database is updated to reflect this change and the
status is set to R
for the certificate that's listed in the
db/index.txt
file.
The database file is used to generate the CRL each time it's created. Good practice is to generate a new CRL as soon as you revoke a certificate. In this way, this list is kept current. See Generate the CRL for more information.
Configure and Run an OCSP Server
The Online Certificate Status Protocol (OCSP) provides an alternative to CRLs and includes its own publishing mechanism. OpenSSL includes an option to run as an OCSP server that can respond to OCSP queries.
Note that OCSP is preferred over CRLs. Usually, it's a good idea to ensure that an OCSP server is running for the CA, especially if the OCSP URL appears in the configuration, as this URL is included in each certificate that's signed by the CA. Any client software can confirm the revocation status of a certificate by querying the OCSP server.
For any CA, create a key and CSR for the OCSP server:
sudo openssl req -new -newkey rsa:2048 -subj "/C=AU/O=Example Org/CN=OCSP Responder" \
-keyout private/ocsp.key -out ocsp.csr
Create a signed certificate from the ocsp.csr
CSR file:
sudo openssl ca -config intermediary.conf -extensions ocsp -days 187 -in ocsp.csr \ -out newcerts/ocsp.crt
Because the OCSP certificate is responsible for handling revocation, it can't be revoked. Therefore, it's good practice to set the validity period on the certificate to a manageable, but relatively short period. In this example, the validity period has been set to 187 days, which means that it needs to be refreshed every 6 months.
To run an OCSP server on the current CA, you can use the tool provided within OpenSSL. For example, you could use the following command:
sudo openssl ocsp -port 9080 -index db/index.txt -rsigner newcerts/ocsp.crt \ -rkey private/ocsp.key -CA sub-ca.crt -text
Note that the command specifies the CA db/index.txt
file directly, which
means that as certificates are revoked, the OCSP server becomes aware of them automatically.
When you run the command, you're prompted for the OCSP key passphrase. The server continues to
run until you end the process or escape by using a control sequence such as
Ctrl-C
.
You can test the service by checking the ocsp.crt
file. Use the
openssl
command as follows to run an OCSP query:
sudo openssl ocsp -issuer sub-ca.crt -CAfile chained-sub-ca.crt -cert newcerts/ocsp.crt \ -url http://127.0.0.1:9080 Response verify OK newcerts/ocsp.crt: good This Update: Oct 30 15:48:11 2019 GMT
The response in the previous example indicates whether the verification has succeeded and
provides a status of good
if the certificate hasn't been revoked. A status of
revoked
is returned if it has been revoked.