[linux] How to determine SSL cert expiration date from a PEM encoded certificate?

If I have the actual file and a Bash shell in Mac or Linux, how can I query the cert file for when it will expire? Not a web site, but actually the certificate file itself, assuming I have the csr, key, pem and chain files.

This question is related to linux bash ssl openssl certificate

The answer is


If (for some reason) you want to use a GUI application in Linux, use gcr-viewer (in most distributions it is installed by the package gcr (otherwise in package gcr-viewer))

gcr-viewer file.pem
# or
gcr-viewer file.crt

For MAC OSX (El Capitan) This modification of Nicholas' example worked for me.

for pem in /path/to/certs/*.pem; do
    printf '%s: %s\n' \
        "$(date -jf "%b %e %H:%M:%S %Y %Z" "$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" +"%Y-%m-%d")" \
    "$pem";
done | sort

Sample Output:

2014-12-19: /path/to/certs/MDM_Certificate.pem
2015-11-13: /path/to/certs/MDM_AirWatch_Certificate.pem

macOS didn't like the --date= or --iso-8601 flags on my system.


Same as accepted answer, But note that it works even with .crt file and not just .pem file, just in case if you are not able to find .pem file location.

openssl x509 -enddate -noout -in e71c8ea7fa97ad6c.crt

Result:

notAfter=Mar 29 06:15:00 2020 GMT

One line checking on true/false if cert of domain will be expired in some time later(ex. 15 days):

openssl x509 -checkend $(( 24*3600*15 )) -noout -in <(openssl s_client -showcerts -connect my.domain.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM)
if [ $? -eq 0 ]; then
  echo 'good'
else
  echo 'bad'
fi

If you just want to know whether the certificate has expired (or will do so within the next N seconds), the -checkend <seconds> option to openssl x509 will tell you:

if openssl x509 -checkend 86400 -noout -in file.pem
then
  echo "Certificate is good for another day!"
else
  echo "Certificate has expired or will do so within 24 hours!"
  echo "(or is invalid/not found)"
fi

This saves having to do date/time comparisons yourself.

openssl will return an exit code of 0 (zero) if the certificate has not expired and will not do so for the next 86400 seconds, in the example above. If the certificate will have expired or has already done so - or some other error like an invalid/nonexistent file - the return code is 1.

(Of course, it assumes the time/date is set correctly)

Be aware that older versions of openssl have a bug which means if the time specified in checkend is too large, 0 will always be returned (https://github.com/openssl/openssl/issues/6180).


Here's my bash command line to list multiple certificates in order of their expiration, most recently expiring first.

for pem in /etc/ssl/certs/*.pem; do 
   printf '%s: %s\n' \
      "$(date --date="$(openssl x509 -enddate -noout -in "$pem"|cut -d= -f 2)" --iso-8601)" \
      "$pem"
done | sort

Sample output:

2015-12-16: /etc/ssl/certs/Staat_der_Nederlanden_Root_CA.pem
2016-03-22: /etc/ssl/certs/CA_Disig.pem
2016-08-14: /etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_S.pem

I have made a bash script related to the same to check if the certificate is expired or not. You can use the same if required.

Script

https://github.com/zeeshanjamal16/usefulScripts/blob/master/sslCertificateExpireCheck.sh

ReadMe

https://github.com/zeeshanjamal16/usefulScripts/blob/master/README.md


Here's a bash function which checks all your servers, assuming you're using DNS round-robin. Note that this requires GNU date and won't work on Mac OS

function check_certs () {
  if [ -z "$1" ]
  then
    echo "domain name missing"
    exit 1
  fi
  name="$1"
  shift

  now_epoch=$( date +%s )

  dig +noall +answer $name | while read _ _ _ _ ip;
  do
    echo -n "$ip:"
    expiry_date=$( echo | openssl s_client -showcerts -servername $name -connect $ip:443 2>/dev/null | openssl x509 -inform pem -noout -enddate | cut -d "=" -f 2 )
    echo -n " $expiry_date";
    expiry_epoch=$( date -d "$expiry_date" +%s )
    expiry_days="$(( ($expiry_epoch - $now_epoch) / (3600 * 24) ))"
    echo "    $expiry_days days"
  done
}

Output example:

$ check_certs stackoverflow.com
151.101.1.69: Aug 14 12:00:00 2019 GMT    603 days
151.101.65.69: Aug 14 12:00:00 2019 GMT    603 days
151.101.129.69: Aug 14 12:00:00 2019 GMT    603 days
151.101.193.69: Aug 14 12:00:00 2019 GMT    603 days

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to ssl

Requests (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.") Error in PyCharm requesting website A fatal error occurred while creating a TLS client credential. The internal error state is 10013 curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number How to install OpenSSL in windows 10? ssl.SSLError: tlsv1 alert protocol version Invalid self signed SSL cert - "Subject Alternative Name Missing" "SSL certificate verify failed" using pip to install packages ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749) Powershell Invoke-WebRequest Fails with SSL/TLS Secure Channel "ssl module in Python is not available" when installing package with pip3

Examples related to openssl

dyld: Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib How to install OpenSSL in windows 10? SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443 How to fix: fatal error: openssl/opensslv.h: No such file or directory in RedHat 7 Homebrew refusing to link OpenSSL Solving sslv3 alert handshake failure when trying to use a client certificate How to install latest version of openssl Mac OS X El Capitan How to resolve the "EVP_DecryptFInal_ex: bad decrypt" during file decryption SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed Can't get private key with openssl (no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY)

Examples related to certificate

Distribution certificate / private key not installed When you use 'badidea' or 'thisisunsafe' to bypass a Chrome certificate/HSTS error, does it only apply for the current site? Cannot install signed apk to device manually, got error "App not installed" Using client certificate in Curl command Convert .cer certificate to .jks SSL cert "err_cert_authority_invalid" on mobile chrome only Android Studio - Unable to find valid certification path to requested target SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch Verify a certificate chain using openssl verify Import Certificate to Trusted Root but not to Personal [Command Line]