Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Anatomy of an X.509 Certificate

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.

X.509 Certificate LayersCertificate (SEQUENCE)TBSCertificateVersionSerialIssuerSubjectValidityPublic KeyExtensionsv3 onlysignatureAlgorithme.g. sha256WithRSAsignatureValueCA proofCA private key signs hash of TBSCertificate
Anatomy of an X.509 certificate: the TBSCertificate block holds identity and key data; the CA signs it to produce the final Certificate object.

The outer Certificate SEQUENCE always contains exactly three elements in order:

  1. TBSCertificate — identity, validity window, subject public key, and optional extensions.
  2. signatureAlgorithm — OID naming the hash and signature scheme (for example sha256WithRSAEncryption).
  3. 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.

TBSCertificate Field MapIdentity Fieldsissuer: CN=Let's Encrypt R3, O=ISRGsubject: CN=example.comserial: 03:a1:... (unique)version: v3 (value 2)Crypto + TimenotBefore: 2026-06-01 UTCnotAfter: 2026-08-30 UTCpubkey: rsaEncryption 2048-bitsig alg inside TBSCert tooExtensions (X.509 v3)Subject Alt NameDNS + IP namesKey UsagedigitalSignatureEKUserverAuth OIDAIAissuer URL
Core TBSCertificate fields and v3 extensions that define hostname coverage, allowed key operations, and chain-building URLs.

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 / ExtensionWhat it controlsTypical failure symptom
Subject CNLegacy common name identityWarning if SAN missing and CN mismatches
SAN (DNS)Allowed hostnames for TLSCertificate name mismatch in browser
notAfterExpiry instantERR_CERT_DATE_INVALID
EKU serverAuthTLS server roleHandshake rejected by strict clients
AIA caIssuersParent cert fetch URLIncomplete chain on mobile networks
Subject Key IdentifierHash of public keyChain 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.

Certificate Chain of TrustRoot CAIn OS trust storesignsIntermediate CASent in fullchain.pemsignsLeaf / End-Entity CertYour domain + public keyBrowser validates signatures upward; root must be trusted locally
Chain of trust anatomy: the leaf cert proves domain ownership; intermediates bridge to a root already trusted by the client.

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.

Certificate File FormatsPEMBase64 + headersApache / NginxGit-friendly textDERBinary ASN.1Java / WindowsSmaller on diskPKCS#12Cert + key bundlePassword lockedIIS / macOS KeychainSame X.509 TBSCertificate inside all threePEMDERPFXopenssl pkcs12 -export combines key + chainNever commit PKCS#12 files to Git
PEM, DER, and PKCS#12 are transport wrappers around the same X.509 certificate anatomy—not different standards.

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 -noout and openssl s_client to 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

A signed ASN.1 structure with three parts: TBSCertificate (version, serial, issuer, subject, validity, public key, extensions), signatureAlgorithm, and signatureValue. Browsers validate chain, dates, and key usage before trusting it.

RFC 5280 defines the outer Certificate SEQUENCE as exactly three ordered elements. TBSCertificate holds identity, validity window, subject public key, and optional v3 extensions—the payload the CA hashes and signs. signatureAlgorithm is an OID naming the hash and signature scheme, such as sha256WithRSAEncryption. signatureValue is the CA's cryptographic signature over the DER encoding of TBSCertificate. Change one bit inside TBSCertificate and the signature breaks, which is why reissuing with a new SAN always produces a new file even when the key pair stays the same.

TBSCertificate means To Be Signed—it is the inner payload everything else wraps. Issuer and subject DNs, notBefore and notAfter dates, SubjectPublicKeyInfo, and extensions like SAN all live here. Hostname mismatches, expired legal portals, and broken API clients usually trace back to TBSCertificate fields, not the outer signature wrapper. On production Ubuntu servers, openssl x509 -in fullchain.pem -text -noout pretty-prints this same block. When TLS fails after deploy, read TBSCertificate top to bottom before blaming the CA.

ASN.1 is the schema language; DER is its strict binary encoding; PEM is Base64 with header and footer lines around DER. Each field uses a tag-length-value triple, and SEQUENCE wraps ordered children. OIDs identify algorithms and extension types by numeric arc, which is why OpenSSL shows strings like 1.2.840.113549.1.1.11 beside human-readable labels. Strip PEM armor, decode Base64, and you get DER—the same bytes TLS sends on the wire. Feed DER to openssl asn1parse -inform DER and you see the nested tree that mirrors the certificate diagram.

SAN is a v3 extension listing DNS names, IP addresses, email addresses, or URIs the certificate covers. For a typical Let's Encrypt web cert, subject CN might equal one hostname, but the authoritative identity list is in SAN. Modern validators require SAN for HTTPS when present; legacy clients that ignored SAN caused real outages years ago. A warning or name mismatch in the browser usually means SAN does not include the hostname you typed. Always verify SAN entries in OpenSSL output, not CN alone.

Four extensions appear on nearly every public TLS certificate. SAN controls allowed hostnames. Key Usage sets bit flags for digitalSignature, keyEncipherment, and related operations. Extended Key Usage includes purpose OIDs such as id-kp-serverAuth for TLS servers. Authority Information Access provides URLs for issuer cert download and OCSP responders. Basic Constraints must show CA:FALSE on end-entity web certs. A missing intermediate in the chain file—often an AIA caIssuers fetch failure—is the most common TLS defect after migration on client portals that handle uploads and payments.

Same certificate anatomy, different transport envelopes. DER is binary and canonical—used on the wire during TLS. PEM is a text file starting with -----BEGIN CERTIFICATE----- around Base64-encoded DER; Apache and Nginx expect PEM. PKCS#7 or P7B is a chain container common from Windows CAs. PKCS#12 or PFX bundles certificate plus private key, password-protected. Conversion between PEM and DER is lossless for the certificate itself—no reissue required. Windows and Java tooling often emit DER .cer files while load balancers and Linux web servers want PEM.

TLS encrypts traffic between client and server. X.509 is the certificate format TLS uses to authenticate identity during the handshake. X.509 also serves email, code signing, and document signing without TLS.

TBSCertificate includes a copy of the signature algorithm identifier for historical reasons, and the outer Certificate repeats it again before signatureValue. Both must align; a mismatch causes immediate rejection during chain validation. When reading openssl x509 -text output, check Signature Algorithm on the TBSCertificate block and the outer algorithm line. SHA-1 signatures should not appear on new public certs—confirm your policy matches sha256WithRSAEncryption or an equivalent modern scheme.

Start with openssl x509 -in fullchain.pem -text -noout for a human-readable dump—confirm version 3, serial, issuer, SAN, and signature algorithm. Check dates with openssl x509 -in cert.pem -noout -dates and store SHA-256 fingerprints via -fingerprint -sha256 in your deploy runbook. Verify chain locally with openssl verify -CAfile chain.pem leaf.pem. See what the public internet receives with openssl s_client -connect example.com:443 -servername example.com piped to openssl x509 -noout. Mismatch between disk and s_client output means wrong vhost, stale symlink, or CDN edge cert.

fullchain.pem should contain the leaf certificate first, then intermediate certificates in order. Never include the root in the served chain—extra bytes on every handshake, and some stacks behave badly. Roots belong only in the client trust store. A single leaf cert alone is never enough; one missing intermediate produces errors on Android but not always on desktop Chrome—a frustrating pattern if you test on one browser only. On shared cPanel hosts in Nepal, download the CA bundle from your issuer and concatenate manually when only the leaf is delivered.

Trust is transitive, not absolute. Your leaf cert is signed by an intermediate CA, which 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 placed it there—not because cryptography alone declares it trustworthy. Incomplete chains—missing intermediates—are the most common cause of NET::ERR_CERT_AUTHORITY_INVALID on mobile clients.

Per RFC 5280, any software that cannot parse a critical extension must reject the certificate. Public CAs mark most web extensions as non-critical for broad compatibility.

Yes. Reissue events often generate a new TBSCertificate and serial while reusing the same key pair. The private key never appears inside an X.509 certificate—only the public half in SubjectPublicKeyInfo. Fingerprints of the public key stay the same across reissues, but the certificate fingerprint changes because the signed bytes differ. Subject Key Identifier, a hash of the public key, helps chain-building tools distinguish reissued certs. When a CDN or WAF swaps certs silently, SHA-256 fingerprint of the full cert is ground truth for what is actually deployed.

notBefore and notAfter define the validity window—a cert is invalid outside that window regardless of chain trust, producing ERR_CERT_DATE_INVALID. Clock skew matters; staging servers with wrong NTP time by even ten minutes can reject valid certs, so verify system time before blaming the CA. Hostname warnings come from SAN not listing the requested name, or legacy CN-only validation edge cases. Public CAs now issue shorter-lived certs, often 90 days, so expiry and serial changes become routine deploy events. Check SAN, dates, and chain completeness with OpenSSL before users see browser warnings.

Share this article

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.

Quick Contact Options
Choose how you want to connect me: