| name | pem-certificate-decoder |
|---|---|
| description | Decode and inspect PEM-encoded X.509 certificate chains in the browser with the Secutils.dev PEM Decoder. Build a one-click prefilled URL the user can open by encoding the raw PEM string into the fragment of https://tools.secutils.dev/pem#{encoded}. Trigger when the user asks to "decode this certificate", "inspect a PEM chain", "show the SANs in this cert", "what's the issuer of this PEM", or anything that names secutils.dev/pem. |
Hand the user a URL that opens the PEM Decoder pre-loaded with their chain. Parsing happens in the browser - the fragment is never sent to the server, so even a privacy-leaking certificate (or a misplaced private key, see Caveats) stays client-side. The tool auto-sorts chain order (leaf first) and surfaces subject / issuer / SANs / validity / key algorithm and size / signature algorithm / SHA-1 + SHA-256 fingerprints per cert.
| Field | Type | Default | Notes |
|---|---|---|---|
pem |
string | required | One or more concatenated -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- blocks. Chain order does not matter. |
State shape: a raw string - no JSON wrapper. The state is exactly the PEM text the user supplied (including newlines between blocks).
After URL-safe base64 decoding:
| 4 bytes uncompressed-length (LE u32) | N bytes raw DEFLATE of UTF-8 string |
Pipeline: take the PEM string verbatim → UTF-8 bytes → deflate-raw →
prepend the 4-byte LE u32 of the uncompressed length → base64url
(+→-, /→_, strip =).
Run this on any machine with Node ≥ 18 (no deps):
node -e '
const zlib = require("node:zlib");
const fs = require("node:fs");
const pem = process.argv[1] === "-" ? fs.readFileSync(0, "utf8") : process.argv[1];
const utf8 = Buffer.from(pem, "utf8");
const out = Buffer.concat([Buffer.alloc(4), zlib.deflateRawSync(utf8)]);
out.writeUInt32LE(utf8.length, 0);
const enc = out.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"");
console.log("https://tools.secutils.dev/pem#" + enc);
' - <<'EOF'
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKl...
-----END CERTIFICATE-----
EOFRead PEM from stdin (heredoc) so the multi-line block with embedded \n
survives untouched. The fragment is opaque - print the full URL.
The same tools.secutils.dev/pem URL with no fragment loads an empty
decoder if you'd rather just direct the user to paste themselves.
If the user only wants a textual summary in chat (no UI), parse the PEM
locally with any X.509 library: openssl x509 -in cert.pem -text -noout,
Node crypto.X509Certificate, Python cryptography, etc. The shareable URL
is most useful when the user wants the visual chain ladder + SAN list.
Hand the URL back in a fenced block or inline code. Keep summaries to one sentence; don't paraphrase certificate fields.
- The PEM travels in the URL fragment. The fragment never reaches the
Secutils server but is fully visible to anyone with the link. Rare but
catastrophic: if the user accidentally includes a
-----BEGIN PRIVATE KEY-----block, refuse to encode and tell them to strip it first. - DER-encoded (binary) certs are not supported - base64-wrap them in PEM
envelopes first (
openssl x509 -inform DER -in cert.der -out cert.pem). - Signature verification against the issuer is out of scope for this tool.
Use a server-side library (or
openssl verify) for trust-chain validation.