# Certificate Decoder

> Decode X.509 certificates and CSRs in your browser: expiry countdown, SAN list, fingerprints, chain diagnosis and cert/key matching. Nothing you paste is sent.

- URL: https://bytescope.dev/en/certificate-decoder/
- Locale: en · Also: [ja](https://bytescope.dev/ja/certificate-decoder.md) · [zh-Hant](https://bytescope.dev/zh-Hant/certificate-decoder.md)
- Runs: Your files never leave your browser — all processing is local.
- Requires: Any modern browser (Chrome, Edge, Firefox, Safari), desktop and mobile.
- Updated: 2026-09-08

## What it does

Paste or drop PEM, DER, CRT or CER material — a single certificate, a whole chain, or a CSR — and every field is decoded instantly: subject and issuer DN component by component, validity with a days-remaining countdown (expired in magenta, under 30 days in orange, because expiry is what you're usually here to check), the full SAN list, key usage and extended key usage, public-key type and size, signature algorithm, serial number, and SHA-1/SHA-256 fingerprints.

Paste several certificates together and the tool sorts them into a chain, verifies each link, and diagnoses the classic server misconfiguration in one line: "missing intermediate certificate". The cert-and-key matcher takes a certificate and a private key and tells you whether they belong together — the five-second answer to the mid-outage question "is this even the right key?". Hostname checking compares a domain you enter against the SAN list, and weak signatures (SHA-1) and self-signed certificates are called out.

All parsing happens in your browser via WebCrypto — certificates, CSRs and above all private keys are never transmitted anywhere. Pasting a private key into a random website is normally a security mistake; here the architecture makes it safe, and you can pull the network cable to prove it.

It also unpacks PKCS#12 containers: drop a .p12 or .pfx file, type the export password, and the certificate chain and private key come straight out — the certificates feed into the same full decoder, the key is checked against the leaf, and everything downloads as PEM. Legacy files matter here: containers from older OpenSSL, Java keytool and Windows exports use RC2-40 and 3DES ciphers that the browser's WebCrypto can't touch, so a bundled JavaScript implementation decrypts them, and the private key still never leaves the tab.

## Limits

Does not fetch certificates from a live server or validate the chain against a trust store; paste or drop the certificate.

## Machine output

Copy JSON copies an envelope `{ tool, url, generatedAt, userAgentHint, result }`. `tool` is `"certificate-decoder"`; `result` is the on-screen decode below. This page does not contact any host and does not consult a system trust store, so no field here means "trusted". It decodes what was pasted, compares `notBefore`/`notAfter` against the clock, and checks the signatures between the pasted certificates — nothing else. Private-key PEM, raw PEM/DER, PKCS#12 passwords, and the dropped file name are omitted.

- `certificates` (array of objects) — Decoded certificates in paste/drop order. Each has `commonName` (or `null`), `subjectDn`, `issuerDn`, `subject` / `issuer` (DN components `{ oidName, value }`), `serialHex`, `notBefore` / `notAfter` (ISO 8601 UTC), `daysRemaining`, `validityWindow` (`"current"` | `"expiring-soon"` | `"expired"` | `"not-yet-valid"`, or `null` if the page did not classify it — a calendar comparison only, and never a statement that the certificate is trusted, unrevoked, or correctly issued), `signatureAlgorithm`, `signatureHash`, `publicKey` (`type`, `size` or `null`, `curve` or `null`, `algorithm`), `sans` (`{ type, value }`), `keyUsage`, `extendedKeyUsage`, `basicConstraints` (`null` = extension absent; otherwise `{ isCA, pathLen }` with `pathLen` `null` when unset), `subjectKeyId` / `authorityKeyId` (lowercase hex or `null`), `isSelfSigned` (the certificate signs itself), `fingerprints` (`sha1`, `sha256` lowercase hex), `weaknesses` (on-screen warning strings).
- `csrs` (array of objects) — Decoded CSRs in paste/drop order. Each has `commonName` (or `null`), `subjectDn`, `subject`, `sans`, `publicKey`, `signatureAlgorithm`, `signatureHash`, `signatureValid` (boolean — proof of possession: the request is signed by the key it carries. It is not a statement about any CA accepting the request).
- `chain` (object | null) — What the pasted certificates amount to when ordered leaf-first. `null` = assembly was not run (fewer than two certificates). When present: `diagnosis` — `"self-contained"` (every issuer needed was pasted, up to a self-signed top), `"missing-issuer"` (an issuer was not among them; see `missingIssuerDn`), `"signature-mismatch"` (a child's signature does not check out against the issuer that was pasted). `rootIsSelfSigned`, `missingIssuerDn` (or `null`), `subjects` (on-screen CN/DN labels, leaf first), `links` (`{ childDn, issuerDn, signatureMatchesIssuer }` — the signature check between two pasted certificates, not a path validation). `"self-contained"` says the pasted bundle hangs together; it does not say any client would accept it.
- `skippedReasons` (string[]) — Why a PEM/DER block was skipped, on-screen order. Block labels are omitted because a dropped file name is used as the label.

## FAQ

### Is it safe to paste a private key here?

Yes — everything is parsed locally in your browser with the WebCrypto/ASN.1 libraries bundled into the page; there is no server call, which you can verify in the DevTools Network tab (or by going offline before pasting). That said, treat any pasted private key as sensitive: close the tab when done.

### What does "missing intermediate certificate" mean?

Browsers trust root CAs, but your server certificate is usually signed by an intermediate CA. The server must send that intermediate along with its own certificate; when it doesn't, some clients fail with trust errors while others work (they cached the intermediate) — the classic "works in Chrome, fails in curl" symptom. Paste your chain here and the tool shows exactly which link is missing.

### How do I check if a certificate matches its private key?

Paste both into the matcher. A certificate contains the public key; the tool derives the public key from your private key and compares them. A mismatch means this key won't work with this certificate — the fastest diagnosis for nginx's "key values mismatch" error.

### Can it decode a CSR before I submit it to a CA?

Yes — paste the CSR to see the subject, requested SANs, and key details before sending it off. Catching a typo'd domain in the CSR is much cheaper than reissuing a certificate.

### Which formats are accepted?

PEM (BEGIN CERTIFICATE / CERTIFICATE REQUEST / PRIVATE KEY blocks, pasted or dropped), DER binary files (.crt/.cer/.der), multi-certificate PEM bundles, and PKCS#12 (.pfx/.p12) containers via the dedicated unpack panel (password-protected; certificate chain and private key extracted locally).

### Can it open a .p12 / .pfx file?

Yes. Drop the container into the unpack panel and enter its password: the certificate chain and private key are extracted in your browser and shown through the full decoder, with the key checked against the leaf certificate and offered as a PEM download. A wrong password is reported distinctly from a corrupt file, because the password is verified against the container's integrity MAC before anything is decrypted.

### Why can this open old .p12 files when other browser tools can't?

Older OpenSSL, Java keytool and Windows exports encrypt the certificates with RC2-40 and the key with 3DES — ciphers the browser's built-in WebCrypto simply doesn't implement, so pure-WebCrypto tools reject those files. This tool bundles a JavaScript implementation of those legacy ciphers, so RC2-40, 3DES and modern AES-256 (PBES2) all open — and the private key still never leaves the page.
