How-to guide · Inspect and check

How to inspect a certificate with OpenSSL

In one sentence

You will have read a certificate file or a server's certificate with OpenSSL and found its names, dates, issuer, key and fingerprint.

Task
Inspect and check
Platforms
  • Linux
  • macOS
  • Windows
  • Java
Who it is for
Level
Beginner · 5 steps
On this page
  1. Before you start
  2. Steps
  3. 1. Find out what kind of file you have
  4. 2. Print the whole certificate
  5. 3. Ask one question at a time
  6. 4. Inspect the certificate a server sends
  7. 5. Inspect every certificate in a bundle file
  8. Windows and Java alternatives
  9. Check it worked
  10. If something goes wrong
  11. Why this works
  12. Go deeper

Before you start

  • OpenSSL 1.1.1 or later, ideally 3.x. Linux distributions include it, Git for Windows ships it inside Git Bash, and on macOS you can install it with Homebrew. The openssl that comes with macOS is LibreSSL, whose options and output can differ.
  • The certificate, as a file (.crt, .cer, .pem, .der) or as a server name such as www.example.com.
  • Nothing secret. A certificate is public, so you can read it anywhere. Its private key is not: never paste a key into a website or a ticket.

Most certificate problems (a missing name, an expired date, the wrong issuer) are visible in 30 seconds once you know which line to read.

Steps

1. Find out what kind of file you have

Look at the first line:

head -1 www.crt
-----BEGIN CERTIFICATE-----
  • -----BEGIN CERTIFICATE-----: a PEM certificate. Go to step 2.
  • Unreadable binary: probably DER. Step 2 works too; add -inform DER on OpenSSL 1.1.1.
  • -----BEGIN PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY-----: this is a key, not a certificate. Keep it to yourself.
  • -----BEGIN CERTIFICATE REQUEST-----: a CSR. Read it with openssl req -in file -noout -text.
  • A .pfx or .p12 file: a password-protected bundle. Extract the certificate first with How to convert PFX to PEM.

The file formats appendix explains every label.

2. Print the whole certificate

openssl x509 -in www.crt -noout -text -certopt no_pubkey,no_sigdump

-noout stops OpenSSL from printing the PEM block again, and -certopt no_pubkey,no_sigdump hides the long hex dumps of the key and signature. Here is our test certificate, issued by a private test CA:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            1c:2a:d3:7b:ba:ee:4f:c8:60:76:fa:37:3b:e4:fc:a5:50:c6:2c:a7
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
        Validity
            Not Before: Oct 20 01:42:24 2026 GMT
            Not After : Jan 18 01:42:24 2027 GMT
        Subject: C=BE, O=Example Shop, CN=www.example.com
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Alternative Name: 
                DNS:www.example.com, DNS:example.com
            X509v3 Subject Key Identifier: 
                F5:0F:A7:10:9F:72:62:B2:CE:A6:F6:68:BB:6B:90:9E:94:FA:8F:12
            X509v3 Authority Key Identifier: 
                D4:01:6F:B3:7A:51:AE:4E:B3:A9:1C:AF:B1:1D:6C:40:6A:B7:77:8C
            Authority Information Access: 
                CA Issuers - URI:http://pki.example.com/issuing-ca-1.cer

Read it with these questions in mind:

Line The question it answers
Subject Alternative Name Which host names is it valid for? Clients match the name here.
Validity When does it start and end? Times are in GMT.
Issuer Which CA signed it? Must match the subject of the next certificate in the chain.
Basic Constraints Is it a CA (CA:TRUE) or an end-entity certificate (CA:FALSE)?
Key Usage, Extended Key Usage What may the key do? A web server needs TLS Web Server Authentication.
Authority Key Identifier Links to the issuer’s Subject Key Identifier.
Authority Information Access Where to download the issuer’s certificate (and, for some CAs, the OCSP address).

The Subject Alternative Name (SAN) is the line that matters most. The CN in the subject is not used for host names by modern clients: Chrome ignores the Common Name and requires the hostname in the Subject Alternative Name (since Chrome 58 (April 2017)).

3. Ask one question at a time

For scripts and quick checks, print only the fields you need:

openssl x509 -in www.crt -noout -subject -issuer -dates -serial
openssl x509 -in www.crt -noout -ext subjectAltName,keyUsage,extendedKeyUsage
openssl x509 -in www.crt -noout -fingerprint -sha256
subject=C=BE, O=Example Shop, CN=www.example.com
issuer=C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
notBefore=Oct 20 01:42:24 2026 GMT
notAfter=Jan 18 01:42:24 2027 GMT
serial=1C2AD37BBAEE4FC86076FA373BE4FCA550C62CA7
X509v3 Key Usage: critical
    Digital Signature, Key Encipherment
X509v3 Extended Key Usage: 
    TLS Web Server Authentication
X509v3 Subject Alternative Name: 
    DNS:www.example.com, DNS:example.com
sha256 Fingerprint=67:E1:E5:8B:37:05:E5:60:D5:61:B0:68:B2:A9:29:BF:87:15:FB:B1:22:F6:C8:01:8E:3A:22:2E:59:34:0C:7D

-ext needs OpenSSL 1.1.1 or later. Name formatting differs between versions: OpenSSL 3.0 prints C = BE, O = Example Shop with spaces, while the 3.2 build used here prints them compactly, as above. Add -nameopt RFC2253 if a script needs one stable format.

The fingerprint is not stored in the certificate. OpenSSL computes it as a SHA-256 hash of the whole DER encoding, so it identifies exactly this certificate.

4. Inspect the certificate a server sends

Pipe openssl s_client into openssl x509:

openssl s_client -connect letsencrypt.org:443 -servername letsencrypt.org </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
subject=CN=letsencrypt.org
issuer=C=US, O=Let's Encrypt, CN=YE2
notBefore=Sep  4 14:34:32 2026 GMT
notAfter=Dec  3 14:34:31 2026 GMT
X509v3 Subject Alternative Name: 
    DNS:cp.letsencrypt.org, DNS:cp.root-x1.letsencrypt.org, DNS:cps.letsencrypt.org, DNS:cps.root-x1.letsencrypt.org, DNS:lencr.org, DNS:letsencrypt.com, DNS:letsencrypt.org, DNS:www.lencr.org, DNS:www.letsencrypt.com, DNS:www.letsencrypt.org

That was the live certificate on 20 October 2026. Three details matter:

  • -servername sends the name in SNI, so a server that hosts many sites returns the right certificate. OpenSSL 1.1.1 and later send the -connect host name automatically, but you need -servername when you connect to an IP address or a load balancer by another name.
  • </dev/null closes the connection straight away. Without it, s_client waits for you to type.
  • openssl x509 reads only the first certificate, which is the server’s own. To see the intermediates as well, follow How to check the certificate chain a server sends.

5. Inspect every certificate in a bundle file

A fullchain.pem holds several certificates, and openssl x509 silently shows only the first. List them all:

openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout
subject=C=BE, O=Example Shop, CN=www.example.com
issuer=C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1

subject=C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
issuer=C=BE, O=Keystone Demo, CN=Keystone Demo Root CA

Each issuer should be the subject of the next certificate down.

Windows and Java alternatives

Without OpenSSL, Windows has certutil, and every JDK has keytool:

certutil -dump www.crt
 NotBefore: 2026-10-20 3:42 AM
 NotAfter: 2027-01-18 3:42 AM
keytool -printcert -file www.crt
keytool -printcert -sslserver letsencrypt.org:443
Owner: CN=www.example.com, O=Example Shop, C=BE
Issuer: CN=Keystone Demo Issuing CA 1, O=Keystone Demo, C=BE
Serial number: 1c2ad37bbaee4fc86076fa373be4fca550c62ca7
Valid from: Tue Oct 20 03:42:24 CEST 2026 until: Mon Jan 18 02:42:24 CET 2027

Both show local time, while OpenSSL shows GMT: the same certificate reads 01:42 in OpenSSL and 03:42 in Brussels. keytool -printcert -sslserver prints every certificate the server sends, with its SHA-256 fingerprint.

Check it worked

Confirm you read the right certificate in two ways. First, ask OpenSSL whether the name you care about is covered:

openssl x509 -in www.crt -noout -checkhost www.example.com
openssl x509 -in www.crt -noout -checkhost shop.example.com
Hostname www.example.com does match certificate
Hostname shop.example.com does NOT match certificate

Then compare the fingerprint of your file with the one the server presents. If they are equal, the server runs exactly the certificate you inspected:

openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256

You can also paste a PEM certificate into the decoder below. It runs in your browser and accepts certificates only, never keys.

Try it: Certificate decoderOpen the full tool

Runs in your browser. Nothing you paste is sent anywhere.

PEM text, several PEM blocks, or a .pem, .crt, .cer or .der file (drop it on the box). Certificates are public, so they are safe to paste.

If something goes wrong

  • Could not read certificate from www.key (OpenSSL 3.0) or Could not find certificate from … (3.2): the file is not a certificate. It is usually a key, a CSR or a PFX. Check the first line again (step 1).
  • unable to load certificate on OpenSSL 1.1.1 with a binary file: add -inform DER, or convert it to PEM.
  • s_client hangs: add </dev/null, or press Ctrl+C.
  • The server shows a different certificate from the one you expect: check -servername, and check that the name resolves to the server you think. A wrong default certificate causes NET::ERR_CERT_COMMON_NAME_INVALID and Python’s hostname mismatch.
  • notAfter is in the past: clients will fail with certificate has expired. See How to check when a certificate expires.
  • You only see one certificate in a bundle: that is openssl x509 reading the first one. Use step 5.

Why this works

A certificate is a signed data structure defined in RFC 5280: a list of fields and extensions, followed by the CA’s signature over them. It is stored as DER bytes, and PEM is the same bytes in Base64 between BEGIN and END lines (RFC 7468). openssl x509 decodes that structure into text, so what you read is exactly what every client reads. Anatomy of an X.509 certificate explains each field, and Names and jobs explains SANs, key usage and the CA flag. Hashes and fingerprints explains why a fingerprint identifies a certificate.

Go deeper

Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.

Last reviewed Edition 0.9