Skip to main content
    Guides

    OpenSSL Commands Cheat Sheet: Keys, CSR, Inspect & Convert

    Essential OpenSSL commands: generate keys and CSRs, inspect certs, convert PEM/PFX/DER formats, and test live TLS connections. Updated for 3.5 LTS and 4.0.

    MS
    My-SSL Team
    ·
    18 min read
    ·Published June 8, 2026·Updated June 8, 2026

    OpenSSL is the command-line toolkit that underpins almost everything in the SSL/TLS world — CAs use it to sign certificates, servers use it to handle handshakes, and administrators use it to diagnose problems. Knowing a handful of core commands will let you generate keys, create CSRs, inspect what a CA returned, convert formats for your server, and confirm that a live site is actually serving the right certificate.

    This guide covers the commands you will reach for most often, organised by task. All examples were tested on OpenSSL 3.5 LTS (the recommended production version, supported until April 2030). Where OpenSSL 4.0 — released April 14, 2026 — behaves differently, the difference is noted.

    Prefer a browser tool?

    My-SSL's free tools handle the most common tasks without the command line: CSR Generator, SSL Checker, and Certificate Converter.

    1. Check your OpenSSL version

    Run this first. The output tells you which version and build flags are active, and whether FIPS mode is compiled in. Some cipher and key operations behave differently between 1.x, 3.x, and 4.x.

    bash
    # Full version string
    openssl version -a
    
    # Example output (OpenSSL 3.5 LTS on Ubuntu 24.04)
    # OpenSSL 3.5.0 8 Apr 2025 (Library: OpenSSL 3.5.0 8 Apr 2025)
    # built on: ...
    # OPENSSLDIR: "/usr/lib/ssl"
    # ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-3"
    # MODULESDIR: "/usr/lib/x86_64-linux-gnu/ossl-modules"
    
    # List all available sub-commands
    openssl help

    OpenSSL 1.x is end-of-life

    OpenSSL 1.1.1 reached end-of-life in September 2023 and receives no security patches. If your system shows OpenSSL 1.x, upgrade your OS or build OpenSSL 3.5 from source. OpenSSL 3.0 receives security-only fixes until September 2026, then it too goes EOL.

    2. Generate private keys

    A private key is generated on your server and never sent to the CA. The CA only receives the CSR (which contains your public key). Keep the private key secure — if it is compromised, the certificate must be revoked.

    RSA keys

    RSA 2048-bit is the minimum accepted by all CAs. RSA 4096-bit offers a larger security margin at the cost of slightly slower TLS handshakes.

    bash
    # RSA 2048-bit (widely compatible)
    openssl genrsa -out private.key 2048
    
    # RSA 4096-bit (stronger, marginally slower handshakes)
    openssl genrsa -out private.key 4096
    
    # RSA 2048-bit with AES-256 passphrase protection
    # (required before copying the key off the server)
    openssl genrsa -aes256 -out private.key 2048
    
    # Remove passphrase from a protected key
    # (needed by Nginx/Apache — they can't prompt interactively)
    openssl rsa -in private-encrypted.key -out private.key

    ECDSA keys

    ECDSA keys are shorter and produce faster handshakes than RSA at equivalent security levels. P-256 and P-384 are universally supported by modern browsers and all major CAs.

    bash
    # ECDSA P-256 (fastest; 128-bit security)
    openssl ecparam -name prime256v1 -genkey -noout -out private.key
    
    # ECDSA P-384 (192-bit security; preferred for high-assurance certs)
    openssl ecparam -name secp384r1 -genkey -noout -out private.key
    
    # OpenSSL 3.x alternative using the newer genpkey command
    # (works for both RSA and ECDSA; preferred in scripts)
    openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out private.key
    openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key

    Inspect the key you just generated

    bash
    # View RSA key details (modulus length, public exponent)
    openssl rsa -in private.key -text -noout
    
    # View ECDSA key details (curve, public key point)
    openssl ec -in private.key -text -noout
    
    # Print only the public key component (safe to share)
    openssl rsa -in private.key -pubout
    openssl ec  -in private.key -pubout

    3. Generate a Certificate Signing Request (CSR)

    A CSR encodes your organisation details and public key, signed by your private key to prove ownership. You submit the CSR to your CA; the CA signs it and returns a certificate. The private key never leaves your server.

    Since March 2026, publicly trusted certificates are capped at 199 days validity (CA/Browser Forum Ballot SC-081v3). This means you will be renewing certificates roughly every six months and generating new CSRs at each renewal.

    Basic single-domain CSR

    bash
    # Generate key and CSR in one step
    openssl req -new -newkey rsa:2048 -nodes -keyout private.key -out request.csr
    
    # You'll be prompted for:
    #   Country Name (2-letter code): US
    #   State or Province Name: California
    #   Locality Name (City): San Francisco
    #   Organization Name: Example Corp
    #   Organizational Unit Name: (leave blank or enter dept)
    #   Common Name: example.com
    #   Email Address: (leave blank)
    #   Challenge password: (leave blank)
    
    # Generate CSR from an existing private key (for renewal)
    openssl req -new -key private.key -out request.csr

    CSR with Subject Alternative Names (SAN)

    Modern CAs ignore the Common Name and use SANs for validation. Always include SANs when you need to secure multiple hostnames.

    bash
    # Create a temporary config file
    cat > san.cnf << 'EOF'
    [req]
    distinguished_name = dn
    req_extensions     = req_ext
    prompt             = no
    
    [dn]
    C  = US
    ST = California
    L  = San Francisco
    O  = Example Corp
    CN = example.com
    
    [req_ext]
    subjectAltName = DNS:example.com, DNS:www.example.com, DNS:api.example.com
    EOF
    
    # Generate key and CSR using the config
    openssl req -new -newkey rsa:2048 -nodes   -keyout private.key   -out request.csr   -config san.cnf
    
    # Verify the SAN is embedded in the CSR
    openssl req -in request.csr -text -noout | grep -A3 "Subject Alternative"

    Non-interactive CSR (CI/CD pipelines)

    bash
    # Pass all fields as a single -subj string
    openssl req -new -key private.key -out request.csr   -subj "/C=US/ST=California/L=San Francisco/O=Example Corp/CN=example.com"

    Only need a certificate for local testing, with no CA involved? Adding -x509 to the same command produces a self-signed certificate instead of a CSR — see our self-signed certificates guide for when that's appropriate and how browsers treat the result.

    4. Inspect certificates, CSRs, and keys

    Before deploying a certificate, verify that the CN, SANs, validity dates, and issuer chain are exactly what you expect. These commands decode the DER structures into human-readable output.

    Inspect a certificate file

    bash
    # Full certificate details (subject, issuer, SANs, validity, signature)
    openssl x509 -in certificate.crt -text -noout
    
    # Print only the validity dates (notBefore / notAfter)
    openssl x509 -in certificate.crt -noout -dates
    
    # Print only the subject (CN, O, C)
    openssl x509 -in certificate.crt -noout -subject
    
    # Print only the issuer
    openssl x509 -in certificate.crt -noout -issuer
    
    # Print Subject Alternative Names only
    openssl x509 -in certificate.crt -noout -ext subjectAltName
    
    # Print the certificate fingerprint (SHA-256)
    openssl x509 -in certificate.crt -noout -fingerprint -sha256
    
    # Print the serial number
    openssl x509 -in certificate.crt -noout -serial

    Inspect a CSR

    bash
    # Full CSR details (subject, public key, requested extensions)
    openssl req -in request.csr -text -noout
    
    # Verify the CSR signature (confirms key ownership)
    openssl req -in request.csr -verify -noout

    Inspect a PFX / PKCS#12 file

    bash
    # List contents of a PFX (will prompt for the PFX password)
    openssl pkcs12 -info -in certificate.pfx -noout
    
    # OpenSSL 3.x: if the PFX was created by old Windows tools using RC2/3DES
    openssl pkcs12 -info -in certificate.pfx -noout -legacy

    Inspect a DER-encoded certificate

    bash
    # DER is binary — add -inform der
    openssl x509 -in certificate.der -inform der -text -noout

    Inspect a P7B / PKCS#7 chain file

    bash
    # Print all certificates in the bundle
    openssl pkcs7 -in certificate.p7b -print_certs -noout

    5. Verify private key matches certificate

    A mismatched key is one of the most common SSL deployment errors. Nginx reports "SSL_CTX_use_PrivateKey_file failed", Apache reports "Init: Private key not found", and IIS silently refuses to bind. Always verify before reloading your server.

    RSA certificates

    bash
    # The MD5 hash of the modulus must be identical for both files.
    openssl x509 -noout -modulus -in certificate.crt | openssl md5
    openssl rsa  -noout -modulus -in private.key      | openssl md5
    
    # If both lines print the same hash (e.g. (stdin)= d41d8cd98f00b204...)
    # the key and certificate match.

    ECDSA certificates

    bash
    # Compare the public key extracted from the private key and from the cert
    openssl ec  -noout -pubout -in private.key       | openssl md5
    openssl x509 -noout -pubkey -in certificate.crt  | openssl md5

    Verify the CSR matches the private key

    bash
    # Use this after generating a CSR to confirm they are a pair
    openssl req -noout -modulus -in request.csr  | openssl md5
    openssl rsa -noout -modulus -in private.key  | openssl md5

    6. Convert certificate formats

    Different servers expect different file formats. Apache and Nginx require PEM. IIS and Windows services require PFX (PKCS#12). Java keystores use JKS or PKCS#12 (since Java 9). See the SSL certificate formats guide for a full explanation, or use the My-SSL Certificate Converter for browser-based conversion.

    PEM → PFX (PKCS#12)

    Required for IIS, Windows Server, Exchange, and Azure services.

    bash
    # Basic: certificate + private key → PFX
    # You will be prompted to set a PFX password.
    openssl pkcs12 -export   -in  certificate.crt   -inkey private.key   -out  certificate.pfx
    
    # Include intermediate CA certificate in the bundle
    openssl pkcs12 -export   -in  certificate.crt   -inkey private.key   -certfile ca_bundle.crt   -out  certificate.pfx
    
    # Non-interactive (pass password on the command line — use in CI only)
    openssl pkcs12 -export   -in  certificate.crt   -inkey private.key   -out  certificate.pfx   -passout pass:YourPassword

    PFX → PEM

    bash
    # Extract the certificate (no private key)
    openssl pkcs12 -in certificate.pfx -nokeys -out certificate.crt
    
    # Extract the private key (no passphrase on output — ready for Nginx/Apache)
    openssl pkcs12 -in certificate.pfx -nocerts -nodes -out private.key
    
    # Extract everything (certificate + key) in one PEM file
    openssl pkcs12 -in certificate.pfx -nodes -out bundle.pem
    
    # OpenSSL 3.x flag for old RC2/3DES PFX files generated by legacy Windows tools
    openssl pkcs12 -in certificate.pfx -nokeys -out certificate.crt -legacy

    PEM → DER

    bash
    # Certificate PEM → DER binary
    openssl x509 -in certificate.crt -outform der -out certificate.der
    
    # DER binary → PEM text
    openssl x509 -in certificate.der -inform der -outform pem -out certificate.crt

    PEM → P7B (PKCS#7)

    P7B bundles contain only certificates (no private key). Windows and IIS use them to distribute certificate chains.

    bash
    # Certificate + CA bundle → P7B
    openssl crl2pkcs7 -nocrl   -certfile certificate.crt   -certfile ca_bundle.crt   -out certificate.p7b
    
    # P7B → PEM (extract all certificates)
    openssl pkcs7 -in certificate.p7b -print_certs -out bundle.pem

    PEM → Java PKCS#12 keystore

    bash
    # Java 9+ accepts PKCS#12 keystores directly — just create a PFX:
    openssl pkcs12 -export   -in  certificate.crt   -inkey private.key   -certfile ca_bundle.crt   -name "myalias"   -out  keystore.p12
    
    # Then import into Java with keytool (set storetype to PKCS12):
    # keytool -importkeystore #   -srckeystore keystore.p12 -srcstoretype PKCS12 #   -destkeystore keystore.jks -deststoretype JKS

    7. Test a live TLS connection

    openssl s_client connects to a server, completes the TLS handshake, and prints the certificate chain, negotiated protocol, and cipher. It is the fastest way to confirm that a newly deployed certificate is actually live.

    Basic connection

    bash
    # Connect to a web server and dump the full handshake
    openssl s_client -connect example.com:443
    
    # Use -servername for SNI (required on servers hosting multiple certs)
    openssl s_client -connect example.com:443 -servername example.com
    
    # Quiet: just print the certificate (suppress handshake noise)
    echo | openssl s_client -connect example.com:443   -servername example.com 2>/dev/null   | openssl x509 -text -noout

    Check protocol and cipher

    bash
    # Show the protocol version and cipher negotiated
    echo | openssl s_client -connect example.com:443   -servername example.com 2>/dev/null   | grep -E "^(Protocol|Cipher)"

    Check expiry of a live certificate

    bash
    # Print notBefore and notAfter dates for example.com
    echo | openssl s_client -connect example.com:443   -servername example.com 2>/dev/null   | openssl x509 -noout -dates

    Force a specific TLS version

    bash
    # Test TLS 1.3 only (fails if server doesn't support it)
    openssl s_client -connect example.com:443 -tls1_3
    
    # Test TLS 1.2 only
    openssl s_client -connect example.com:443 -tls1_2
    
    # Note: -ssl3, -tls1, -tls1_1 are removed in OpenSSL 4.0 and
    # were no-ops in 3.x (SSLv3/TLS 1.0/1.1 were already disabled).

    Check SMTP STARTTLS (and other non-HTTPS)

    bash
    # SMTP with STARTTLS
    openssl s_client -connect mail.example.com:587 -starttls smtp
    
    # IMAP with STARTTLS
    openssl s_client -connect mail.example.com:143 -starttls imap
    
    # PostgreSQL with TLS
    openssl s_client -connect db.example.com:5432 -starttls postgres

    Test OCSP stapling

    bash
    # Check whether the server is stapling an OCSP response
    echo | openssl s_client -connect example.com:443   -servername example.com -status 2>/dev/null   | grep -A10 "OCSP response"

    8. Verify the certificate chain

    A broken certificate chain is the most common SSL misconfiguration. Chrome hides it by fetching missing intermediates automatically (AIA Fetching), but mobile clients, curl, and API consumers will reject an incomplete chain. See the certificate chain guide for a full explanation.

    Verify against a CA bundle file

    bash
    # Verify a certificate against a specific CA bundle
    openssl verify -CAfile ca_bundle.crt certificate.crt
    # Expected output: certificate.crt: OK
    
    # Verify including untrusted intermediates you have locally
    openssl verify -CAfile root.crt -untrusted intermediate.crt certificate.crt

    Verify the chain served by a live server

    bash
    # s_client with -showcerts prints the full chain the server sends
    echo | openssl s_client -connect example.com:443   -servername example.com -showcerts 2>/dev/null   | grep -E "^(subject|issuer)"

    Verify against the system trust store

    bash
    # Uses /etc/ssl/certs (Linux) or the OS keychain (macOS) as the root store
    openssl verify certificate.crt

    9. Check OCSP revocation status

    OCSP (Online Certificate Status Protocol) lets you ask a CA's responder whether a specific certificate has been revoked — without downloading a CRL. See the OCSP stapling guide to learn how to cache and serve OCSP responses on Nginx and Apache.

    bash
    # Step 1: Get the OCSP responder URL from the certificate
    openssl x509 -in certificate.crt -noout -text   | grep -A2 "Authority Information Access"
    # Typical output: OCSP - URI:http://ocsp.example-ca.com
    
    # Step 2: Send an OCSP request using the issuer certificate
    openssl ocsp   -issuer intermediate.crt   -cert certificate.crt   -url http://ocsp.example-ca.com   -text -noverify
    
    # Expected output includes: Response verify OK
    # And: example.crt: good (if the certificate is not revoked)

    10. Quick reference table

    One-line commands for the most common tasks.

    TaskCommand
    OpenSSL versionopenssl version -a
    Generate RSA 2048 keyopenssl genrsa -out private.key 2048
    Generate ECDSA P-256 keyopenssl ecparam -name prime256v1 -genkey -noout -out private.key
    Generate CSR from keyopenssl req -new -key private.key -out request.csr
    Inspect certificateopenssl x509 -in cert.crt -text -noout
    Check cert expiry datesopenssl x509 -in cert.crt -noout -dates
    Inspect CSRopenssl req -in request.csr -text -noout
    Verify key ↔ cert match (RSA)openssl x509 -noout -modulus -in cert.crt | openssl md5
    PEM → PFXopenssl pkcs12 -export -in cert.crt -inkey private.key -out cert.pfx
    PFX → PEM (cert only)openssl pkcs12 -in cert.pfx -nokeys -out cert.crt
    PFX → PEM (key only)openssl pkcs12 -in cert.pfx -nocerts -nodes -out private.key
    PEM → DERopenssl x509 -in cert.crt -outform der -out cert.der
    DER → PEMopenssl x509 -in cert.der -inform der -out cert.crt
    PEM → P7Bopenssl crl2pkcs7 -nocrl -certfile cert.crt -certfile ca.crt -out cert.p7b
    Test live TLS connectionopenssl s_client -connect example.com:443 -servername example.com
    Check live cert expiryecho | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
    Verify cert chainopenssl verify -CAfile ca_bundle.crt certificate.crt
    Check OCSP staplingecho | openssl s_client -connect example.com:443 -status 2>/dev/null | grep -A10 'OCSP response'

    Common OpenSSL errors and fixes

    unable to load Private Key

    The file path is wrong, the key has a passphrase (add -passin pass:password), or the file is PEM for a different key type. Run openssl rsa -in private.key -check to diagnose.

    error 20: unable to get local issuer certificate

    Your CA bundle is missing or incomplete. Pass the correct -CAfile or concatenate root + intermediate into a bundle: cat intermediate.crt root.crt > ca_bundle.crt

    error 18: self-signed certificate

    The certificate is self-signed and not in any trust store. For testing, add -noverify (OCSP) or bypass verification — but never in production.

    unable to load certificate (bad end line / bad base64)

    The PEM file is truncated, has Windows CRLF line endings, or contains extra whitespace. Try: dos2unix certificate.crt or re-download the certificate from your CA.

    PKCS12 mac verify error / bad password read

    Wrong PFX password, or a legacy PFX encrypted with RC2/3DES. Add the -legacy flag on OpenSSL 3.x: openssl pkcs12 -legacy -in cert.pfx …

    OpenSSL 4.0: What changed for certificate work

    OpenSSL 4.0, released on April 14, 2026, is a feature release with breaking changes. Most Linux distributions have not yet shipped it as their system OpenSSL (Fedora 42 is an early adopter). If you install it alongside 3.5 for testing, be aware of the following differences that affect the commands in this guide:

    Engine API removed

    The -engine flag and OPENSSL_NO_ENGINE build option are gone. If you relied on HSM or PKCS#11 engine-based key storage, migrate to provider-based loading (openssl pkey -provider pkcs11 …).

    SSLv3 and SSLv2 ClientHello removed

    The -ssl3 flag no longer exists. All SSLv3-specific test options in s_client are removed. This only affects legacy diagnostic scenarios — no modern server supports SSLv3.

    RSA hex output no longer has leading '00:'

    When OpenSSL 4.0 prints an RSA modulus in hex (e.g., openssl x509 -modulus), the leading 00: that appeared on 3.x when the first byte was ≥ 0x80 is no longer printed. This affects scripts that compare raw modulus strings rather than their MD5 hashes.

    pkcs12 -legacy still available

    The -legacy flag for handling old RC2/3DES PFX files remains in 4.0, provided the legacy provider is loaded. Run openssl pkcs12 -legacy -provider legacy -provider default -in cert.pfx … if you encounter errors.

    Related guides and tools

    Not a command-line person? My-SSL's free CSR Generator creates a key and CSR in your browser with no software to install. The Certificate Converter handles PEM ↔ PFX ↔ DER ↔ P7B conversions with a file upload.

    FAQ