Skip to content
Learni
View all tutorials
Sécurité

How to Generate SSL Certificates with OpenSSL in 2026

Lire en français

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

terminal
openssl version -a
openssl list -1 -cipher-algorithms | head -5
openssl rand -hex 32

This 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

terminal
openssl genpkey -algorithm RSA -out private-rsa.key -aes256
openssl rsa -in private-rsa.key -out private-rsa-unencrypted.key -passin pass:SuperSecretPass2026

The 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)

terminal
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

terminal
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

terminal
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.crt

Generates 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

terminal
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:SuperSecretPass2026

Bundles 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

openssl.cnf
[ 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.1

This 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

terminal
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.cnf

Verifies 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_INVALID on 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+ and openssl update -check.

Next Steps