Skip to content

OpenSSL cheat sheet

OpenSSL 3 commands for keys, CSRs, self-signed certificates, checking a live TLS endpoint, format conversion and hashing, each one run before publishing.

By Pushkar Kumar Verified against OpenSSL 3.6.3 Updated

The OpenSSL commands most people need are openssl req to make a CSR or a self-signed certificate, openssl x509 -noout -text to read a certificate, openssl s_client -connect host:443 to see what a server actually sends, openssl pkcs12 to package a key and certificate together, and openssl dgst to hash or sign a file. Everything below is OpenSSL 3 syntax. Every command on this page was run against the version stamped above before it was published.

Start by checking which binary you have: openssl version -a. If it says LibreSSL, some options here will not exist.

Generate keys

CommandWhat it does
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out key.pemAn ECDSA P-256 private key, the usual choice for a new TLS certificate.
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out rsa.pemA 3072-bit RSA key, for systems that still expect RSA.
openssl genpkey -algorithm ED25519 -out ed.pemAn Ed25519 key, for signing.
openssl pkey -in key.pem -pubout -out pub.pemExtract the public key.
openssl pkey -in key.pem -noout -textShow the key’s type, size and parameters.
openssl pkey -in key.pem -aes256 -out key-enc.pemWrite a passphrase-protected copy (it prompts for the passphrase).
openssl pkey -in key-enc.pem -out key-plain.pemRemove the passphrase. Keep the result readable by its owner only.

The OpenSSL docs recommend genpkey over the older per-algorithm commands such as genrsa; it takes the same shape for every key type.

Certificate signing requests

CommandWhat it does
openssl req -new -key key.pem -out req.csr -subj '/CN=example.com' -addext 'subjectAltName=DNS:example.com,DNS:www.example.com'A CSR for an existing key, with the names browsers actually check in the SAN extension.
openssl req -new -newkey rsa:3072 -noenc -keyout new.key -out new.csr -subj '/CN=example.com'A new unencrypted key and its CSR in one step.
openssl req -in req.csr -noout -text -verifyRead a CSR back and check its self-signature.

Self-signed certificates

One command makes a key and a certificate valid for a year, with a SAN for localhost and 127.0.0.1:

bash
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc \
  -keyout key.pem -out cert.pem -days 365 \
  -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost,IP:127.0.0.1'

Modern TLS clients match the host name against the subjectAltName entries, not the CN, so that line is the part that matters. A self-signed certificate is only trusted where you add it to the trust store yourself; use it for development and internal tests, not for a public site.

Read a certificate

CommandWhat it does
openssl x509 -in cert.pem -noout -textEverything: subject, issuer, validity, key, extensions.
openssl x509 -in cert.pem -noout -subject -issuer -datesJust who it is for, who signed it, and when it is valid.
openssl x509 -in cert.pem -noout -enddateOnly the expiry date.
openssl x509 -in cert.pem -noout -ext subjectAltNameOnly the host names and IPs it covers.
openssl x509 -in cert.pem -noout -fingerprint -sha256SHA-256 fingerprint, for pinning or comparing.
openssl x509 -in cert.pem -noout -serialSerial number, which is what revocation lists refer to.
openssl x509 -in cert.pem -noout -checkend 2592000Exit status 0 if it is still valid 30 days (2,592,000 seconds) from now, non-zero if not.

To check that a key and a certificate belong together, compare their public keys. No output from diff means they match:

bash
diff <(openssl x509 -in cert.pem -noout -pubkey) <(openssl pkey -in key.pem -pubout)

Prefer a browser view? The Certificate Decoder reads a PEM chain, checks the order and verifies each signature without uploading anything.

Test a live TLS endpoint

CommandWhat it does
openssl s_client -connect example.com:443 </dev/nullHandshake and print the certificate, chain and session. </dev/null makes it exit instead of waiting for input.
openssl s_client -connect example.com:443 -brief </dev/nullOnly the protocol, cipher and verification result.
openssl s_client -connect example.com:443 -showcerts </dev/nullEvery certificate the server sent, in the order it sent them.
openssl s_client -connect 203.0.113.10:443 -servername example.com </dev/nullConnect by IP but ask for a specific host’s certificate (SNI).
openssl s_client -connect example.com:443 -tls1_3 </dev/nullOnly offer TLS 1.3, to test whether the server supports it.
openssl s_client -connect example.com:443 -alpn h2 </dev/nullOffer HTTP/2 through ALPN and show what the server picked.
openssl s_client -connect example.com:443 -verify_return_error </dev/nullClose the connection when verification fails instead of carrying on.
openssl s_client -connect mail.example.com:587 -starttls smtp </dev/nullUpgrade a plain SMTP session with STARTTLS, then show the certificate. Also works with imap, pop3, ftp and others.

Expiry of a live certificate, in one line:

bash
openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -enddate

Verify a chain

CommandWhat it does
openssl verify -CAfile root.pem -untrusted intermediate.pem cert.pemCheck that cert.pem chains to root.pem through the intermediate.
openssl verify -show_chain -CAfile root.pem -untrusted intermediate.pem cert.pemSame, and print the chain that was built.

Convert between formats

CommandWhat it does
openssl x509 -in cert.pem -outform DER -out cert.derPEM (Base64 text) to DER (binary).
openssl x509 -inform DER -in cert.der -out cert.pemDER back to PEM.
openssl pkcs12 -export -inkey key.pem -in cert.pem -certfile chain.pem -out bundle.p12Key, certificate and chain in one password-protected .p12/.pfx file.
openssl pkcs12 -export -legacy -inkey key.pem -in cert.pem -out legacy.p12The same in legacy mode, for older software that cannot read the default AES-256-CBC encryption.
openssl pkcs12 -in bundle.p12 -noenc -out all.pemUnpack a .p12 to PEM with the key unencrypted.
openssl pkcs12 -in bundle.p12 -nokeys -clcerts -out cert.pemOnly the leaf certificate.

Hash, sign and encrypt files

CommandWhat it does
openssl dgst -sha256 file.tar.gzSHA-256 digest of a file. Add -r for sha256sum-style output.
openssl dgst -sha256 -hmac 'secret' payload.jsonHMAC-SHA256 with a shared key, as webhook signatures use.
openssl dgst -sha256 -sign rsa.pem -out sig.bin file.tar.gzSign a file with a private key.
openssl dgst -sha256 -verify pub.pem -signature sig.bin file.tar.gzCheck that signature with the public key; prints Verified OK.
openssl rand -hex 3232 random bytes as hex, for a token or secret.
openssl rand -base64 32The same as Base64.
openssl enc -aes-256-cbc -pbkdf2 -salt -in notes.txt -out notes.encEncrypt a file with a passphrase.
openssl enc -d -aes-256-cbc -pbkdf2 -in notes.enc -out notes.txtDecrypt it; the options must match.
openssl base64 -in file.bin -out file.b64Base64-encode; add -d to decode.
openssl passwd -6A SHA-512 crypt hash for /etc/shadow or cloud-init; it prompts for the password.

To hash a quick string without a terminal, the Hash Generator computes MD5, SHA-1, SHA-256, SHA-512 and HMAC in the browser.

Gotchas

Gotcha: -nodes (“no DES”) is deprecated since OpenSSL 3.0. Use -noenc. Both leave the private key unencrypted, so protect the file with permissions.

Gotcha: -showcerts prints what the server sent, not a verified chain. A missing intermediate shows up as a short list here and as a verification error in the summary.

Gotcha: SNI is sent automatically when -connect names a host. Connect by IP address and you get the server’s default certificate unless you add -servername.

Gotcha: -out overwrites an existing file without asking. Writing a new key over the only copy of a key in use breaks the certificate that belongs to it.

Gotcha: openssl enc cannot do authenticated modes such as GCM, and it never will. For anything beyond a quick passphrase-protected file, use openssl cms or a dedicated tool like age.

Go deeper: the Networking for DevOps guide covers how TLS fits into DNS, ports and load balancers. Moving keys around in containers? See the Docker cheat sheet.

Sources

Every command above was checked against these official references and against OpenSSL 3.6.3.

All cheat sheets

FAQ

Questions, answered.

Tap a question to expand the answer.

Use -noenc. Both write the private key without a passphrase, but -nodes has been deprecated since OpenSSL 3.0. It still works, so old scripts keep running, but new ones should use -noenc.

Pipe s_client into x509: openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -enddate. For a script, use -checkend with a number of seconds instead: it exits non-zero if the certificate expires within that window.

macOS ships LibreSSL as /usr/bin/openssl, which accepts a different set of options from OpenSSL 3. Run openssl version; if it says LibreSSL, install OpenSSL (for example with Homebrew) and call that binary by its full path.