⌨️ Daily Life Commands — the SSL cheat sheet
Updated 28 August 2026
Not everything the track covered — the ones you will actually reach for. Grouped by what you are trying to do, because that is how you will look for them: not "what does x509 do" but "how do I find out when this expires".
⭐ marks the genuinely daily ones. If you learn only those, you will handle most of what comes up.
🔍 Look at something
A certificate on disk
openssl x509 -in cert.pem -noout -text # ⭐ everything, readable
openssl x509 -in cert.pem -noout -subject -issuer -dates # ⭐ the four facts you usually want
openssl x509 -in cert.pem -noout -enddate # ⭐ just: when does this die?
openssl x509 -in cert.pem -noout -ext subjectAltName # ⭐ which names is it valid for?
openssl x509 -in cert.pem -noout -serial -fingerprint -sha256
openssl x509 -in cert.pem -noout -purpose # what is it allowed to do?
openssl x509 -in cert.pem -noout -subject -nameopt RFC2253 # the DN as a proxy will see itThe other file types
openssl req -in request.csr -noout -text # ⭐ read a CSR
openssl crl -in ca.crl -noout -text # read a CRL
openssl crl -in ca.crl -noout -lastupdate -nextupdate # ⭐ is this CRL still fresh?
openssl pkey -in key.pem -noout -text # read a private key
openssl pkcs12 -in bundle.p12 -info -noout # what is inside a .p12?
openssl asn1parse -in cert.pem # the raw ASN.1, when desperateA live server
echo | openssl s_client -connect host:443 -servername host -verify_hostname host # ⭐ the full check
echo | openssl s_client -connect host:443 -servername host 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates # ⭐ the cert it actually served
echo | openssl s_client -connect host:443 -servername host 2>/dev/null \
| sed -n '/Certificate chain/,/^---/p' # ⭐ what did it send, in order?
echo | openssl s_client -connect host:443 -servername host 2>/dev/null \
| grep -m1 "Verify return code" # ⭐ the numbered verdict
echo | openssl s_client -connect host:443 -servername host -showcerts 2>/dev/null🔨 Make something
Keys
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out key.pem # ⭐ RSA
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out key.pem # ⭐ ECDSA, smaller+faster
openssl pkey -in key.pem -pubout -out pub.pem # just the public halfA CSR
openssl req -new -key key.pem -out req.csr -subj "/CN=example.com" # ⭐
# with SANs, in one command, no config file
openssl req -new -key key.pem -out req.csr -subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com" # ⭐A self-signed certificate, for a quick test
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem \
-days 90 -subj "/CN=test.local" -addext "subjectAltName=DNS:test.local" # ⭐ one commandA CA, and issuing from it
# the CA
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ca.key
openssl req -x509 -new -key ca.key -sha256 -days 3650 -out ca.crt -subj "/CN=My CA" \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign" # ⭐
# the extensions the certificate will get (a CSR's own extensions are IGNORED)
cat > ext.cnf <<'EOF'
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=DNS:example.com
EOF
openssl x509 -req -in req.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-days 90 -sha256 -extfile ext.cnf -out cert.crt # ⭐Without it, openssl x509 -req produces a certificate with no SAN, no EKU and no basicConstraints — and openssl verify will still say OK, because it does not check hostnames. It will fail in every browser.
Whatever a CSR asks for, the issuer decides the extensions. That is deliberate: otherwise anyone could request CA:TRUE.
✅ Check that something is right
openssl verify -CAfile ca.crt cert.crt # ⭐ does the chain verify?
openssl verify -CAfile root.crt -untrusted int.crt cert.crt # ⭐ with an intermediate
openssl verify -CAfile ca.crt -purpose sslclient cert.crt # valid for CLIENT auth?
openssl verify -CApath ./mystore cert.crt # against a hashed directory
# does this key belong to this certificate? compare the two hashes
openssl x509 -in cert.crt -noout -pubkey | openssl sha256 # ⭐
openssl pkey -in key.pem -pubout | openssl sha256 # ⭐
# did a rotation actually rotate the KEY, or only reissue the certificate?
openssl x509 -in old.crt -noout -pubkey | openssl sha256 # ⭐ same hash = key NOT rotated
openssl x509 -in new.crt -noout -pubkey | openssl sha256🔄 Convert between formats
openssl x509 -in cert.der -inform der -out cert.pem # ⭐ DER → PEM
openssl x509 -in cert.pem -outform der -out cert.der # PEM → DER
openssl pkcs12 -export -out bundle.p12 -inkey key.pem -in cert.pem \
-certfile chain.pem # ⭐ → PKCS#12 (Java, Windows)
openssl pkcs12 -in bundle.p12 -nokeys -out certs.pem # ← certificates out
openssl pkcs12 -in bundle.p12 -nocerts -nodes -out key.pem # ← key out
openssl pkcs8 -topk8 -in key.pem -out key-pkcs8.pem -nocrypt # PKCS#1 → PKCS#8
cat leaf.crt intermediate.crt > fullchain.pem # ⭐ leaf FIRST, no root🚨 Something is broken
# 1. what is broken? ten seconds, right most of the time
curl -sS https://host/ 2>&1 | head -1
# 2. the verdict and the chain together
echo | openssl s_client -connect host:443 -servername host -verify_hostname host 2>/dev/null \
| grep -E "Verify return code|^ [0-9] s:|^ i:"
# 3. the certificate you actually received
echo | openssl s_client -connect host:443 -servername host 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
# 4. what does the SERVER's log say? the client only ever sees a summary
tail -50 /var/log/nginx/error.log | grep -i sslThe verify codes, and what each one means for you
| Code | Meaning | What to do |
|---|---|---|
| 0 | ok | Not a certificate problem. Look elsewhere |
| 10 | certificate has expired | Check the whole chain — it may be the intermediate |
| 18 | self-signed certificate | A test certificate reached a real environment |
| 19 | self-signed certificate in chain | The server is sending the root. Strip it from fullchain.pem |
| 20 | unable to get local issuer certificate | Your trust store. Missing internal root, or no ca-certificates |
| 21 | unable to verify the first certificate | Their server. It did not send the intermediate |
| 23 | certificate revoked | It is on the CRL |
| 26 | unsuitable certificate purpose | Wrong EKU — a serverAuth certificate used as a client |
| 34 | unhandled critical extension | Often a CT precertificate. Not meant to be used |
| 47 | permitted subtree violation | A name constraint refused that name |
| 62 | hostname mismatch | No SAN covers the name you asked for |
Decoding the other kind of error number
openssl errstr 05800074 # ⭐ error:05800074:x509 routines::key values mismatch
openssl errstr 0A000086 # error:0A000086:SSL routines::certificate verify failed🌐 DNS, CAA and Certificate Transparency
dig +short CAA example.com # ⭐ who may issue for this domain?
dig CAA example.com +noall +answer # ⭐ with TTLs, for change work
dig +short CAA example.com @1.1.1.1 # from a specific resolver
dig +short CAA example.com @ns1.example.com # ⭐ straight from the authoritative server
# every certificate ever issued for a domain, from the CT logs
curl -s 'https://crt.sh/?q=%25.example.com&output=json&exclude=expired' \
| python3 -c 'import json,sys; [print(n) for r in json.load(sys.stdin)
for n in r["name_value"].splitlines()]' | sort -u # ⭐
openssl x509 -in cert.pem -noout -ext ct_precert_scts # ⭐ the SCTs, if any🖥️ Servers
nginx
nginx -t -c /path/nginx.conf # ⭐ ALWAYS test before reloading
nginx -s reload -c /path/nginx.conf # ⭐ pick up new certificates, no dropped connections
nginx -s stop -c /path/nginx.conf
grep -rn "mycert" /etc/nginx/ # ⭐ EVERY place a file is referencedssl_certificate /path/fullchain.pem; # leaf + intermediates, never the root
ssl_certificate_key /path/privkey.pem;
ssl_client_certificate /path/client-ca.crt; # mTLS: who may sign client certificates
ssl_verify_client on; # DEFAULT IS off
ssl_verify_depth 2; # DEFAULT IS 1 (Apache defaults to 10)
ssl_crl /path/client-ca.crl; # re-read only on reloadApache
apachectl configtest # ⭐ the equivalent of nginx -t
apachectl graceful # ⭐ reload without dropping connectionsA throwaway TLS server, for testing
openssl s_server -accept 4433 -cert cert.pem -key key.pem -www # ⭐
openssl s_server -accept 4433 -cert cert.pem -key key.pem \
-CAfile client-ca.crt -Verify 1 -verify_return_error -www # ⭐ mTLS🤝 Client certificates and mTLS
curl --cacert server-ca.crt --cert client.crt --key client.key https://host/ # ⭐
cat client.crt client-int.crt > client-chain.crt # ⭐ clients send chains too
openssl verify -CAfile client-ca.crt -purpose sslclient client.crt # ⭐ would a server accept it?
openssl x509 -in client.crt -noout -subject -nameopt RFC2253 # ⭐ the string nginx will see
echo | openssl s_client -connect host:443 2>&1 \
| sed -n '/Acceptable client certificate CA names/,/Peer signing/p' # ⭐ which CA does it want?📅 Expiry and renewal
# days left on a live endpoint
end=$(echo | openssl s_client -connect host:443 -servername host 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
echo $(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 )) days # ⭐
certbot certificates # ⭐ what certbot manages, and when each expires
certbot renew --dry-run # ⭐ will renewal work? run this BEFORE it matters
certbot renew --force-renewal # renew now regardless
systemctl list-timers | grep certbot # is the renewal timer actually running?🔎 Scanners
sslscan --no-colour --sni-name=host host:443 # ⭐ what WOULD it accept?
testssl.sh -S --add-ca internal-root.crt host:443 # ⭐ certificate and chain, fast
testssl.sh -U host:443 # every named vulnerability
testssl.sh --ip 10.0.0.7 www.example.com:443 # ⭐ audit ONE node behind a load balancer
testssl.sh --add-ca internal-root.crt host:443 | tail -20 # ⭐ an SSL Labs-style grade, locally🧹 Clean up the lab
pgrep -f 'openssl s_server' | xargs -r kill # stop any test servers
nginx -s stop -c ~/tls-lab/*/nginx.conf 2>/dev/null
rm -rf ~/tls-lab # remove every file this track createdcurl -sS https://host/ 2>&1 | head -1 # what is broken?
echo | openssl s_client -connect host:443 -servername host -verify_hostname host
openssl x509 -in cert.pem -noout -subject -issuer -dates -ext subjectAltName
openssl x509 -in cert.pem -noout -pubkey | openssl sha256 # does the key match?
nginx -t && nginx -s reload # test, THEN reloadThey cover triage, inspection, verification and safe change — which is most of the job.