Introduction
OpenSSL remains the go-to open-source cryptography tool in 2026, powering 99% of web servers for SSL/TLS certificate management. Whether you're setting up an Nginx reverse proxy, Kubernetes cluster, or Node.js API, knowing how to generate private keys, CSRs (Certificate Signing Requests), and self-signed certificates is essential for dev, staging, or isolated prod environments.
This intermediate tutorial walks you through it step by step: from RSA/ECC key generation to custom configs via openssl.cnf, including format conversions (PEM, PKCS12). Think of OpenSSL as a crypto blacksmith workshop: you forge your own security tools. By the end, you'll implement a basic PKI (Public Key Infrastructure), validate certs, and dodge common issues like weak keys or missing SANs. Ready to secure your deployments? (128 words)
Prerequisites
- OpenSSL 3.0+ installed (Linux:
sudo apt install openssl; macOS:brew install openssl; Windows: via Chocolatey or WSL). - Unix-like terminal (Bash/Zsh).
- Basic cryptography knowledge: RSA vs ECC, PEM vs DER.
- Empty workspace:
mkdir openssl-tutorial && cd openssl-tutorial.
Verify OpenSSL Installation
openssl version -a
openssl list -1 -cipher-algorithms | head -5
openssl rand -hex 32This sequence checks the version (must be 3.x for modern ECC curves), lists available algorithms, and generates random hex to test entropy. Avoid versions <3.0 lacking post-quantum readiness; reinstall via package manager if errors occur.
The Basics: Keys and Formats
Before diving in, understand the formats: PEM (base64 text, .pem/.key) for universal compatibility; PKCS12 (encrypted binary, .p12/.pfx) for Java/Tomcat keystores. A 2048-bit RSA private key is standard, but switch to ECC P-384 for better performance (as NIST recommends in 2026). Each command generates standalone files, always protected by an initial passphrase.
Generate a 4096-bit RSA Private Key
openssl genpkey -algorithm RSA -out private-rsa.key -aes256
openssl rsa -in private-rsa.key -out private-rsa-unencrypted.key -passin pass:SuperSecretPass2026The first command creates an AES-256 encrypted key (interactive passphrase or via -passout). The second decrypts it for servers (less secure against theft). Use 4096 bits minimum in 2026; pitfalls: forgetting the passphrase or using obsolete DSA.
Generate a CSR with Subject Alternative Names (SAN)
cat > san.cnf << EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
IP.1 = 192.168.1.100
EOF
openssl req -new -key private-rsa-unencrypted.key -out example.csr -config san.cnf -subj "/C=FR/ST=Paris/L=Paris/O=Learni/OU=Dev/CN=example.com"This script creates a san.cnf for SANs (crucial for multi-domain HTTPS), then generates a CSR signed by the private key. -subj skips interactivity; verify with openssl req -text -noout -in example.csr. Pitfall: no SAN means modern browsers reject the cert.
Create a Self-Signed Certificate Valid for 1 Year
openssl x509 -req -days 365 -in example.csr -signkey private-rsa-unencrypted.key -out example.crt -extensions v3_req -extfile san.cnf
openssl x509 -in example.crt -text -noout | grep -A5 'Subject Alternative Name'Signs the CSR with the private key for a self-signed root cert (fine for dev/staging). -days 365 sets 1 year; verification shows SANs. In prod, use external CA like Let's Encrypt. Pitfall: short expiry dates break CI/CD tests.
Switch to ECC for Performance
RSA is secure but slow; ECC (Elliptic Curve Cryptography) delivers equivalent security with 10x shorter keys. In 2026, prime256v1 or secp384r1 are standard for TLS 1.3. Analogy: RSA = armored truck, ECC = agile motorcycle.
Generate ECC Key and Certificate
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:secp384r1 -out private-ecc.key
openssl req -new -key private-ecc.key -out example-ecc.csr -subj "/C=FR/ST=Paris/L=Paris/O=Learni/OU=Dev/CN=ecc.example.com" -addext "subjectAltName=DNS:ecc.example.com"
openssl x509 -req -days 365 -in example-ecc.csr -signkey private-ecc.key -out example-ecc.crtGenerates secp384r1 ECC key (NIST-approved), CSR with -addext (OpenSSL 1.1.1+), then cert. Faster TLS handshakes. Verify: openssl ec -in private-ecc.key -text -noout. Pitfall: non-standard curves like brainpool break Chrome interop.
Convert to PKCS12 for Java/Node
openssl pkcs12 -export -out keystore.p12 -inkey private-rsa-unencrypted.key -in example.crt -certfile ca.crt -passout pass:SuperSecretPass2026
openssl pkcs12 -in keystore.p12 -info -noout -passin pass:SuperSecretPass2026Bundles key + cert into encrypted .p12 (for Java keystores, NODE_EXTRA_CA_CERTS). Add -certfile for CA chains. Verification lists contents. Pitfall: weak passphrase exposed in scripts; use env vars.
Custom OpenSSL.cnf Configuration
[ req ]
default_bits = 4096
prompt = no
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
C = FR
ST = Paris
L = Paris
O = Learni Group
OU = DevOps
CN = localhost
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = 127.0.0.1
IP.1 = 127.0.0.1This complete openssl.cnf automates CSRs with defaults (CN=localhost for local dev). Use with openssl req -new -key private.key -out csr.csr -config openssl.cnf. Customize for prod. Pitfall: missing absolute path to cnf breaks validations.
Verify and Revoke a Certificate
openssl verify -CAfile example.crt example-ecc.crt
openssl x509 -in example.crt -serial -noout
openssl ca -revoked example.crt -keyfile private-rsa-unencrypted.key -cert example.crt -config openssl.cnfVerifies chain (self-signed = ok), extracts serial, simulates CA revocation (for PKI). Requires index/CRL setup for real CA. Pitfall: no -CAfile fails self-signed verification; always check expiry with openssl x509 -enddate -noout.
Best Practices
- Always encrypt private keys at rest (
-aes256), decrypt only in-memory on servers. - Use ECC secp384r1 or Ed25519 for new setups; RSA 4096 as fallback.
- Enable HSTS and OCSP Stapling after certs; test with
openssl s_client -connect example.com:443. - Atomic backups: tar key+cert+cnf; manage CRLs for revocations.
- Integrate into CI/CD: GitHub Actions with OpenSSL Docker image.
Common Errors to Avoid
- Keys too short (<3072 RSA): vulnerable to quantum Shor's algorithm (post-2030 threat).
- Missing SAN/DNS:
ERR_CERT_COMMON_NAME_INVALIDon Chrome/Firefox. - Passphrases in plain text in scripts: use
openssl rand -base64+ secrets manager (Vault/AWS SSM). - Vulnerable OpenSSL versions (e.g., Heartbleed): pin to
openssl 3.3+andopenssl update -check.
Next Steps
- Official docs: OpenSSL Man Pages.
- Advanced tools: step-ca for self-hosted PKI.
- Training: Check out Learni's DevOps security courses.
- Practice: Integrate with Docker Compose for local HTTPS (
nginx:alpine).