
September 12, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Every HTTPS handshake, API mTLS connection, and code-signing check depends on a small binary document most developers never open. The anatomy of an X.509 Certificate is the map you need when TLS fails in production, a browser shows NET::ERR_CERT_AUTHORITY_INVALID, or a client portal rejects a document upload signed with the wrong key. If you already understand SSL/TLS certificates at a high level, this guide goes one layer deeper into the actual bytes, fields, and extensions your web server presents to the world.
What is the basic structure of an X.509 certificate?
An X.509 v3 certificate is defined in RFC 5280. It is not JSON or XML. It is ASN.1 encoded, usually wrapped in PEM or DER for transport. Think of it as three nested layers: the payload, the signing algorithm identifier, and the cryptographic proof.
The payload is the TBSCertificate (To Be Signed). Everything inside TBSCertificate is what the Certificate Authority hashes and signs. Change one bit in TBSCertificate and the signature breaks. That is why reissuing a cert with a new SAN always produces a new file even when the key pair stays the same.
The outer Certificate SEQUENCE always contains exactly three elements in order:
- TBSCertificate — identity, validity window, subject public key, and optional extensions.
- signatureAlgorithm — OID naming the hash and signature scheme (for example
sha256WithRSAEncryption). - signatureValue — the CA's signature over the DER encoding of TBSCertificate.
On production Ubuntu servers I maintain for Linux hosting and TLS termination, the first debugging step after a deploy is still openssl x509 -in fullchain.pem -text -noout. That command pretty-prints the same structure RFC 5280 describes.
Version and serial number
Version is an integer: v1 = 0, v2 = 1, v3 = 2. Every publicly trusted web certificate today is v3. Version 3 introduced the extensions block, which is where Subject Alternative Names (SAN), key usage, and OCSP pointers live.
Serial number must be unique per issuer. CAs generate long random serials to avoid collision and predictable values. Browsers and operating systems may reject serials that are negative, zero, or too short under current Baseline Requirements.
How does ASN.1 encoding relate to the anatomy of an X.509 certificate?
ASN.1 is a schema language. DER is its strict binary encoding. PEM is Base64 with header/footer lines around DER. When you paste a cert into a Base64 encoder or decoder, you are looking at the same bytes OpenSSL reads—just wrapped for text transport.
Each field has a tag-length-value triple. A SEQUENCE wraps ordered children. An OID identifies algorithms and extension types by numeric arc, not by name. That is why OpenSSL output shows strings like 1.2.840.113549.1.1.11 beside human-readable labels.
Common encodings you will encounter in the wild:
- DER — binary, canonical, used on the wire during TLS.
- PEM — text file starting with
-----BEGIN CERTIFICATE-----. - PKCS#7 / P7B — chain container, often from Windows CAs.
- PKCS#12 / PFX — cert + private key bundle, password-protected.
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQALrzSp9...
-----END CERTIFICATE----- Strip the armor lines and decode the Base64 body. You get DER. Feed that to openssl asn1parse -inform DER -in cert.der and you see the nested SEQUENCE tree that mirrors the diagram above. Understanding this stack saves hours when a load balancer expects PEM but your vendor emailed a .cer DER file.
What are the critical fields inside the TBSCertificate?
The TBSCertificate is where hostname mismatches, expired legal portals, and broken API clients originate. These fields deserve line-by-line attention.
Issuer and subject Distinguished Names
Issuer identifies who signed the certificate. Subject identifies who the certificate is issued to. Each is an X.500 Distinguished Name (DN): a SET of Relative Distinguished Name components such as CN, O, OU, C, ST, and L.
For a typical Let's Encrypt web cert, subject CN might equal one hostname, but the authoritative identity list is in the SAN extension. Legacy clients that ignore SAN caused real outages years ago. Modern validators require SAN for HTTPS when present.
Validity period
notBefore and notAfter are UTCTime or GeneralizedTime values. A cert is invalid outside that window regardless of chain trust. Public CAs now issue shorter-lived certs—often 90 days—which pushes teams toward automation covered in our guide on automating certificate rotation.
Clock skew matters. I've seen staging servers reject valid certs because NTP was wrong by ten minutes. Always verify system time before blaming the CA.
SubjectPublicKeyInfo
This block holds the algorithm OID and the public key bit string. RSA certs embed modulus and exponent. ECDSA certs embed the curve name and EC point. The private key never appears inside an X.509 certificate—only the public half.
Key size and algorithm must match what your stack supports. PHP 8.3+ and OpenSSL 3.x on Ubuntu 24.04 handle RSA 2048/4096 and curves P-256/P-384 without drama. Legacy 1024-bit RSA should be gone from production in 2026.
Extensions that break production if wrong
Extensions are typed as critical or non-critical. A client that does not understand a critical extension must reject the cert. These four extensions appear on nearly every public TLS certificate:
- Subject Alternative Name (SAN) — DNS names, IP addresses, email, or URIs the cert covers.
- Key Usage — bit flags for digitalSignature, keyEncipherment, keyCertSign, cRLSign, and others.
- Extended Key Usage (EKU) — purpose OIDs such as id-kp-serverAuth or id-kp-clientAuth.
- Authority Information Access (AIA) — URLs for issuer cert download and OCSP responders.
Basic Constraints includes the CA:TRUE flag. End-entity web certs must show CA:FALSE. A mis-issued intermediate with wrong constraints can take down trust for an entire brand. That is core PKI and certificate management territory.
| Field / Extension | What it controls | Typical failure symptom |
|---|---|---|
| Subject CN | Legacy common name identity | Warning if SAN missing and CN mismatches |
| SAN (DNS) | Allowed hostnames for TLS | Certificate name mismatch in browser |
| notAfter | Expiry instant | ERR_CERT_DATE_INVALID |
| EKU serverAuth | TLS server role | Handshake rejected by strict clients |
| AIA caIssuers | Parent cert fetch URL | Incomplete chain on mobile networks |
| Subject Key Identifier | Hash of public key | Chain building ambiguity with reissued keys |
For client portals that handle uploads and payments—like the Mijar Law Associates secure portal—a missing intermediate in the chain file is the most common TLS defect I fix after migration. The leaf cert alone is never enough.
How do you inspect the anatomy of an X.509 certificate with OpenSSL?
OpenSSL is the reference toolchain. It ships on Ubuntu server images and remains the fastest way to decode cert anatomy without GUI tools. The official openssl-x509 manual page documents every flag below.
Human-readable dump
openssl x509 -in fullchain.pem -text -noout Read the output top to bottom. Confirm version 3, note serial, verify issuer matches your CA, list SAN entries, and check Signature Algorithm against your security policy. SHA-1 signatures should not appear on new public certs.
Check dates and fingerprint
openssl x509 -in cert.pem -noout -dates
openssl x509 -in cert.pem -noout -fingerprint -sha256 Store fingerprints in your deploy runbook. When a CDN or WAF swaps certs silently, the SHA-256 fingerprint is the ground truth. Pinning by fingerprint is rare on public sites but common in internal API meshes.
Verify chain and hostname locally
openssl verify -CAfile chain.pem leaf.pem
openssl s_client -connect example.com:443 -servername example.com \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName The s_client call shows what the world actually receives. Compare it to the file on disk. Mismatch means the wrong vhost, stale symlink, or a CDN edge cert you forgot about.
When debugging regex-heavy log filters for cert expiry alerts, a regex tester helps validate patterns against sample OpenSSL output before you push them into CI.
Convert between PEM and DER
openssl x509 -in cert.cer -inform DER -out cert.pem -outform PEM
openssl x509 -in cert.pem -outform DER -out cert.der Windows and Java tooling often emits DER .cer files. Apache and Nginx want PEM. Conversion is lossless for the certificate itself—no reissue required.
Detailed server placement steps live in our install SSL certificates on Ubuntu guide. Anatomy knowledge tells you what you are installing; that guide covers where it goes.
How does the X.509 certificate chain of trust work?
A single certificate rarely stands alone. Trust is transitive. Your leaf cert is signed by an intermediate CA. That intermediate is signed by a root CA preloaded in the client's trust store.
Validation walks upward until it finds a trusted anchor. Each link must sign the TBSCertificate of the child below it. The root's public key is self-signed, but the root is trusted because the OS or browser vendor put it there—not because cryptography magically says so.
Your fullchain.pem should contain leaf first, then intermediates. Never include the root in the served chain—extra bytes on every handshake, and some stacks behave badly. Roots stay in the trust store only.
On domain and hosting setups in Nepal, shared cPanel hosts sometimes deliver only the leaf. Download the CA bundle from your issuer and concatenate manually. One missing intermediate produces errors on Android but not on desktop Chrome—a frustrating pattern if you test on one browser only.
Cloud secret stores—see Azure Key Vault keys, secrets, and certificates—often inject just the leaf into App Service. You must upload the intermediate separately or enable automatic chain fetching via AIA, which not all runtimes do reliably.
What is the difference between PEM, DER, and PKCS#12 for X.509 files?
Same certificate anatomy, different envelopes. Pick the format your server, language runtime, or HSM expects.
Extract a private key from PKCS#12 only on a secure workstation. Rotate the export password if you must share the file. For Laravel or API apps behind mTLS, I store PEM splits in environment variables and mount paths documented in API development workflows—never the PFX blob in the repo.
Nepal government and banking workflows sometimes reference digital signature certificates for web apps. Those certs follow the same X.509 anatomy with different EKU bits and stricter identity proofing at issuance time.
Key Takeaways
- An X.509 certificate is TBSCertificate + signatureAlgorithm + signatureValue, encoded as ASN.1 DER and often wrapped in PEM.
- Hostname trust for HTTPS comes from the SAN extension, not the subject CN alone—always verify SAN in OpenSSL output.
- Serve leaf plus intermediate certs in
fullchain.pem; keep the root out of the live chain file. - Use
openssl x509 -text -nooutandopenssl s_clientto compare on-disk files against what the public internet receives. - Match file format to your stack: PEM for Nginx/Apache, DER for some Java tools, PKCS#12 when the platform demands a bundled key.
- Short-lived public certs make field-level understanding essential—expiry and serial changes become routine deploy events, not annual fire drills.
People Also Ask
What is the difference between X.509 and TLS?
TLS is the protocol that encrypts traffic between client and server. X.509 is the certificate format TLS uses to authenticate the server's identity during the handshake. You can have X.509 certs for email, code signing, and document signing without TLS involved.
Why does my certificate have two signature algorithms?
TBSCertificate includes a copy of the signature algorithm identifier for historical reasons, and the outer Certificate repeats it before signatureValue. Both must align. Mismatch causes immediate rejection during chain validation.
Can two certificates share the same public key?
Yes. Reissue events often generate a new TBSCertificate and serial while reusing the same key pair. Fingerprints of the public key stay the same; the cert fingerprint changes because the signed bytes differ.
What happens if an extension is marked critical?
Any software that cannot parse that extension must reject the certificate per RFC 5280. That is why public CAs mark most web extensions as non-critical—broad compatibility depends on it.
Put the anatomy of an X.509 certificate to work on your stack
Understanding the anatomy of an X.509 certificate turns TLS from a black box into a checklist you can run in five minutes. Read TBSCertificate fields, confirm SAN and dates, verify the chain, and compare served bytes to disk. That workflow prevents most production cert incidents before users see a browser warning.
If you are launching a portal, eCommerce store, or API that needs correct TLS from day one, review our web development service and testing and optimization offerings. For ongoing renewals and chain fixes after migration, support and maintenance covers the operational side. See live examples on the Court Marriage in Nepal and Notary Nepal portfolio entries—both run HTTPS-backed lead flows in production.
Need help auditing certs on your server or wiring automated renewal into Deployer or GitLab CI? Contact us with your domain and stack details. Bring one sample PEM and the OpenSSL output—we can tell you quickly whether the anatomy looks right or the chain is incomplete.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

