Key idea
A certificate ties a name, like app.example.com, to a key the server holds, and it's signed by a certificate authority (CA). Your browser trusts it only if those signatures lead back to a root CA that your device already trusts.
The chain
A certificate chain
- Subject
- Example Root CA
- Issuer
- Itself (self-signed)
- Valid
- Jun 2015 – Jun 2040
- Subject
- Example Issuing CA
- Issuer
- Example Root CA
- Valid
- Mar 2024 – Mar 2027
- Subject
- app.example.com
- Issuer
- Example Issuing CA
- Valid
- Sep 1 – Nov 30, 2026
Your operating system and browser ship with a short list of root CAs. Roots rarely sign sites directly; they sign intermediate CAs, which sign the leaf certificate your server uses. The server sends the leaf and the intermediate, and the browser follows the signatures up to a root it already has.
Keeping roots offline and signing through intermediates means a leaked intermediate key can be replaced without updating every device.
Three fields worth reading
- Subject and names. Browsers check the list of names in the certificate (its subject alternative names). A wildcard such as
*.example.comcoversapp.example.com, but notexample.comitself ora.b.example.com. - Issuer. The CA that signed it. On a leaf certificate this is usually an intermediate.
- Validity. A start date and an expiry date. Many public certificates last 90 days, and the maximum is shrinking toward 47 days by 2029, so renewal has to be automatic.
Try it: read a real certificate
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
In PowerShell:
$tcp = [Net.Sockets.TcpClient]::new("example.com", 443)
$tls = [Net.Security.SslStream]::new($tcp.GetStream())
$tls.AuthenticateAsClient("example.com")
[Security.Cryptography.X509Certificates.X509Certificate2]::new($tls.RemoteCertificate) |
Format-List Subject, Issuer, NotBefore, NotAfter
$tcp.Close()
You get four lines: the subject (CN=example.com), the issuer, and the start and expiry dates. -servername sends the name in the hello, so a server hosting many sites returns the right certificate. Try a site you use every day and compare its issuer and expiry.
How a CA decides to sign
Before issuing, the CA asks you to prove you control the domain: serve a token at a URL on it, or publish a DNS record it names. That's why getting a certificate usually starts with DNS pointing at your server.
Operating system and browser makers audit the CAs on their root lists. A CA that signs carelessly can be removed from those lists, and then browsers stop trusting what it issued.
What about self-signed certificates?
A self-signed certificate skips the CA: it signs itself. It encrypts just as well, but no device trusts it, so browsers show an error. It's fine for local testing, never for a public site.
Check yourself