X.509 Certificates Explained — PEM, DER, and How to Parse Them
Every HTTPS connection, every signed email, every code-signed binary depends on X.509 certificates. They're the identity cards of the internet — binding a public key to a name, an organization, and a set of permissions. But when you open a .pem or .crt file, you see a wall of Base64. This guide explains exactly what's inside an X.509 certificate, how to parse it, and how to use our X.509 Cert Parser to inspect certificates without installing anything.
1. What Is an X.509 Certificate?
X.509 is the ITU-T standard (first published 1988) that defines the format for public key certificates. A certificate is a digitally signed document that binds a public key to an identity. It says: "This RSA 2048-bit public key belongs to example.com, and VeriSign vouches for it."
The current version is X.509 v3 (introduced 1996), which added the extension mechanism that powers modern features like Subject Alternative Names (SANs) and Certificate Transparency.
2. PEM vs DER — The Two Formats
X.509 certificates appear in two common encodings. They contain exactly the same data — only the wrapper differs.
DER (Distinguished Encoding Rules)
DER is the raw binary format. It's a stream of bytes following ASN.1 encoding rules. DER certificates use the .der or .cer extension. If you open one in a text editor, you'll see garbage — it's binary.
# Hex dump of a DER certificate (first 32 bytes)
30 82 03 3F 30 82 02 27 A0 03 02 01 02 02 09 00
E1 8A 7F 3C 8B 2F 7A 91 30 0D 06 09 2A 86 48 86
The first byte 30 is the ASN.1 SEQUENCE tag — every X.509 certificate starts here. The 82 03 3F tells us the total certificate is 831 bytes long.
PEM (Privacy-Enhanced Mail)
PEM is DER wrapped in Base64 with header and footer lines. It's the format you'll see 99% of the time. PEM files use .pem, .crt, or .key extensions.
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQ...
...more Base64 lines...
-----END CERTIFICATE-----
The conversion is simple: PEM = "-----BEGIN CERTIFICATE-----" + Base64(DER) + "-----END CERTIFICATE-----". Our Base64 Encoder can decode the PEM body to reveal the DER bytes underneath.
-----BEGIN, it's PEM. If it starts with 0x30 byte or looks like hex, it's DER. Our X.509 Cert Parser auto-detects both.3. Anatomy of an X.509 Certificate
Every X.509 v3 certificate contains these fields. Let's walk through them using a real example — the certificate for cupass.com.
| Field | Example Value | What It Means |
|---|---|---|
| Version | v3 | X.509 version. v3 is universal today (adds extensions). |
| Serial Number | 00e18a7f3c8b2f7a91 | Unique ID assigned by the issuer. Used in CRLs (revocation lists). |
| Signature Algorithm | SHA-256 with RSA | How the issuer signed this certificate. Modern certs use SHA-256; avoid SHA-1. |
| Issuer | CN=Let's Encrypt, C=US | Who issued (signed) this certificate. For self-signed certs, issuer = subject. |
| Subject | CN=cupass.com | Who this certificate identifies. The Common Name (CN) was historically the domain, but modern validation uses SANs. |
| Valid From / To | 2026-07-02 to 2026-09-30 | Validity window. Let's Encrypt issues 90-day certs; commercial CAs offer 1 year. |
| Public Key | RSA 2048-bit / EC P-256 | The actual cryptographic key. RSA keys show modulus + exponent; EC keys show the curve. |
| Extensions | SANs, Key Usage, etc. | v3 extensions define what the certificate can be used for. See Section 4 below. |
Why the Subject Alone Isn't Enough
Before SANs (Subject Alternative Names), browsers checked the Common Name (CN) in the Subject field to verify the domain. This had obvious problems: a single certificate for example.com and www.example.com required two separate certs or a wildcard *.example.com (which doesn't match the bare domain).
Today, browsers ignore the CN entirely if SANs are present. The SAN extension lists all domains the certificate is valid for.
4. Critical X.509 v3 Extensions
Extensions are the real power of v3. Here are the ones you'll encounter most often:
Subject Alternative Name (SAN) — OID 2.5.29.17
The most important extension. Lists all DNS names, IP addresses, and email addresses the certificate covers.
DNS: cupass.com
DNS: www.cupass.com
DNS: *.cupass.com
www.example.com does NOT automatically cover example.com. Both must be listed in the SANs. This is the #1 cause of "Your connection is not private" errors after deploying a new certificate.Key Usage — OID 2.5.29.15
Defines what cryptographic operations the public key is authorized for:
| Flag | Meaning |
|---|---|
| digitalSignature | Can sign data (TLS server authentication) |
| keyEncipherment | Can encrypt session keys (RSA key transport in TLS) |
| keyCertSign | Can sign other certificates (CA certificates only) |
| cRLSign | Can sign Certificate Revocation Lists (CA only) |
A typical TLS server certificate has digitalSignature + keyEncipherment. A CA certificate has keyCertSign + cRLSign.
Basic Constraints — OID 2.5.29.19
Marks whether the certificate belongs to a CA (Certificate Authority) or an end entity. If CA: TRUE, the certificate can sign other certificates. The optional pathlen parameter limits how deep the CA chain can go (pathlen=0 means "can only sign end-entity certs, not intermediate CAs").
Extended Key Usage (EKU) — OID 2.5.29.37
Further narrows down the purpose:
| EKU | OID | Used For |
|---|---|---|
| serverAuth | 1.3.6.1.5.5.7.3.1 | TLS server certificates (HTTPS) |
| clientAuth | 1.3.6.1.5.5.7.3.2 | TLS client certificates (mTLS) |
| codeSigning | 1.3.6.1.5.5.7.3.3 | Signing executables and scripts |
| emailProtection | 1.3.6.1.5.5.7.3.4 | S/MIME email signing and encryption |
5. Certificate Fingerprints
A fingerprint is a hash of the entire DER-encoded certificate. It's a short, unique identifier you can compare manually. When you download software or connect to a service, comparing fingerprints verifies you have the right certificate — no CA trust chain needed.
SHA-1: 6A:5E:3C:2F:91:88:4D:02:BB:71:8A:3F:19:5C:77:2E:AA:14:6D:09
SHA-256: F3:1A:8B:44:2C:6D:9E:71:0A:55:33:BF:8E:12:49:7C:
3D:2E:91:5A:88:6F:11:4B:CC:77:22:EA:19:33:5D:80
SHA-1 fingerprints are deprecated for security decisions (collision attacks exist), but they're still widely displayed. SHA-256 is the modern standard. Both are computed over the full DER certificate — the signature is not included in the hash input.
6. The Certificate Chain
A certificate alone is useless without a trust chain back to a root CA your system trusts. The full chain during a TLS handshake looks like:
[End-Entity: cupass.com] → [Intermediate: Let's Encrypt R3] → [Root: ISRG Root X1]
── Signed by R3 ── ── Signed by Root ── ── In your trust store ──
The server typically sends the end-entity cert + the intermediate(s). The root must already be in the client's trust store (your OS or browser ships with ~150 root CAs).
How to View a Site's Chain
# Show full chain from a live server
openssl s_client -connect cupass.com:443 -showcerts < /dev/null 2>/dev/null
# Save each certificate (between BEGIN/END lines) to separate files
# Then inspect each one
openssl x509 -in cert.pem -text -noout
7. Parsing Certificates: Three Ways
7.1 Online — No Installation Required
Use our X.509 Cert Parser. Paste any PEM or hex DER certificate and get all fields, fingerprints, and extensions decoded instantly. No data leaves your browser. Also try the ASN.1 DER Parser to see the raw tag-length-value structure underneath.
7.2 OpenSSL Command Line
# Full text dump of a PEM certificate
openssl x509 -in certificate.pem -text -noout
# Show just the subject and issuer
openssl x509 -in certificate.pem -subject -issuer -noout
# Show SANs
openssl x509 -in certificate.pem -ext subjectAltName -noout
# Show fingerprints
openssl x509 -in certificate.pem -fingerprint -sha256 -noout
# Check if cert is still valid
openssl x509 -in certificate.pem -checkend 86400 && echo "OK" || echo "EXPIRING"
# Convert between formats
openssl x509 -in certificate.der -inform DER -out certificate.pem -outform PEM
7.3 Python (cryptography library)
from cryptography import x509
from cryptography.hazmat.primitives import hashes
# Load a PEM certificate
with open("certificate.pem", "rb") as f:
cert = x509.load_pem_x509_certificate(f.read())
# Basic fields
print(f"Subject: {cert.subject.rfc4514_string()}")
print(f"Issuer: {cert.issuer.rfc4514_string()}")
print(f"Valid: {cert.not_valid_before_utc} → {cert.not_valid_after_utc}")
print(f"Serial: {cert.serial_number}")
# SANs
sans = cert.extensions.get_extension_for_oid(
x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME
)
for name in sans.value:
print(f" SAN: {name.value}")
# Fingerprint
fp = cert.fingerprint(hashes.SHA256()).hex().upper()
print(f"SHA-256: {':'.join(fp[i:i+2] for i in range(0, len(fp), 2))}")
# Public key
pk = cert.public_key()
if hasattr(pk, 'key_size'):
print(f"RSA {pk.key_size}-bit")
else:
print(f"EC {pk.curve.name}")
8. Common Certificate Errors and Fixes
| Error | Cause | Fix |
|---|---|---|
ERR_CERT_COMMON_NAME_INVALID | Domain not in SAN list | Reissue certificate with the correct SANs. Check for missing www or bare domain. |
ERR_CERT_DATE_INVALID | Certificate expired | Renew the certificate. Set up auto-renewal (Let's Encrypt certbot). |
ERR_CERT_AUTHORITY_INVALID | Untrusted CA or missing intermediate | Ensure the server sends the full chain (end-entity + intermediate). Check your CA bundle. |
ERR_CERT_WEAK_SIGNATURE_ALGORITHM | SHA-1 signature | Reissue with SHA-256. SHA-1 certificates are rejected by modern browsers. |
ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN | HPKP key pinning failure | The new certificate's public key doesn't match the pinned key. Update pins or revert. |
9. Self-Signed vs CA-Signed Certificates
Our X.509 Cert Parser accepts both. Here's when to use each:
| Self-Signed | CA-Signed (Let's Encrypt, DigiCert, etc.) | |
|---|---|---|
| Browser trust | Warning — user must click through | Trusted automatically |
| Cost | Free, generated instantly | Free (Let's Encrypt) to $200+/year (EV) |
| Best for | Development, internal services, testing | Production websites, public APIs |
| Generation | openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 | certbot, acme.sh, or CA portal |
10. Key Takeaways
- PEM = Base64(DER) with headers. Same data, different wrapper.
- SANs are mandatory. Browsers ignore Common Name if SANs are present. List every domain explicitly.
- SHA-256 fingerprints uniquely identify a certificate. Compare them manually when you can't trust the CA system.
- The full chain matters. Always send intermediate certificates from your server — clients don't magically fetch them.
- Our X.509 Cert Parser parses any PEM or DER certificate instantly, in-browser, with no data upload.