OpenSSL commands cheatsheet for TLS work
The OpenSSL commands worth keeping for certificate inspection, CSRs, private keys, chains, fingerprints, expiry checks, and TLS handshake debugging.
Control Plane Labs Staff
Published August 3, 2026
OpenSSL is most useful when you want to separate a certificate problem from an application problem. A browser hides many details: it follows redirects, chooses an SNI name, builds a trust path, and may reuse a session. The commands here make those choices visible. They follow the OpenSSL 3 command documentation and the certificate profile in RFC 5280.
Run commands with a copy of the certificate or key that you are allowed to inspect. Private keys are secrets. Never paste them into a ticket, shell transcript, or online decoder.
Inspect a certificate file
The first command turns a PEM certificate into readable fields:
openssl x509 -in fullchain.pem -noout -text
The fields that matter most are:
openssl x509 -in cert.pem -noout \
-subject -issuer -serial -dates -fingerprint -sha256
openssl x509 -in cert.pem -noout -ext subjectAltName
The subject is the certificate’s distinguished name; the names a browser
matches are normally in subjectAltName, not the old Common Name field. Check
the SAN list before diagnosing a hostname mismatch. notBefore and notAfter
are expressed in UTC. A certificate can be structurally valid and still be
unusable because the current time is outside that interval.
To print only the expiry date in a monitoring job:
openssl x509 -in cert.pem -noout -enddate
The output is text such as notAfter=Aug 31 23:59:59 2026 GMT. Convert it with
the date tools available on your platform, but keep the original UTC value in
the alert. Do not alert only on a certificate’s file modification time; a
renewal process can replace a file without changing the certificate that a
server has loaded.
For a quick fingerprint comparison:
openssl x509 -in cert.pem -noout -fingerprint -sha256
Fingerprints identify the exact certificate bytes. They do not prove that a certificate is trusted, that its key is private, or that the server is presenting it for the right hostname. For those questions, inspect the SANs, chain, signature, and TLS handshake separately.
Inspect a live TLS endpoint
SNI is essential when a server hosts several names on one IP address:
openssl s_client \
-connect www.example.com:443 \
-servername www.example.com \
-showcerts </dev/null
-connect selects the socket. -servername sends the hostname in the TLS
Server Name Indication extension, which lets the server choose the right
certificate. -showcerts prints the certificates the server sent. The
OpenSSL s_client manual
lists the other handshake options and explains that the command is a test
client, not a complete certificate-policy checker.
Save the leaf certificate from the output and inspect it:
openssl s_client -connect www.example.com:443 \
-servername www.example.com -showcerts </dev/null 2>/dev/null |
awk '/BEGIN CERTIFICATE/{n++} n==1{print} /END CERTIFICATE/{if(n==1) exit}' |
openssl x509 -noout -subject -issuer -dates -ext subjectAltName
For a verification attempt against the system trust store:
openssl s_client \
-connect www.example.com:443 \
-servername www.example.com \
-verify_return_error </dev/null
The final Verify return code matters. A successful TLS handshake alone does
not prove that the chain is trusted: s_client can continue after some
verification errors unless -verify_return_error is set. Compare this result
with a client that uses the same trust store as production.
Read a chain and verify it explicitly
A server normally sends the leaf and one or more intermediates. It should not send the root; clients already carry roots in their trust stores. Split a PEM bundle into individual certificates when you need to see the order:
awk 'BEGIN {n=0} /BEGIN CERTIFICATE/ {n++} n {print > ("cert-" n ".pem")} /END CERTIFICATE/ {close("cert-" n ".pem")}' fullchain.pem
for cert in cert-*.pem; do
echo "== $cert =="
openssl x509 -in "$cert" -noout -subject -issuer -dates
done
The issuer of one certificate should identify the signer of the next certificate in the path. That relationship alone is not enough: signature verification, validity periods, key usage, name constraints, and trust-anchor selection also matter. The OpenSSL verify documentation describes path validation and its trust-store options.
If you have a leaf and an intermediate bundle, verify the leaf against the intermediate:
openssl verify \
-CAfile intermediate.pem \
-purpose sslserver \
-verify_hostname www.example.com \
cert.pem
For a private internal root, provide the root as the trust anchor and the intermediate as an untrusted chain:
openssl verify \
-CAfile internal-root.pem \
-untrusted intermediate.pem \
-purpose sslserver \
-verify_hostname service.internal.example \
leaf.pem
Do not add a downloaded certificate to the system trust store just to make a test pass. That hides the distinction between a missing intermediate, an untrusted root, and a hostname mismatch. Keep test trust material in a temporary file and remove it after the check.
Compare a private key, CSR, and certificate
A certificate does not contain the private key. You can compare public-key material without printing the secret:
openssl pkey -in server.key -pubout -outform pem | openssl sha256
openssl req -in server.csr -pubkey -noout | openssl sha256
openssl x509 -in server.crt -pubkey -noout | openssl sha256
The three digests should match when the key, CSR, and certificate belong
together. Older guides often compare RSA moduli with openssl rsa -modulus;
the public-key method also works for modern key types. Protect the first
command’s input file with normal filesystem permissions. The
OpenSSL pkey manual
documents the key-format and public-output options.
Create a private key with an explicit algorithm and inspect its public parameters:
openssl genpkey -algorithm RSA \
-pkeyopt rsa_keygen_bits:2048 \
-out server.key
chmod 600 server.key
openssl pkey -in server.key -text_pub -noout
Create a certificate signing request with SANs. The extension must be present in the CSR if the CA or issuance workflow copies requested extensions:
openssl req -new -key server.key -out server.csr \
-subj "/CN=www.example.com" \
-addext "subjectAltName=DNS:www.example.com,DNS:example.com"
openssl req -in server.csr -noout -text
A CSR proves possession of the private key corresponding to its public key; it does not prove ownership of a domain. The CA still performs its own authorization checks. Never include a private key in a CSR or send it to a CA.
Test protocol and cipher negotiation
Pin a protocol version when isolating a compatibility problem:
openssl s_client -connect www.example.com:443 \
-servername www.example.com -tls1_2 </dev/null
openssl s_client -connect www.example.com:443 \
-servername www.example.com -tls1_3 </dev/null
The negotiated protocol and cipher appear in the handshake summary. A failure
with one version does not tell you whether the server, client, certificate, or
middlebox is at fault, so compare the two runs and record the exact error.
Use -alpn h2,http/1.1 when checking application protocol negotiation:
openssl s_client -connect www.example.com:443 \
-servername www.example.com -alpn h2,http/1.1 </dev/null 2>/dev/null |
grep -E 'Protocol|Cipher|ALPN|Verify return'
s_client is intentionally low-level. It can complete a handshake even when a
browser would reject the endpoint for policy or hostname reasons. Pair it with
the TLS certificate inspector and the
certificate transparency lookup when you need to compare
the live certificate with issuance history.
PKCS#12 and safe conversion
PKCS#12 files commonly end in .p12 or .pfx and may contain a certificate,
private key, and chain. List the contents without exporting the key:
openssl pkcs12 -in bundle.p12 -info -noout
Export a certificate only:
openssl pkcs12 -in bundle.p12 -clcerts -nokeys -out cert.pem
Export the private key only when a migration requires it, then restrict and remove the output:
umask 077
openssl pkcs12 -in bundle.p12 -nocerts -nodes -out server.key
chmod 600 server.key
-nodes means the exported key is not encrypted at rest. It is convenient for
automation and dangerous on a shared filesystem. Prefer an encrypted key when
the receiving service supports it, and pass passwords through a secret
manager rather than a shell argument. The
OpenSSL pkcs12 manual
describes the import and export modes.
Read next
- Inspect a certificate in the browser with the TLS certificate inspector.
- Read How to read a TLS certificate.
- Check a hostname’s Certificate Transparency history.
Frequently asked questions
Why must I pass -servername to openssl s_client?+
Does a successful s_client handshake prove the certificate is valid?+
Should a server send the root certificate?+
How do I know whether a CSR matches a certificate?+
Is it safe to paste a private key into an online checker?+
Tags: #openssl, #tls, #certificates, #security, #cheatsheet