Paste a certificate, or click Example Chain. A full chain (leaf, intermediates, root) is decoded one card per certificate.
Decode an SSL/TLS certificate without reading
openssl x509 -text output. Paste a PEM block, a
whole chain, or upload a DER file, and you get the subject, SANs,
expiry, key type and every extension a browser checks. A small
hand-written ASN.1 reader parses it in this tab, so the certificate
is never uploaded.
Paste a certificate, or click Example Chain. A full chain (leaf, intermediates, root) is decoded one card per certificate.
-----BEGIN CERTIFICATE-----
MIIDSDCCAs6gAwIBAgIUPtlVi22WWaf/FmcQ2emo0iJZpS0wCgYIKoZIzj0EAwMw
...
-----END CERTIFICATE----- Subject: C=US, ST=California, L=San Francisco, O=Example Shop Ltd, CN=shop.example.com
Issuer: C=US, O=Example Test CA, CN=Example Test Root R1
Serial: 3E:D9:55:8B:6D:96:59:A7:FF:16:67:10:D9:E9:A8:D2:22:59:A5:2D
Not After: 2031-09-29T10:25:21.000Z
Signature Algorithm: ecdsa-with-SHA384
Public Key: EC P-256 (prime256v1), 256 bit
Subject Alternative Name:
DNS:shop.example.com
DNS:*.shop.example.com
IP:203.0.113.10
IP:2001:db8::10 Check the SAN list, not the CN. Browsers match the hostname against the SANs only; Chrome has ignored the subject CN for this since version 58. A hostname missing from the SANs is a mismatch error.
The expiry, in UTC. The badge on each card counts the days. Check the intermediates too: an expired intermediate breaks the chain the same way an expired leaf does.
In a correct chain, each certificate's issuer equals the next one's subject, and its Authority Key Identifier equals the next one's Subject Key Identifier. Each card flags it when the order looks wrong.
CA:TRUE means the certificate can sign other certificates. A leaf should say CA:FALSE. pathlen:0 on an intermediate means it may only sign leaves.
The tool does not check the signature against the issuer's key,
query revocation (CRL or OCSP), or compare anything against a
trust store. A certificate that decodes cleanly here can still be
rejected by a browser. For a live server, openssl s_client -connect
host:443 -showcerts shows the chain the server sends, and you can paste that whole output
in: the decoder ignores anything outside the BEGIN and END lines.
The decoder does not parse PKCS#7 (.p7b) or PKCS#12 (.pfx) bundles. Convert
them first with openssl pkcs7 -print_certs -in bundle.p7b
or openssl pkcs12 -in file.pfx -nokeys. Never paste a private key into a website, this one
included. The decoder refuses to display one, but the key has
already left your terminal by then.
const { X509Certificate } = require("node:crypto");
const fs = require("node:fs");
const cert = new X509Certificate(fs.readFileSync("cert.pem"));
console.log(cert.subject); // "C=US\nST=California\n...\nCN=shop.example.com"
console.log(cert.issuer);
console.log(cert.subjectAltName); // "DNS:shop.example.com, ..., IP Address:203.0.113.10, ..."
console.log(cert.validTo); // "Sep 29 10:25:21 2031 GMT"
console.log(cert.serialNumber); // hex, no colons
console.log(cert.fingerprint256); // "1B:0C:6C:..."
console.log(cert.publicKey.asymmetricKeyType); // "ec" or "rsa"
const daysLeft = Math.floor((new Date(cert.validTo) - Date.now()) / 86400000);
console.log(daysLeft + " days left"); X509Certificate reads one certificate. For a chain, split the file on the END CERTIFICATE line and construct one per block.
<?php
$pem = file_get_contents('cert.pem');
$info = openssl_x509_parse($pem);
if ($info === false) {
exit("Not a certificate: " . openssl_error_string() . PHP_EOL);
}
echo $info['subject']['CN'], PHP_EOL;
echo $info['issuer']['O'] ?? '', PHP_EOL;
echo $info['extensions']['subjectAltName'] ?? '', PHP_EOL;
echo date('c', $info['validTo_time_t']), PHP_EOL;
echo $info['serialNumberHex'], PHP_EOL;
$days = intdiv($info['validTo_time_t'] - time(), 86400);
echo "$days days left", PHP_EOL;
echo openssl_x509_fingerprint($pem, 'sha256'), PHP_EOL; openssl_x509_parse() returns the extensions as openssl's own display strings, which is convenient to print and awkward to parse further.
# Everything, the long way
openssl x509 -in cert.pem -noout -text
# Just the fields you usually want
openssl x509 -in cert.pem -noout -subject -issuer -enddate -ext subjectAltName
# Fingerprint (DER bytes hashed, same as the tool)
openssl x509 -in cert.pem -noout -fingerprint -sha256
# DER to PEM
openssl x509 -inform der -in cert.der -out cert.pem
# The chain a live server actually sends
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null Certificates are DER-encoded ASN.1 (X.690), and this page parses them with a small hand-written reader rather than a library. It covers the fields RFC 5280 defines for TLS certificates plus the common CA/Browser Forum policy OIDs, Certificate Transparency SCTs and OCSP Must-Staple. Unknown extensions are shown by OID with their raw bytes, so nothing is silently dropped.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
Paste the PEM and read the Not after line, or the badge on the card, which counts the days left. From a terminal, openssl x509 -in cert.pem -noout -enddate prints the same date.
Yes. Every BEGIN CERTIFICATE block becomes its own card, in the order pasted, and each card says whether its issuer matches the subject of the next one. Text outside the blocks, such as openssl s_client output, is ignored.
No. It decodes the fields but does not check the signature, query OCSP or CRLs, or compare against a trust store, so a certificate that decodes cleanly can still be rejected by a browser.
DER is the binary encoding. PEM is the same bytes in Base64 between BEGIN and END lines. .crt and .cer are only file extensions and can hold either, which is why the upload accepts both and detects the format from the content.
A certificate is public: every server sends it to every visitor. Parsing happens in your browser and nothing is uploaded. A private key is a different matter, and the tool refuses to display one if you paste it by mistake.
For tokens rather than certificates, use the JWT decoder. The fingerprints here are SHA-256 and SHA-1 digests of the DER bytes; the SHA generator computes the same algorithms over text. For raw Base64 that is not a certificate, use the Base64 encoder.