TLS (Transport Layer Security) encrypts data in transit. Every HTTPS connection uses TLS. OpenSSL is the universal toolkit for generating keys, certificates, and testing TLS. Let's Encrypt provides free, auto-renewing certificates.
| Item | Syntax / Value | Description |
|---|---|---|
| TLS handshake | ClientHello, ServerHello, Certificate, Finished | Negotiate cipher, exchange keys, verify certificate |
| TLS 1.2 | Requires 2 round trips to establish | Still widely supported — uses RSA or ECDHE key exchange |
| TLS 1.3 | 1 round trip (0-RTT resumption) | Faster and more secure — removes weak cipher suites |
| Certificate | X.509 certificate — public key + identity + signature | Issued by CA, proves server identity |
| CA | Certificate Authority — signs certificates | DigiCert, Comodo, Let's Encrypt, self-signed |
| Self-signed cert | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes | For dev/testing only — browsers don't trust it |
| CSR | Certificate Signing Request | Send to CA to get certificate signed |
| PEM format | .pem — Base64-encoded certificate or key | Most common format — header: -----BEGIN CERTIFICATE----- |
| DER format | .der — Binary encoded certificate | Used in Java keystores, Windows |
| PKCS#12 | .p12 / .pfx — Certificate + key in one file | Used in Windows, Java — password-protected |
| openssl genrsa | openssl genrsa -out key.pem 4096 | Generate RSA private key |
| openssl genpkey | openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out key.pem | Generate EC key (faster than RSA) |
| openssl req | openssl req -new -key key.pem -out csr.pem | Generate Certificate Signing Request |
| openssl x509 | openssl x509 -in cert.pem -text -noout | Display certificate details |
| openssl verify | openssl verify -CAfile ca.pem cert.pem | Verify certificate against CA |
| openssl s_client | openssl s_client -connect example.com:443 | Test TLS connection — debug certificates |
| openssl pkcs12 | openssl pkcs12 -export -in cert.pem -inkey key.pem -out bundle.p12 | Create PKCS#12 bundle |
| Let's Encrypt | Free, automated, open CA — 90-day certs, auto-renew | certbot --apache or --nginx |
| certbot | certbot certonly --webroot -w /var/www/html -d example.com | Obtain Let's Encrypt certificate |
| certbot renew | certbot renew --quiet | Renew expiring certificates |
| HSTS | Strict-Transport-Security: max-age=31536000; includeSubDomains | Force HTTPS for 1 year |
| Certificate pinning | Pin expected certificate fingerprint in client | Prevents MITM even with rogue CA — hard to update |
| SNI | Server Name Indication — TLS extension | Multiple certs on one IP — client sends hostname in hello |
| OCSP stapling | SSLUseStapling on (Apache) | Server provides cert validity proof — faster than OCSP lookup |
| Perfect Forward Secrecy | ECDHE key exchange — session keys not derived from private key | Compromise of private key doesn't expose past sessions |
# OpenSSL — Essential Commands
# ── Generate keys and certificates ───────────────────────────
# RSA private key (4096-bit)
openssl genrsa -out server.key 4096
# EC private key (256-bit — faster, equally secure)
openssl ecparam -name prime256v1 -genkey -noout -out server.key
# Self-signed certificate (dev/testing)
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \
-days 365 -nodes \
-subj "/C=US/ST=CA/L=SanFrancisco/O=MyWebUniversity/CN=localhost"
# Self-signed with SAN (Subject Alternative Names) — required by modern browsers
cat > san.cnf << 'EOF'
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = mywebuniversity.com
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = mywebuniversity.com
DNS.2 = www.mywebuniversity.com
DNS.3 = localhost
IP.1 = 127.0.0.1
EOF
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \
-days 365 -nodes -config san.cnf
# Generate CSR (to send to a real CA)
openssl req -new -key server.key -out server.csr \
-subj "/C=US/O=MyWebUniversity/CN=www.mywebuniversity.com"
# ── Inspect certificates ──────────────────────────────────────
openssl x509 -in server.crt -text -noout # full details
openssl x509 -in server.crt -dates -noout # expiry dates
openssl x509 -in server.crt -subject -noout # subject
openssl x509 -in server.crt -fingerprint -noout # SHA1 fingerprint
openssl x509 -in server.crt -fingerprint -sha256 -noout # SHA256
# Check certificate matches private key
openssl x509 -noout -modulus -in server.crt | md5sum
openssl rsa -noout -modulus -in server.key | md5sum
# Must match!
# ── Test TLS connections ──────────────────────────────────────
# Basic TLS test
openssl s_client -connect www.mywebuniversity.com:443
# Show full certificate chain
openssl s_client -connect www.mywebuniversity.com:443 -showcerts
# Check TLS version and ciphers
openssl s_client -connect www.mywebuniversity.com:443 -tls1_3
openssl ciphers -v | grep ECDHE | head -10
# Test specific TLS version
openssl s_client -connect example.com:443 -no_tls1 -no_tls1_1 # force TLS 1.2+
# ── Let's Encrypt ─────────────────────────────────────────────
sudo apt install certbot python3-certbot-apache python3-certbot-nginx
# Apache
sudo certbot --apache -d mywebuniversity.com -d www.mywebuniversity.com
# NGINX
sudo certbot --nginx -d mywebuniversity.com -d www.mywebuniversity.com
# Standalone (no web server running)
sudo certbot certonly --standalone -d mywebuniversity.com
# Check certificate expiry
sudo certbot certificates
openssl x509 -in /etc/letsencrypt/live/mywebuniversity.com/cert.pem -noout -dates
# Auto-renewal cron (certbot usually adds this automatically)
echo "0 3 * * * certbot renew --quiet" | sudo crontab -
# ── Python: verify TLS ────────────────────────────────────────
import ssl, socket
def check_cert(hostname, port=443):
ctx = ssl.create_default_context()
with socket.create_connection((hostname, port), timeout=5) as sock:
with ctx.wrap_socket(sock, server_hostname=hostname) as ssock:
cert = ssock.getpeercert()
print(f"Subject: {dict(x[0] for x in cert['subject'])}")
print(f"Issuer: {dict(x[0] for x in cert['issuer'])}")
print(f"Expires: {cert['notAfter']}")
print(f"SANs: {[v for t,v in cert.get('subjectAltName',[])]}")
return cert
check_cert("www.mywebuniversity.com")
# python3 check_cert.py