TLS Certificate Cheat Sheet - OpenSSL & Curl
This is a practical cheat sheet for working with TLS certs – generating keys, creating CSRs, signing, validating and inspecting certificates, and testing TLS connections.
I’ve originally put these together for myself when working with TLS certs and ACME recently, and thought it makes sense to share them in a post, since they might also be helpful to others. Let me know if it’s useful, and if you have suggestions for improvements!
About TLS
Transport Layer Security (TLS) is a cryptographic protocol that provides secure communication over a computer network using public key cryptography and digital certificates to authenticate the communicating parties and to encrypt the data transmitted between them.
A TLS certificate contains:
- A public key, corresponding to a private key owned by the entity presenting the certificate (i.e. a webserver).
- Information about the entity it represents (e.g., domain name, organization, etc.).
- Optionally a signature by a certificate authority (CA) to verify its authenticity.
TLS certificates fall into two main categories:
- CA certificates (which can issue other certificates)
- Root CA certificate (trusted by browsers)
- Intermediate CA certificates (subordinate CA certificates)
- (See also: https://letsencrypt.org/certificates)
- End-entity certificates (aka “leaf cert”, cannot issue other certificates below it)
Formats and encoding for TLS certificates and keys:
- PEM format
- Base64 encoded data, enclosed between
-----BEGIN ...-----
and-----END ...-----
lines. - The most common format to store certificates, signing requests and keys. Defined in RFC 7468. More flexible alternative to the binary DER format.
- Base64 encoded data, enclosed between
- X.509: A standard that defines the format of public key certificates.
Private and Public Keys
Let’s start with private and public keys.
# Create private key, 4096-bit RSA or ed25519
openssl genrsa -out key.pem 4096
openssl genpkey -algorithm ed25519 -out key.pem
# Inspect private key details
openssl pkey -in key.pem -noout -text
# Show the public key of a private key in key.pem
openssl pkey -in key.pem -pubout
# Get sha256+base64 fingerprint (as needed for `curl --pinnedpubkey`)
openssl pkey -in key.pem -pubout -outform DER |
openssl dgst -sha256 -binary |
openssl enc -base64
TLS Certificates and Certificate Signing Request (CSRs)
Let’s create and examine TLS certificates and CSRs.
# Create TLS cert
openssl req -noenc -x509 -key key.pem -out cert.pem -sha256 -days 365 -subj "/O=YourOrg/CN=_DOMAIN_"
# Create CSR from cert
openssl x509 -x509toreq -signkey key.pem -in cert.pem -out csr.pem
# Create a CSR directly instead of from a cert
openssl req -new -key key.pem -subj "/O=YourOrg/CN=_DOMAIN_" -out csr.pem
# Show cert details
openssl x509 -in cert.pem -text -noout
# Show CSR details
openssl req -in csr.pem -text -noout
# Get key sha256+base64 fingerprint from cert
openssl x509 -in cert.pem -pubkey -noout |
openssl pkey -pubin -outform der |
openssl dgst -sha256 -binary |
openssl enc -base64
# If you want to add extension fields (e.g., subjectAltName) to a CSR or cert, you can either do it with -addext, or
# using a config file. Here's an example creating a TLS cert with -addext for subjectAltName:
openssl req -noenc -x509 -key key.pem -out cert.pem -sha256 -days 365 -subj "/O=YourOrg/CN=_DOMAIN_" -addext subjectAltName=IP:192.168.100.82
CA Certificates
Now let’s dive into CA certificates. We will create a root CA cert, an intermediate CA cert, and an end-entity cert signed by the root CA.
# Create private key for CA and intermediate CA
openssl genrsa -out ca.key 4096
openssl genrsa -out intermediate.key 4096
# Create CA certificate
openssl req -noenc -x509 -key ca.key -out ca-cert.pem -sha256 -days 365 -subj "/O=MyCA"
# Create intermediate CA certificate
openssl req -noenc -x509 -key intermediate.key -out intermediate-cert.pem -sha256 -days 365 -subj "/O=MyIntermediate"
# Create a CSR for intermediate CA
openssl x509 -x509toreq -signkey intermediate.key -in intermediate-cert.pem -out intermediate-csr.pem
# Sign intermediate CA with root CA
openssl x509 -req -in intermediate-csr.pem -CA ca-cert.pem -CAkey ca.key -CAcreateserial -out intermediate-cert-signed.pem -days 365 -sha256
# Verify intermediate CA is signed by root CA
openssl verify -CAfile ca-cert.pem intermediate-cert-signed.pem
# Show intermediate CA cert details
openssl x509 -in intermediate-cert-signed.pem -text -noout
# Create CSR (and key) for end-entity cert
openssl req -new -noenc -keyout key.pem -subj "/O=YourOrg/CN=_DOMAIN_" -out csr.pem
# Sign CSR with intermediate cert to create end-entity cert
openssl x509 -req -in csr.pem -CA intermediate-cert-signed.pem -CAkey intermediate.key -CAcreateserial -out cert.pem -days 365 -sha256
# Verify end-entity cert is signed by intermediate CA
openssl verify -CAfile intermediate-cert.pem cert.pem
# Combine CA cert and intermediate CA cert into a chain file
cat ca-cert.pem intermediate-cert-signed.pem > cert-chain.pem
# Verify end-entity cert is signed by root CA via intermediate CA
openssl verify -CAfile chain.pem cert.pem
Curl Commands
# Save TLS cert from a server using curl
curl -w %{certs} -k https://_DOMAIN_ > server-cert.pem
# Require server to present a specific cert (using curl)
curl --cacert server-cert.pem https://_DOMAIN_
# Require server to present a specific key (using curl)
curl --pinnedpubkey "sha256//_PUBKEY_BASE64_FINGERPRINT_" https://_DOMAIN_
Documentation and References
Documentation:
- How to setup your own CA with OpenSSL
- https://knowledge.digicert.com/solution/how-certificate-chains-work
- https://sslinsights.com/what-are-digital-signatures-in-ssl-tls/
- PEM (Privacy-Enhanced Mail) Format: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
- X.509: https://en.wikipedia.org/wiki/X.509
- TLS 1.3
- Certificate Authority Authorization (CAA)
- Certificate Transparency
Tools: