Cheat Sheet

OpenSSL Commands Cheat Sheet

OpenSSL is the command line toolkit behind most TLS work on Linux, macOS, and Windows (it ships with Git for Windows). This sheet covers the openssl commands you actually type: reading and checking certificates, generating keys and CSRs, converting between PEM, DER, and PFX, and the odd hashing and encryption jobs.

Last updated August 29, 2026

Inspect a Certificate

stops OpenSSL echoing the PEM block after the fields you asked for. For a paste-and-read version, use the certificate decoder.

CommandWhat it does
Print everything: subject, issuer, validity, SANs, key type, extensions
Just the notBefore and notAfter lines
Expiry date only
Exit 1 if it expires within 30 days (value is seconds), for scripts
Who the certificate is for ( for who signed it)
The DNS names it covers
Serial number
SHA-256 fingerprint ( for the old style)
Extract the public key as PEM
Read a binary DER file ( from Windows is often DER)
What the certificate may be used for (server, client, CA)

Read every certificate in a chain file, not just the first:

openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout

Check a Live Server

opens a TLS connection and prints the handshake. Always pass (SNI), or a host serving several sites hands you the default certificate instead of the one you wanted. The closes the session instead of leaving it waiting for input. The SSL checker runs the same check from a browser.

CommandWhat it does
Handshake, certificate, chain, and cipher for a site
Print every certificate the server sends, in PEM
Test a STARTTLS service (, , , , , also work)
Force one protocol version (, or to exclude)
Verify against a specific CA bundle (internal CAs)
Fail the connection on a verify error instead of continuing
Test a server by IP before DNS changes, with the right SNI
Check HTTP/2 negotiation

Print just the dates or the subject of the live certificate:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer

Save the live certificate to a file:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -out example.pem

Look for at the bottom of the output. means the server is not sending its intermediate. shows the same verdict in fewer lines; see the curl cheat sheet.

Generate Keys

is the current all-purpose generator. still works in OpenSSL 3 and is not going anywhere soon. For SSH login keys, use instead, or the SSH key generator.

CommandWhat it does
RSA 4096 private key
Same thing, older syntax
ECDSA P-256 key (smaller, faster, fine for TLS)
Same EC key, older syntax
Ed25519 key
RSA key encrypted with a passphrase
Extract the public key
Print the key details ( and also work)
Verify an RSA key is internally consistent
Remove the passphrase from a key
Add a passphrase to a key
Rewrite a PKCS#8 as for old software

PuTTY cannot read these keys directly. The PEM to PPK converter and PPK to PEM converter go both ways.

Create a CSR

A certificate signing request is what you send to a CA. Set the subject with so it does not prompt, and put every hostname in a SAN, because browsers ignore the CN.

CommandWhat it does
CSR from an existing key
New key and CSR in one go (prompts for the subject)
Read a CSR
Just the subject
Check the CSR signature
Extract the public key

With SANs, which every public CA now requires:

openssl req -new -key key.pem -out req.csr \
  -subj "/CN=example.com/O=Example Ltd/C=US" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com"

needs OpenSSL 1.1.1 or newer. On older builds, put the SANs in a config file and pass .

Self-Signed Certificate

For local development, internal services, and anything that will never face a public browser.

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \
  -subj "/CN=example.com" -addext "subjectAltName=DNS:example.com,DNS:localhost,IP:127.0.0.1"
CommandWhat it does
Key plus self-signed certificate, no passphrase, one year
Self-sign with a key you already have
Self-sign an existing CSR
Same with an EC key

means "no DES", that is, do not encrypt the key. OpenSSL 3 spells it and still accepts .

Convert Formats

The extension tells you very little. , , , and are usually PEM (text starting with ), and sometimes are binary DER, and and are PKCS#12 bundles. Run before converting.

CommandWhat it does
PEM certificate to DER
DER certificate to PEM
PEM key to DER
DER key to PEM
Key, certificate, and chain to PFX (prompts for an export password)
CRT plus KEY to PFX, no chain
PFX without the password prompt (scripts)
PFX to PEM, key and certificates in one file, key unencrypted
Only the private key from a PFX
Only the server certificate from a PFX
Only the CA chain from a PFX
List what a PFX contains
PEM to PKCS#7 (, what Windows and Tomcat sometimes ask for)
PKCS#7 to PEM
Binary PKCS#7 to PEM
Traditional key to PKCS#8 (Java, some Node libraries)

If OpenSSL 3 refuses an old PFX with or , the file uses RC2 or 40-bit ciphers; add . The same flag on makes a PFX that old Windows Server and Java 8 can import.

openssl pkcs12 -in old.pfx -out cert.pem -nodes -legacy
openssl pkcs12 -export -legacy -out cert.pfx -inkey key.pem -in cert.pem -certfile chain.pem

Verify Chain and Key Match

CommandWhat it does
Verify a certificate against a chain file (root plus intermediates)
Verify with the intermediate supplied separately
Verify against the system trust store
Print the chain it built
RSA modulus hash of the certificate
RSA modulus hash of the key; must match the line above
RSA modulus hash of a CSR
Public key hash of a certificate (works for EC and Ed25519 too)
Public key hash of a key; must match the line above

Check that a full-chain file is in the right order (leaf first, then each issuer):

openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout

Each certificate's should be the next certificate's .

Create a CA

A private CA for internal hostnames, so you can sign as many certificates as you like and install one root on your machines.

# Root CA (10 years)
openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3650 -nodes \
  -subj "/CN=Example Internal CA"

# CSR for a server, with SANs
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr \
  -subj "/CN=app.internal" -addext "subjectAltName=DNS:app.internal,DNS:app"

# Sign it, keeping the SANs from the CSR (OpenSSL 3)
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -days 825 -copy_extensions copy
CommandWhat it does
Sign a CSR with your CA
Carry the SANs from the CSR into the certificate (OpenSSL 3; on 1.1.1 use )
Confirm the result chains to your CA

Trust the root on a client: on Debian and Ubuntu, on Fedora and RHEL, and Keychain Access on macOS.

Hash, Encrypt, Random

CommandWhat it does
SHA-256 of a file (, , also work)
HMAC-SHA256
Sign a file with a private key
Verify a signature with the public key
Encrypt a file with a passphrase
Decrypt it (same flags plus )
Base64 encode ( decodes; for a single line)
Base64 a string
Random 32 bytes as base64 (session secrets, API keys)
Random 16 bytes as hex
SHA-512 crypt hash for ( for SHA-256, for htpasswd)
Version, build flags, and where it looks for
Ciphers this build supports (, )

Always pass to . Without it OpenSSL derives the key with a single MD5 round and warns you about it. Files encrypted without must be decrypted without it too.

Gotchas

  • Forget and prints the fields you asked for and then the whole PEM block again. Harmless, but it fills the screen.
  • without gets the server's default certificate, which on a shared host is a different site's. Without it sits there waiting for you to type an HTTP request; or ends it. In PowerShell, use since does not exist there.
  • The modulus trick only compares RSA keys. For EC and Ed25519, hash the output instead, as shown above.
  • Chrome, Firefox, and Safari ignore the CN entirely. A certificate without a matching the hostname is rejected even when the CN is right, so always pass .
  • OpenSSL 3 changed a few defaults: uses AES-256 and SHA-256 (old Windows and Java need ), reading an old PFX needs , is now , and is fine but is the documented path. tells you which you have; macOS ships LibreSSL, which lacks and in older releases, so if a flag is missing.
  • , , , and are naming conventions, not formats. When a command says , check and add if the file is binary.
  • A key file from OpenSSL is not a PuTTY , and a is not a PEM. The PEM to PPK and PPK to PEM converters handle both directions.

OpenSSL Cheat Sheet FAQ

What are the most common OpenSSL commands?
Five cover most days. openssl x509 -in cert.pem -text -noout reads a certificate. openssl s_client -connect host:443 -servername host checks what a live server presents. openssl req -new -key key.pem -out req.csr makes a signing request, and the same command with -x509 makes a self-signed certificate. openssl pkcs12 -export bundles a key and certificate into a PFX for Windows or IIS, and openssl pkcs12 -in file.pfx -nodes unpacks one. Everything else on this page is a variation of those.
How do I check a certificate's expiration date with OpenSSL?
For a file, openssl x509 -in cert.pem -noout -enddate prints the notAfter line, and -dates prints both ends. For a script, openssl x509 -in cert.pem -noout -checkend 2592000 exits 1 if the certificate expires within 30 days (the number is seconds), so it slots into cron or a health check without parsing dates. For a live site, pipe s_client into the same command: openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -enddate.
How do I check that a private key matches a certificate?
Compare the public key each one carries. The classic way is to hash the RSA modulus of both: openssl x509 -noout -modulus -in cert.pem | openssl md5 and openssl rsa -noout -modulus -in key.pem | openssl md5 should print the same hash. That only works for RSA. The version that works for RSA, EC, and Ed25519 keys alike is openssl x509 -in cert.pem -noout -pubkey | openssl sha256 against openssl pkey -in key.pem -pubout | openssl sha256. Swap x509 for req -in req.csr to check a CSR the same way. If the hashes differ you have the wrong key, and the server will refuse to start or IIS will reject the import.
How do I convert a PEM certificate to PFX?
A PFX (PKCS#12) holds the private key, the certificate, and the chain in one password-protected file, which is what Windows, IIS, Exchange, and most Java tools want. Run openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -certfile chain.pem and enter an export password when asked. If you only have a .crt and a .key, those are PEM files with different extensions, so the same command works. If an older Windows or Java version refuses the result, OpenSSL 3 encrypted it with AES by default; add -legacy to produce the older RC2 and 3DES format they expect.
How do I remove the password from a private key?
Write an unencrypted copy: openssl pkey -in key.pem -out key-nopass.pem prompts for the current passphrase and writes the key without one (openssl rsa -in key.pem -out key-nopass.pem does the same for RSA keys). Nginx and Apache cannot start unattended with an encrypted key, which is why people do this. To go the other way and add a passphrase, use openssl pkey -in key.pem -aes256 -out key-enc.pem. When you first generate a key with req, pass -nodes (or -noenc on OpenSSL 3) so it never asks for one.

Related cheat sheets