ar_doc_26 openssl_ECC_enc_dec_signature - JohnHau/mis GitHub Wiki

Revoke certificate and generate CRL OpenSSL [Step-by-Step] Table of Contents OpenSSL revoke certificate – Introduction Certificate Revocation List (CRL) – Overview Lab Environment Create directory structure Sample openssl.cnf file Generate RootCA certificate Generate server/client certificates Step-1: Revoke certificate using OpenSSL Step-2: Verify the rootCA database Step-3: Generate Certificate Revocation List (CRL) Step-4: Check the Revoked Certificate List in CRL Step-5: Verify certificate against RootCA certificate after revoking the certificate Step-6: Revoke more certificates and update CRL Step-7: Update the Certificate Expiration time for CRL in openssl.cnf Summary Further Readings

OpenSSL revoke certificate - Introduction Revoking a certificate means declaring the certificate as 'Not Valid' and it can't be used any more. Once a certificate has been issued, it is generally put into production, where it will be distributed to many clients. If an attacker compromises the associated private key, he now has the ability to use the certificate even though it doesn’t belong to him. Assuming the proper owner is aware of the compromise, a new certificate with a new key pair should be obtained and put into use. In this situation there are two certificates for the same entity—both are technically valid, but one should not be trusted. The compromised certificate will eventually expire, but in the meantime, how will the world at large know not to trust it?

Enters Certificate Revocation List

Certificate Revocation List (CRL) - Overview A CRL contains a list of all of the revoked certificates a CA has issued that have yet to expire. When a certificate is revoked, the CA declares that the certificate should no longer be trusted. Bandwidth is a significant concern when distributing CRLs, since clients need to have reasonably current revocation information in order to properly validate a certificate. In an ideal world, the client would get up-to-date revocation information as soon as the CA gets the information. Unfortunately, many CAs distribute CRLs only as a huge list. Downloading a huge list before validating each certificate could easily add unacceptable latency and place an undue load on the server when there are a lot of clients. As a result, CAs tend to update their CRLs regularly, but not immediately after they learn about key compromises One solution to this problem is for the CA to break up its CRLs into segments. To do this, the CA specifies ranges of certificate serial numbers that each CRL contains. For example, the CA could create a different CRL for each 1,000 serial numbers. Therefore, the first CRL would be for serial numbers 1 through 1,000; the second would be for serial numbers 1,001 through 2,000, and so on. In this tutorial we will cover different steps involved to revoke certificate using openssl command and generate CRL.

Lab Environment First we will setup our Lab Environment with a bunch of certificates which we will revoke during the course of this tutorial. I have already created multiple tutorials covering different steps involved in generating RootCA , server and client certificate (you can find the links in the left sidebar menu).

Create directory structure We will store our rootCA certificate inside /root/tls directory:

[root@controller ~]# mkdir /root/tls; cd /root/tls [root@controller tls]# mkdir certs private crl [root@controller tls]# touch index.txt serial [root@controller tls]# touch crlnumber [root@controller tls]# echo 01 > serial [root@controller tls]# echo 1000 > crlnumber We have created two serial files wherein the serial file would be used to add serial number for newly signed certificate while crlnumber file would be used to assign the serial number to revoked certificates.

Sample openssl.cnf file This is my openssl configuration file which I will use in this entire article:

[ 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 name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options

crlnumber must also be commented out to leave a V1 CRL.

crl_extensions = crl_ext

default_days = 365 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = sha256 # use SHA-256 by default preserve = no # keep passed DN ordering

policy = policy_match

For the CA policy

[ policy_match ] countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional

#################################################################### [ req ] default_bits = 2048 default_md = sha256 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

[ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = IN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Karnataka localityName = Locality Name (eg, city) localityName_default = Bengaluru 0.organizationName = Organization Name (eg, company) 0.organizationName_default = GoLinuxCloud organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = Admin

commonName = Common Name (eg, your name or your server's 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

[ v3_req ]

Extensions to add to a certificate request

basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]

Extensions for a typical CA

PKIX recommendation.

subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer basicConstraints = critical,CA:true

[ crl_ext ]

CRL extensions.

Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.

authorityKeyIdentifier=keyid:always

Generate RootCA certificate I will not explain each step in detail as these are already covered in my previous tutorials which you can access from the left sidebar menu:

navigate inside your tls path

cd /root/tls

generate rootca private key

openssl genrsa -out private/cakey.pem 4096

generate rootCA certificate

openssl req -new -x509 -days 3650 -config openssl.cnf -key private/cakey.pem -out certs/cacert.pem

Verify the rootCA certificate content and X.509 extensions

openssl x509 -noout -text -in certs/cacert.pem

Generate server/client certificates I will generate multiple server and client certificate using the following steps:

navigate to /certs folder where we will store the certificates

cd /certs

generate server private key

openssl genrsa -out server.key.pem 4096

generate certificate signing request

openssl req -new -key server-1.key.pem -out server-1.csr

generate and sign the server certificate using rootca certificate

openssl ca -config /root/tls/openssl.cnf -notext -batch -in server-1.csr -out server-1.crt -extfile ext_template.cnf Following is the content of ext_template.cnf which contains the X,509 extension to be used for the server certificate:

basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth Next I generate a couple of server certificates inside /certs directory:

image

During this process, we have signed each of these certificates using our rootca certificate so the index.txt file was updated every time we signed the certificate.

[root@controller certs]# cat /root/tls/index.txt V 220904031732Z 01 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Admin/CN=server-1.example.com V 220904031929Z 02 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Admin/CN=server-2.example.com V 220904032019Z 03 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=Admin/CN=server-3.example.com V 220904040850Z 04 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-4.example.com V 220904042808Z 05 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-5.example.com Next we will revoke these certificates using openssl and generate CRL.

Step-1: Revoke certificate using OpenSSL Assuming you have the certificate which you plan to revoke, execute the following command. Here we are revoking server-1.crt certificate:

[root@controller certs]# openssl ca -config /root/tls/openssl.cnf -revoke /certs/server-1.crt Using configuration from /root/tls/openssl.cnf Revoking Certificate 01. Data Base Updated No change is made to the certificate at all. In fact, the only noticeable change is to the CA’s database to indicate that the certificate has been revoked.

Step-2: Verify the rootCA database Next you can check the rootCA index.txt file to make sure your certificate has been properly revoked:

[root@controller certs]# cat /root/tls/index.txt R 220904031732Z 210904032109Z 01 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Admin/CN=server-1.example.com V 220904031929Z 02 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Admin/CN=server-2.example.com V 220904032019Z 03 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=Admin/CN=server-3.example.com V 220904040850Z 04 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-4.example.com V 220904042808Z 05 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-5.example.com Notice the first column of first row i.e. R for Revoked. So certificate with server-1.example.com CN has been revoked

Step-3: Generate Certificate Revocation List (CRL) Next we need to generate the Certificate Revocation List which will contain the list of the certificates which has been revoked. You can actually create a CRL even before a certificate is revoked in which case the revocation list will be empty inside the CRL.

[root@controller certs]# openssl ca -config /root/tls/openssl.cnf -gencrl -out /root/tls/crl/rootca.crl Using configuration from /root/tls/openssl.cnf Here /root/tls/crl/rootca.crl file will be created based on the existing list of certificates that have been revoked.

Step-4: Check the Revoked Certificate List in CRL We can get the list of certificates that have been revoked inside the CRL. Use the following command to view the CRL:

[root@controller certs]# openssl crl -in /root/tls/crl/rootca.crl -text -noout Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = rootca.com Last Update: Sep 4 03:22:06 2021 GMT Next Update: Oct 4 03:22:06 2021 GMT CRL extensions: X509v3 CRL Number: 4096 Revoked Certificates: Serial Number: 01 Revocation Date: Sep 4 03:21:09 2021 GMT Signature Algorithm: sha256WithRSAEncryption ... So the certificate with Serial Number 01 has been revoked which we also verified using our index.txt file in the previous steps.

As soon as you generate or update a CRL, the crlnumber file gets incremented with a new integer:

[root@controller tls]# cat crlnumber 1001 If you recall from our lab environment section, we had added 1000 as the base value which now has been incremented to 1001 as one we generated our first CRL.

Step-5: Verify certificate against RootCA certificate after revoking the certificate You will define the CRL file location to your server application which will perform the certificate validation before initiating the connection to make sure that the certificate in use is valid or not.

But we can also manually verify the certificate. Create a temporary RootCA by merging the CRL file with the RootCA certificate:

[root@controller tls]# cat certs/cacert.pem crl/rootca.crl > /tmp/test.pem Next verify the server-1.crt against this newly created bundle containing rootCA + CRL file:

[root@controller tls]# openssl verify -extended_crl -verbose -CAfile /tmp/test.pem -crl_check /certs/server-1.crt C = IN, ST = Karnataka, O = GoLinuxCloud, OU = Admin, CN = server-1.example.com error 23 at 0 depth lookup: certificate revoked error /certs/server-1.crt: verification failed As you can see, the verification failed because the certificate was revoked.

You can use the same bundle to test remaining certificate and it should pass because those have not been revoked or expired yet:

[root@controller tls]# openssl verify -extended_crl -verbose -CAfile /tmp/test.pem -crl_check /certs/server-2.crt /certs/server-2.crt: OK

Step-6: Revoke more certificates and update CRL Next we will continue to revoke some more certificates:

[root@controller certs]# openssl ca -config /root/tls/openssl.cnf -revoke /certs/server-2.crt Using configuration from /root/tls/openssl.cnf Revoking Certificate 02. Data Base Updated Our database has been updated accordingly:

[root@controller tls]# cat index.txt R 220904031732Z 210904032109Z 01 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Admin/CN=server-1.example.com R 220904031929Z 210904033301Z 02 unknown /C=IN/ST=Karnataka/O=GoLinuxCloud/OU=Admin/CN=server-2.example.com V 220904032019Z 03 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=Admin/CN=server-3.example.com V 220904040850Z 04 unknown /C=IN/ST=Karnataka/O=golinuxcloud/OU=admin/CN=server-4.example.com V 220904042808Z 05 unknown /C=IN/ST=karnataka/O=golinuxcloud/OU=admin/CN=server-5.example.com Update the CRL

[root@controller tls]# openssl ca -config /root/tls/openssl.cnf -gencrl -out /root/tls/crl/rootca.crl Using configuration from /root/tls/openssl.cnf HINT: At this stage you can either decide to create a new CRL or update the existing one. Since we have a single RootCA so we will update the existing CRL. Verify the CRL file content to get the list of revoked certificates:

[root@controller tls]# openssl crl -in /root/tls/crl/rootca.crl -text -noout Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = rootca.com Last Update: Sep 4 03:33:57 2021 GMT Next Update: Oct 4 03:33:57 2021 GMT CRL extensions: X509v3 CRL Number: 4099 Revoked Certificates: Serial Number: 01 Revocation Date: Sep 4 03:21:09 2021 GMT Serial Number: 02 Revocation Date: Sep 4 03:33:01 2021 GMT Signature Algorithm: sha256WithRSAEncryption ... Verify the server-2.crt against the test.pem bundle which we had created earlier:

[root@controller tls]# openssl verify -extended_crl -verbose -CAfile /tmp/test.pem -crl_check /certs/server-2.crt /certs/server-2.crt: OK The validation says OK because we have not added our latest CRL inside the test.pem bundle. let's update the test.pem bundle and perform re-validation:

[root@controller tls]# cat certs/cacert.pem crl/rootca.crl > /tmp/test.pem

[root@controller tls]# openssl verify -extended_crl -verbose -CAfile /tmp/test.pem -crl_check /certs/server-2.crt C = IN, ST = Karnataka, O = GoLinuxCloud, OU = Admin, CN = server-2.example.com error 23 at 0 depth lookup: certificate revoked

Step-7: Update the Certificate Expiration time for CRL in openssl.cnf It is important that you are familiar with default_crl_days , default_days , and default_md values which we have added in our openssl.cnf

Currently we have defined following values for these parameters in the openssl.cnf:

default_days = 365 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = sha256 # use SHA-256 by default Here,

The default_crl_days key specifies the number of days between CRLs. You may wish to use default_crl_hours instead if you plan to publish CRLs more than once a day. This setting computes the nextUpdate field of the CRL when it is generated. The default_days key specifies the number of days an issued certificate will be valid. The default_md specifies the message digest algorithm that will be used to sign issued certificates and CRLs. Possible legal values for this key include md5, sha1, and mdc2. If the CRL is expired then the certificate verification would fail. For example, here I am using faketime to manipulate the system time into thinking that we are in 2021 December which is past the date of expiry for our CRL. Now let's validate one of our certificates against the CRL and RootCA certificate (bundle which we created in previous examples):

[root@controller tls]# faketime '2021-12-24 08:15:42' openssl verify -extended_crl -CAfile /tmp/test.pem -crl_check /certs/server-5.crt C = IN, ST = karnataka, O = golinuxcloud, OU = admin, CN = server-5.example.com error 12 at 0 depth lookup: CRL has expired error /certs/server-5.crt: verification failed

As you can see, the CRL is marked as expired hence the validation could not be performed.

So it is recommended that you update your CRL at regular intervals to keep the revocation list up to date.

Summary In this tutorial we covered steps to properly revoke certificate using openssl command and generate CRL. Although we have only covered the steps to revoke any server or client certificate and generate the CRL. But there is also a possible problem when the root CA certificate needs to be revoked. A CRL can not be used to handle such scenarios. The reason because, a CRL is issued by the RootCA itself for its children i.e. intermediate certificates or server/client certificates but if the CA's key is compromised then it still be be trued. Unfortunately this can not be handled by CRL.