Computer Networking Cheatsheet
TLS and Certificates
Use this Computer Networking reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
What TLS provides
Three guarantees, and it is worth keeping them separate because they fail separately.
| Guarantee | Mechanism |
|---|---|
| Confidentiality | symmetric AEAD cipher (AES-GCM, ChaCha20-Poly1305) |
| Integrity | the AEAD tag, plus a transcript hash over the handshake |
| Authentication | the server's X.509 certificate chained to a trusted root |
| Version | Status | Notes |
|---|---|---|
| SSL 2.0, 3.0 | broken, removed | POODLE, do not enable |
| TLS 1.0, 1.1 | deprecated (RFC 8996) | fails PCI and modern browsers |
| TLS 1.2 | current, widely required | still fine with AEAD suites and PFS |
| TLS 1.3 | current, preferred | 1 RTT handshake, PFS mandatory, RSA key exchange removed |
TLS 1.3 removed static RSA key exchange, renegotiation, compression, and CBC suites, which is why most classic TLS attacks simply do not apply to it.
TLS 1.3 handshake
client server
ClientHello
supported_versions, key_share (X25519),
cipher_suites, server_name (SNI), alpn
------------------------------------------------>
ServerHello
key_share, selected suite
{EncryptedExtensions, Certificate,
CertificateVerify, Finished}
<------------------------------------------------
{Finished}
------------------------------------------------>
[application data] <--------> [application data]
{} encrypted with handshake keys, [] with application keysOne round trip to application data, against two for TLS 1.2. Session resumption with a PSK ticket allows 0-RTT early data, which is replay-prone and so should only carry idempotent requests.
TLS 1.2 for contrast: ClientHello → ServerHello, Certificate, ServerKeyExchange,
ServerHelloDone → ClientKeyExchange, ChangeCipherSpec, Finished → ChangeCipherSpec,
Finished, two round trips before data.
Certificate fields that matter
| Field | Holds | Gotcha |
|---|---|---|
Subject CN | legacy name | ignored by modern clients, SAN is authoritative |
Subject Alternative Name | the DNS names and IPs the cert is valid for | must list every hostname served |
Issuer | the signing CA | must chain to a trusted root |
Not Before / Not After | validity window | clock skew causes false failures |
Public Key | RSA 2048+ or ECDSA P-256 | ECDSA is smaller and faster |
Signature Algorithm | SHA-256 or better | SHA-1 certs are rejected |
Basic Constraints | CA:TRUE/FALSE | a leaf must be FALSE |
Key Usage / EKU | digitalSignature, serverAuth | wrong EKU fails validation |
AIA | issuer cert and OCSP URLs | how clients fetch a missing intermediate |
CRL Distribution Points | revocation list URL | — |
SCT | Certificate Transparency proofs | Chrome requires them |
Wildcards match one label only: *.example.com covers www.example.com but
not example.com itself nor a.b.example.com.
Chain of trust and validation
Root CA (self-signed, in the OS or browser trust store) └── Intermediate CA (signs leaves, ships with the server) └── Leaf / end-entity certificate (your hostname)
The server must send the leaf plus every intermediate, in order, but not the
root. A missing intermediate is the single most common TLS misconfiguration:
browsers often paper over it by fetching via AIA, while curl, Java, and Go
clients fail outright. That is the shape of "works in my browser, fails in CI".
Validation checks, all of which must pass: signature chain to a trusted root,
current date inside the validity window, hostname matches a SAN entry, EKU
includes serverAuth, and the cert is not revoked (OCSP, CRL, or an OCSP
stapled response from the server).
| Failure string | Real cause |
|---|---|
unable to get local issuer certificate | missing intermediate, or an untrusted private root |
certificate has expired | expired cert, or a wrong system clock |
Hostname mismatch | the name is not in the SAN list |
self signed certificate in certificate chain | private CA not installed in the trust store |
SSL routines::wrong version number | plain HTTP spoken to a TLS port, or the reverse |
no shared cipher | version or suite mismatch, often TLS 1.0 client to a 1.2+ server |
Inspect and debug with openssl
# full handshake, chain, negotiated version and suite openssl s_client -connect example.com:443 -servername example.com openssl s_client -connect example.com:443 -showcerts </dev/null openssl s_client -connect example.com:443 -tls1_2 # force a version openssl s_client -connect example.com:443 -alpn h2 </dev/null | grep ALPN # read a certificate openssl x509 -in cert.pem -noout -text openssl x509 -in cert.pem -noout -subject -issuer -dates openssl x509 -in cert.pem -noout -ext subjectAltName openssl x509 -in cert.pem -noout -fingerprint -sha256 # expiry check straight off a live host echo | openssl s_client -connect example.com:443 -servername example.com \ 2>/dev/null | openssl x509 -noout -enddate # verify a chain locally openssl verify -CAfile chain.pem cert.pem # does the key match the cert? the two moduli must be identical openssl x509 -noout -modulus -in cert.pem | openssl sha256 openssl rsa -noout -modulus -in key.pem | openssl sha256 # CSR and self-signed cert for local development openssl req -new -newkey rsa:2048 -nodes -keyout key.pem -out req.csr \ -subj "/CN=example.com" openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem \ -days 365 -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
curl -vI https://example.com # verbose handshake summary curl --resolve example.com:443:203.0.113.9 https://example.com # test an origin nmap --script ssl-enum-ciphers -p 443 example.com
| Format | Encoding | Typical extensions |
|---|---|---|
| PEM | base64 with -----BEGIN----- headers | .pem .crt .cer .key |
| DER | binary | .der .cer |
| PKCS#12 | encrypted bundle, cert plus key | .p12 .pfx |
| PKCS#8 | private key container | .key |
openssl x509 -in cert.der -inform der -out cert.pem -outform pem openssl pkcs12 -in bundle.pfx -out all.pem -nodes
SNI, ALPN, and modern extensions
- SNI puts the hostname in the ClientHello so one IP can serve many
certificates. It is sent in cleartext in TLS 1.2 and 1.3, which ECH
(Encrypted Client Hello) is designed to fix. Omitting -servername in
s_client is a classic self-inflicted "wrong certificate" result.
- ALPN negotiates the application protocol inside the handshake, which is how
h2 is selected without an extra round trip. HTTP/2 over TLS requires it.
- Perfect forward secrecy comes from ephemeral key exchange (ECDHE, X25519),
so capturing traffic today and stealing the private key later does not decrypt
it. Mandatory in TLS 1.3, and it is why static RSA suites were removed.
- mTLS adds a client certificate: the server sends a CertificateRequest and
validates the client chain the same way. Common for service-to-service auth.
- HSTS (Strict-Transport-Security) tells browsers to refuse plaintext for a
domain, which closes the redirect-stripping window. It is an HTTP header, not a
TLS feature, but it is part of the same posture.
- Certificate lifetimes keep shrinking. Public certs are capped at well under
a year now, so automated renewal (ACME, certbot, lego, caddy) is the only
sane operating model, plus monitoring on expiry.