Why to manually expire any certificate?
There are multiple lab use cases where we want to test certain scenarios which requires a certificate to be expired. For example you have configured an alarm to be triggered when any certificate is about to be expired. Now to verify such alarm you would want the certificate to be expired right?
So how do we manually expire any certificate? Actually there is no such command which you can execute to just mark any certificate as expired. But there are a couple of tricks which can be used to achieve this.
In this tutorial I will share different tips and tricks which you can utilise to expire any certificate generated with openssl.
Lab Environment
I have already generate RootCA certificate, Private Key and CSR for Server certificate. In this article I will only execute the commands related to generate a signed server certificate.
You may follow these article to generate your own RootCA and server certificate before starting with this tutorial (if you don't already have one):
Create Certificate Authority and sign a certificate with Root CA
OpenSSL create certificate chain with Root & Intermediate CA
How OpenSSL verifies expiry of any certificate
You can check the validity of a certificate using following openssl command:
[root@controller certs]# openssl x509 -noout -text -in server.crt | grep -i -A2 validity
Validity
Not Before: Aug 27 19:32:58 2021 GMT
Not After : Aug 25 19:32:58 2031 GMT
To verify the certificate against RootCA certificate, we use following command:
[root@controller certs]# openssl verify -CAfile cacert.pem -verbose server.crt server.crt: OK [root@controller certs]# openssl x509 -checkend 86400 -noout -in server.crt Certificate will not expire
So basically all looks good here.
Now let us modify the date of my Linux server where this certificate is placed. The current date and time is:
[root@controller certs]# date
Sat Aug 28 01:51:28 IST 2021
I will use a different method to manipulate system's date and time later in this article which would be the recommended way.
As per above validity check we did with openssl command, our server certificate is going to expire on Aug 25 2031 so let me change my date to any day after this date:
[root@controller certs]# date --set "26 Aug 2031 10:10:10"
Tue Aug 26 10:10:10 IST 2031
Now check the validity of the certificate:
[root@controller certs]# openssl x509 -checkend 86400 -noout -in server.crt
Certificate will expire
So basically our certificate is marked as to be expired. Let us verify the certificate against rootCA:
[root@controller certs]# openssl verify -CAfile cacert.pem -verbose server.crt
C = IN, ST = KARNATAKA, L = BENGALORE, O = GoLinuxCloud, OU = Admin, CN = RootCA
error 10 at 1 depth lookup: certificate has expired
C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = example.com
error 10 at 0 depth lookup: certificate has expired
error server.crt: verification failed
So this exercise should explain the answer to the question "how openssl determines if any certificate has expired or not"
Basically openssl uses localhost server's date and time to determine the certificate's expiry date, so you can manipulate your server's date and time to manually expire any certificate.
Let us look into different scenarios and examples to check this further:
Scenario-1: Generate an expired certificate
In this scenario we do not have a certificate yet and we are actually planning to generate a new certificate.
Method-1: Generate expired certificate using faketime with openssl
Now instead of modifying system's date and time we can use faketime
tool to trick openssl into providing a different date and time.
For RHEL/CentOS/Fedora you must install epel-repo to install faketime:
[root@controller certs]# yum install epel-release
[root@controller certs]# yum whatprovides */faketime
Last metadata expiration check: 0:01:51 ago on Tue 26 Aug 2031 10:15:29 AM IST.
libfaketime-0.9.8-5.el8.x86_64 : Manipulate system time per process for testing purposes
Repo : epel
Matched from:
Filename : /usr/bin/faketime
Filename : /usr/lib64/faketime
[root@controller certs]# yum install libfaketime -y
Let us see how faketime
works:
# faketime '2010-01-01 10:10:10' date Fri Jan 1 10:10:10 IST 2010 # date Sat Aug 28 13:13:51 IST 2021
As you can see, I executed date command by providing a dummy past date using faketime and date command returned the same date while the actual system's date was not changed.
So, now we can use faketime
to manipulate system's date into an old date and then generate a certificate:
[root@controller certs]# faketime '2010-01-01 10:10:10' openssl x509 -req -days 365 -in server.csr -CA cacert.pem -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
subject=C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = example.com
Getting CA Private Key
We have set the system date to 01 Jan 2010
and then we generated a certificate with an expiry of 1 year and yet the certificate will still be expired because the actual date is 25 Aug 2021
Check the validity of this certificate:
[root@controller certs]# openssl x509 -checkend 86400 -noout -in server.crt Certificate will expire [root@controller certs]# openssl x509 -noout -text -in server.crt | grep -i -A2 validity Validity Not Before: Jan 1 04:40:10 2010 GMT Not After : Jan 1 04:40:10 2011 GMT [root@controller certs]# openssl verify -CAfile cacert.pem -verbose server.crt C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = example.com error 10 at 0 depth lookup: certificate has expired error server.crt: verification failed
So our certificate is already expired and you can continue with your tests.
Method-2: Generate expired certificate using past date
We also have an option to generate an expired certificate without using any additional tool. We have an option to specify number of days of expiry for the certificate using -days NUM
.
Here we can provide negative values to provide an past date so the generated certificate will already be expired. Let us check this using an example:
[root@controller certs]# openssl x509 -req -days -365 -in server.csr -CA cacert.pem -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
subject=C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = example.com
Getting CA Private Key
Here I have given number of days as -365
so the expiry date will be in past.
Now check the validity of this server.crt
file:
[root@controller certs]# openssl x509 -noout -text -in server.crt | grep -i -A2 validity Validity Not Before: Aug 28 07:53:53 2021 GMT Not After : Aug 28 07:53:53 2020 GMT [root@controller certs]# openssl x509 -checkend 86400 -noout -in server.crt Certificate will expire [root@controller certs]# openssl verify -CAfile cacert.pem -verbose server.crt C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = example.com error 10 at 0 depth lookup: certificate has expired error server.crt: verification failed
So we were able to manually expire this certificate without using any additional tools.
Scenario-2: How to expire any existing certificate
Now this can be tricky depending on your use case as we actually cannot expire an existing certificate without manipulating system's date and time where again we would be tricking openssl into thinking that the certificate has expired.
We would again use faketime
with openssl command to manipulate the system date and time. But here actually the certificate will not be in expired state.
For example, I have generated a fresh certificate with proper days of expiry:
[root@controller certs]# openssl x509 -req -days 365 -in server.csr -CA cacert.pem -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
subject=C = IN, ST = Karnataka, L = Bengaluru, O = GoLinuxCloud, OU = Admin, CN = example.com
Getting CA Private Key
The certificate verification is success:
[root@controller certs]# openssl verify -CAfile cacert.pem -verbose server.crt
server.crt: OK
Now we can execute the same command with faketime and some past date:
[root@controller certs]# faketime '2010-01-01 10:10:10' openssl verify -CAfile cacert.pem -verbose server.crt
C = IN, ST = KARNATAKA, L = BENGALORE, O = GoLinuxCloud, OU = Admin, CN = RootCA
error 9 at 1 depth lookup: certificate is not yet valid
error server.crt: verification failed
As you can see, now the same certificate is reporting as expired but in real we know that the certificate is still proper.
Summary
In this tutorial we covered different scenarios and methods which can be used to manually expire any certificate using openssl command. These testcases are mostly required for lab use cases and are not relevant in production environment. In dev environment, we have use cases related to expiry, alarm generation etc which expects the certificate to be expired where we can use the steps from this article.
Let me know if you have any questions or feedbacks using the comment section.