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.
| Command | What 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 -nooutCheck 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.
| Command | What 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 -issuerSave 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.pemLook 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.
| Command | What 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.
| Command | What 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"| Command | What 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.
| Command | What 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.pemVerify Chain and Key Match
| Command | What 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 -nooutEach 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| Command | What 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
| Command | What 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.