TLS Certificates: Everything That Can Go Wrong (and Why mTLS Is Becoming the Standard for Serious Stuff) A complete guide to digital certificates in 2026 — from the basics that still break production to mTLS that's becoming mandatory for serious APIs and CDN integrations.
A complete guide to digital certificates in 2026 — from the basics that still break production to mTLS that's becoming mandatory for serious APIs and CDN integrations.
If you manage anything on the internet, you've been through this: the client calls complaining that "the site is showing a security error", you open the browser and see that red screen. Expired certificate. Invalid certificate. Certificate for another name. And always on a Friday afternoon.
TLS certificates are one of those things that seem simple until you need to touch them. And here's the point: certificates aren't just for HTTPS. In 2026, they're the foundation of practically all modern authentication on the internet. mTLS is becoming the standard for APIs between systems. Cloudflare, AWS, Google, and Azure are pushing certificate-based authentication for serious integrations. Service mesh uses certificates to authenticate service-to-service. Zero Trust depends on certificates to identify devices.
Three things:
The first two are solved by symmetric cryptography. The third is the hard problem: how do you share a secret key with someone you've never met over a potentially hostile network?
The answer: digital certificates and asymmetric cryptography.
The magic is in step 4: using elliptic curve Diffie-Hellman, both sides arrive at the same secret key without ever transmitting it on the wire.
The browser/OS "trust store" contains the pre-installed trusted CAs.
Root CA (in trust store)
└── Intermediate CA
└── Your certificate
The server needs to send certificate leaf + intermediates. Forgetting this is one of the most common errors: it works in Chrome (which has a cache) but breaks in curl or Firefox.
Always use fullchain.pem.
DV (Domain Validation) — only verifies control of the domain. Automated, free (Let's Encrypt). Sufficient for 99% of cases.
OV (Organization Validation) — verifies that the company exists. Asks for CNPJ, phone, address. Time: 1-5 days. Cost: tens to hundreds of dollars.
EV (Extended Validation) — extended validation. In 2026, browsers no longer show a differentiated green bar. EV became a compliance requirement, not visual differentiation.
Single domain — one name only.
Wildcard — *.empresa.com.br covers all direct subdomains. Does not cover the root domain or subdomains of subdomains. Let's Encrypt issues via DNS-01.
Multi-Domain (SAN) — specific list of names. Let's Encrypt supports up to 100 SANs.
The revolution. Today it issues more than half of all public certificates on the internet.
Free alternative to Let's Encrypt. Also ACME. Useful for diversification.
Google issuing publicly since 2022. Free for Google Cloud customers.
DigiCert, Sectigo, GlobalSign, Entrust. Who still buys: companies with required OV/EV, long validity, commercial SLA, special certificates.
You can run your own. For internal mTLS, IoT, service mesh, private infrastructure.
Tools:
The classic. It already happened to Microsoft Teams, LinkedIn, Spotify, Cisco, Ericsson, everyone.
Root cause: someone installed manually, reminder got lost, person left, nobody knew.
How to avoid:
Works in Chrome, breaks in curl. Symptom: client swears it doesn't work and you can't reproduce it.
openssl s_client -connect empresa.com.br:443 -showcerts
# Or ssllabs.com/ssltest
Solution: always fullchain.pem.
Certificate for www.empresa.com.br but someone accesses empresa.com.br. Include all SANs.
Minimum acceptable in 2026:
HTTPS loading HTTP resources. Use relative URLs, explicit https://, Content-Security-Policy: upgrade-insecure-requests as a band-aid.
Once received, browser remembers via max-age. If cert expires, users get locked out. Preload is practically irreversible.
Start with max-age=300, increase gradually.
If you say "ignore the warning and click advanced", you have a problem. Fix it with Let's Encrypt in 2 minutes.
*.empresa.com.br does not cover:
empresa.com.br (no subdomain)dev.app.empresa.com.br (subdomain of subdomain)Revoke immediately and issue a new one. Attacker with your key can impersonate your domain.
Prevention:
chmod 600Since 2018, public certificates need to be in CT logs. Use crt.sh to monitor:
https://crt.sh/?q=empresa.com.br
If a certificate appears that you didn't authorize, it's a sign of compromise.
Verify:
openssl s_client -connect empresa.com.br:443 -status </dev/null 2>&1 | grep -A 17 'OCSP response:'
List of revoked certificates. Grows indefinitely, expensive to download, cached for hours.
Replaces CRL. Client asks the CA directly. Privacy problem.
Server periodically consults and "staples" to the handshake. Faster, more private.
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/empresa.com.br/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
Requires stapling. Stronger, but requires server always reaches the CA.
Public auditable log. Today mandatory. Use crt.sh to monitor.
Whitelist of authorized CAs via DNS:
empresa.com.br. IN CAA 0 issue "letsencrypt.org"
empresa.com.br. IN CAA 0 issuewild "letsencrypt.org"
empresa.com.br. IN CAA 0 iodef "mailto:security@empresa.com.br"
Always configure. Simple, free, real protection.
Normal TLS only authenticates the server. mTLS authenticates both sides — client also presents a certificate.
Result: server mathematically knows who the client is before any application data is exchanged.
Nginx:
server {
listen 443 ssl;
server_name api.empresa.com.br;
ssl_certificate /etc/letsencrypt/live/api.empresa.com.br/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.empresa.com.br/privkey.pem;
# mTLS
ssl_verify_client on;
ssl_client_certificate /etc/nginx/ssl/clients-ca.crt;
ssl_verify_depth 2;
location / {
proxy_pass http://backend;
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
proxy_set_header X-SSL-Client-Serial $ssl_client_serial;
}
}
Apache:
<VirtualHost *:443>
ServerName api.empresa.com.br
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/api.empresa.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/api.empresa.com.br/privkey.pem
SSLVerifyClient require
SSLVerifyDepth 2
SSLCACertificateFile /etc/apache2/ssl/clients-ca.crt
<Location />
SSLOptions +StdEnvVars
RequestHeader set X-SSL-Client-DN "%{SSL_CLIENT_S_DN}s"
</Location>
</VirtualHost>
Curl Client:
curl --cert client.crt --key client.key https://api.empresa.com.br/recurso
Python Client:
import requests
response = requests.get(
'https://api.empresa.com.br/recurso',
cert=('client.crt', 'client.key'),
verify='ca-bundle.crt'
)
Makes a lot of sense:
Doesn't make as much sense:
Cloudflare/CloudFront/Akamai in front of the website. But the origin is still directly accessible — whoever discovers the real IP bypasses the entire CDN, WAF, rate limits.
Attempts to solve:
Modes:
server {
listen 443 ssl;
server_name origin.empresa.com.br;
ssl_certificate /etc/ssl/origin.crt;
ssl_certificate_key /etc/ssl/origin.key;
ssl_client_certificate /etc/ssl/cloudflare-origin-ca.pem;
ssl_verify_client on;
}
Result: even if they discover the real IP, the connection is rejected at handshake. Origin is effectively hidden.
Uses AWS Certificate Manager Private CA. Same concept.
mTLS with CDN is an elegant solution to an old problem. Implementation costs hours. Protection lasts forever.
Standard protocol (RFC 8555) for automation. Supported by Let's Encrypt, ZeroSSL, Google Trust, DigiCert, Sectigo, step-ca, Vault.
Clients:
Why? Limits compromise window. And it only works because automation solved the operational part.
Quantum computers will break RSA and ECDSA via Shor's algorithm. NIST finalized standards in 2024:
In 2026, browsers and CDNs already implement hybrids (classic + post-quantum). Cloudflare since 2023, Chrome since 2024.
Concern: "harvest now, decrypt later" — attackers capturing today to decrypt when they have quantum.
Ed25519 is state of the art:
Prefer ECDSA P-256 or Ed25519 to RSA for new certificates.
Finalized in 2018:
In 2026, TLS 1.3 should be mandatory. TLS 1.0/1.1 are dead.
Nginx (Mozilla intermediate):
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_ecdh_curve X25519:secp384r1:secp256r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/empresa.com.br/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
Modern (TLS 1.3 only):
ssl_protocols TLSv1.3;
Use Mozilla SSL Configuration Generator: https://ssl-config.mozilla.org/
For any production change:
Goal: A+ on both.
# /etc/cron.d/certbot-renew
0 3 * * * root certbot renew --quiet --post-hook "systemctl reload nginx"
And monitor that it's working. Renewal that silently stopped is the worst case.
PUBLIC CERTIFICATES
[ ] Trusted CA
[ ] Complete chain (fullchain.pem)
[ ] SAN includes all names
[ ] Wildcard configured correctly
[ ] Validity monitored (60/30/14/7)
[ ] Renewal automated via ACME
[ ] CAA records configured
[ ] Private key chmod 600
[ ] Key never in git
[ ] Monitoring via crt.sh
TLS CONFIGURATION
[ ] TLS 1.2 and 1.3 only
[ ] TLS 1.0 and 1.1 disabled
[ ] Mozilla intermediate or modern ciphers
[ ] OCSP Stapling working
[ ] HSTS configured carefully
[ ] Modern curves (X25519, P-256)
[ ] Session tickets disabled
VALIDATION
[ ] SSL Labs A or A+
[ ] Hardenize A or A+
[ ] testssl.sh no warnings
[ ] No mixed content
[ ] No incomplete chain
[ ] No hostname mismatch
mTLS (when applicable)
[ ] Private CA for issuance
[ ] Secure distribution to clients
[ ] Automated rotation
[ ] Revocation configured
[ ] Authentication logs
[ ] Clear documentation
CDN WITH mTLS
[ ] Authenticated Origin Pulls enabled
[ ] Origin rejects connections without cert
[ ] Real IP not exposed
[ ] Tested from external IP
[ ] Bypass monitoring
OPERATIONAL
[ ] Centralized inventory
[ ] Manual fallback procedure
[ ] Revocation procedure
[ ] Compromise response plan
[ ] Team training
TLS certificates are one of those technologies that aged well. SSL was born in 1994, the math is from the 70s-80s, and it's still what keeps the internet running. But the ecosystem changed drastically in the last 10 years: free became standard, automation solved operations, validity keeps getting shorter, mTLS is becoming mandatory for serious integration.
The difference between who understands this and who doesn't is the difference between who sleeps peacefully next Friday and who spends the night explaining to the boss why the site is down.
Clear trend: certificate-based authentication will become increasingly important. Post-quantum, short certificates, mTLS everywhere, universal service mesh, Zero Trust as standard. Whoever masters certificates in the coming years will be well positioned for practically everything.
SentinelHub sweeps exactly these problems: monitors TLS certificates, alerts on expiration (60/30/14/7 days), detects incomplete chain, identifies weak ciphers, verifies TLS 1.0/1.1, detects hostname mismatch, monitors Certificate Transparency for unauthorized issuances. In Portuguese.
Because the problem isn't configuring it once — it's keeping it running every single day.
Found it useful? Share it with your infrastructure team. Especially with that sysadmin who still has a self-signed certificate in production saying "I'll change it later".