Check a PEM certificate’s expiration date
Read notAfter with OpenSSL, test an expiration threshold, inspect certificate bundles, and calculate remaining days with explicit error handling.
Use openssl x509 -in certificate.pem -noout -dates to print a certificate's validity period. notBefore is its start time and notAfter is its expiration time, normally displayed in GMT. For an automated threshold check, use -checkend rather than parsing a date string.
Read the dates
openssl x509 -in certificate.pem -noout -dates
# Example output:
# notBefore=Mar 20 12:00:00 2023 GMT
# notAfter=Mar 20 12:00:00 2024 GMT
# Print only the expiration date.
openssl x509 -in certificate.pem -noout -enddate
The example dates are illustrative, not a currently valid certificate.
Test a renewal threshold
# 30 days = 2,592,000 seconds.
if openssl x509 -in cert.pem -checkend 2592000 -noout; then
echo "Certificate expires beyond the 30-day threshold."
else
echo "Certificate expires within 30 days, or it could not be read. Check diagnostics."
fi
For a successfully parsed certificate, exit status zero means it will not expire within the threshold. A nonzero status can mean expiration or a read/parse error, so retain the diagnostic output. This check does not validate the hostname, trust chain, or notBefore date.
Inspect a directory
for f in /etc/ssl/certs/*.pem; do
[ -f "$f" ] || continue
if exp=$(openssl x509 -in "$f" -noout -enddate); then
printf '%s -> %s\n' "$f" "$exp"
else
printf 'Could not read certificate: %s\n' "$f" >&2
fi
done
Keep the system clock accurate before comparing dates. Convert GMT to local time explicitly when reporting results to others.
A full-chain PEM contains several certificates. openssl x509 reads the first certificate, normally the leaf in a correctly ordered server chain. To inspect all certificates, including intermediates:
openssl crl2pkcs7 -nocrl -certfile fullchain.pem \
| openssl pkcs7 -print_certs -noout -text
Inspect a remote endpoint
openssl s_client -servername example.com -connect example.com:443 </dev/null \
| openssl x509 -noout -dates
This extracts dates; it does not by itself prove the endpoint's identity. Use explicit hostname and trust verification for that separate task. When an endpoint has renewed, check what it serves rather than assuming it loaded the new file.
Guance SSL tests can check certificate lifetime by hostname and port. Include every relevant entry point and select a remaining-days condition appropriate to the renewal schedule.
Common questions
Does this work when the PEM also contains a private key?
Yes. openssl x509 reads a certificate block and skips other PEM block types. It does not print the private key.
How can I print remaining days?
This shell example requires GNU date, commonly available on Linux; macOS's default date has different options:
end=$(openssl x509 -in cert.pem -noout -enddate) || exit 1
end_epoch=$(date -d "${end#notAfter=}" +%s) || exit 1
now_epoch=$(date +%s) || exit 1
printf '%s days\n' "$(( (end_epoch - now_epoch) / 86400 ))"
Integer division truncates toward zero, so use -checkend for threshold decisions rather than treating this rounded display as a precise pass/fail result.
Does a future notAfter date mean the certificate is valid?
It only answers the expiration question. A certificate can still be not yet valid, issued for another hostname, untrusted, revoked, or paired with the wrong key.
See the OpenSSL x509 options.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan