SSL/TLS/HTTPS

January 31, 2019 Application 3 minutes, 3 seconds

Simple usecase

openssl req -x509 -newkey rsa:4096 -sha256 -keyout key.pem -out cert.pem -days 365

Advanced usecase Including Subject Alternative Names

openssl req \
-newkey rsa:4096 \
-x509 \
-nodes \
-keyout key.pem \
-out cert.pem \
-subj "/C=DE/ST=Munich/L=Bavaria/O=department/OU=company/CN=example.com" \
-reqexts SAN \
-extensions SAN \
-config <(cat /etc/ssl/openssl.cnf \
    <(printf '[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost')) \
-sha256 \
-days 365

Path of /etc/ssl/openssl.cnf might differ

openssl rsa -in original.key -out unencripted.key

Instead of cert.pem use fullchain.pem to prevent "missing local issuer" error

openssl rsa -in priv.key -check

openssl x509 -in cert.pem -text -noout

openssl pkcs12 -info -in keyStore.p12

openssl pkcs12 -in keyStore.[pfx|p12] -out keyStore.pem -nodes

-nocerts to only output the private key or -nokeys to only output the certificates.

openssl pkcs12 -export -out example.com.pfx -inkey example.com.key -in example.com.pem -certfile foo_intermediate.pem -certfile bar_intermediate.pem -certfile super_ca_root.pem

When the key matches the certificate only one has output is returned

(openssl rsa -noout -modulus -in example.com.key | openssl md5; openssl x509 -noout -modulus -in example.com.pem | openssl md5) | uniq

alias get-ssl-cert='echo Q |openssl s_client -connect' # prints certificate
alias get-ssl-fingerprint='openssl x509 -in cert.pem -sha1 -noout -fingerprint'

Example:

get-ssl-cert google.com:443 > cert.pem
get-ssl-fingerprint # assumes cert.pem in current directory

openssl s_client -state -nbio -connect HOST:PORT

curl --insecure -v https://google.com 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'

Generating CA, certificates, and keys

# Generate CA and CA key to sign CSRs
# -des3 for password protection of the CA key
openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

# Generate Server key and CSR
# Optionally use -des3 for password protection of the server key
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr

# Sign the server CSR with the CA key
# Enter the pass provied in the first step
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

# Generate Client key and CSR
# Optionally use -des3 for password protection of the client key
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr

# Singn the client CSR with the CA key
# Enter the pass provied in the first step
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt

# Optionally create a PKCS 12 archive for importing client certificate data in web browsers
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

Relevant snippet for nginx.conf

listen *:443;               # Listen for incoming connections from any interface on port 443 (TLS)
ssl on;
ssl_certificate        /etc/nginx/certs/server.crt;
ssl_certificate_key    /etc/nginx/certs/server.key;
ssl_client_certificate /etc/nginx/certs/ca.crt; # used to sign the client certificates
ssl_verify_client      on; # force SSL verification

Testing with curl (assuming nginx is running on localhost listening to standard https port)

curl --insecure https://localhost
# --insecure as we use self signed certificates
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
curl --insecure --key client.key --cert client.crt  https://localhost
<h1>Welcome</h1>
<p>This is my home page</p>