/api/cert/decode
MCP tool cert_decode Decodes every certificate (PEM, DER, Base64 DER, or PKCS#7 bundle) and CSR in the input. For chains it checks, for each adjacent pair, that the issuer name matches and that the signature verifies with the next certificate's key. With hostname it reports which certificates cover that name under RFC 6125 wildcard rules. It does not establish trust: there is no root store, and revocation (OCSP/CRL) is not checked.
Browser version (runs locally): Certificate Decoder.
Try it
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
input | string | — | PEM text (one or more blocks) or Base64 DER. Use exactly one of input, input_base64, or a file upload (.pem, .crt, .cer, .der, .p7b, .csr). |
input_base64 | string | — | Data as Base64 (either alphabet), for binary content over JSON or MCP. |
hostname | string (≤ 253 chars) | — | Report whether each certificate's DNS SANs cover this host name. |
at | string | — | Evaluate validity at this ISO 8601 time instead of now, e.g. 2026-01-01T00:00:00Z. |
Also accepted on every endpoint: format (json | text).
Parameters may come from the query string, a JSON object body, an urlencoded or multipart form,
or (for input) a text/plain body.
Binary data can be uploaded as a multipart file field or an application/octet-stream body.
Global parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | json | text | json | json returns the documented object. text returns only the primary value as text/plain (see "Text output"). |
Response 200 application/json
| Field | Type | Description |
|---|---|---|
certificates | array of object | Certificates in input order (leaf first in a well-ordered chain). |
certificates[].subject | string | Subject distinguished name (RFC 4514 string). |
certificates[].issuer | string | Issuer distinguished name. |
certificates[].serialNumber | string | Serial number as colon-separated uppercase hex. |
certificates[].signatureAlgorithm | string | Signature algorithm, e.g. RSA PKCS#1 v1.5 with SHA-256. |
certificates[].validity | object | |
certificates[].validity.notBefore | string | ISO 8601 UTC. |
certificates[].validity.notAfter | string | ISO 8601 UTC. |
certificates[].validity.status | "valid" | "expired" | "not-yet-valid" | Relative to at (default: now). |
certificates[].validity.daysRemaining | integer | Whole days until notAfter; negative once expired. |
certificates[].publicKey | object | |
certificates[].publicKey.algorithm | string | RSA, EC, Ed25519, X25519, or the algorithm OID name. |
certificates[].publicKey.bits | integer | null | Key size in bits (RSA modulus, EC field size). |
certificates[].publicKey.curve | string | null | Named curve for EC keys (P-256, …). |
certificates[].publicKey.spkiSha256 | string | RFC 7469 pin: Base64(SHA-256(SubjectPublicKeyInfo)). |
certificates[].subjectAltNames | array of object | Subject alternative names. |
certificates[].subjectAltNames[].type | string | dns, ip, email, url, dn, … |
certificates[].subjectAltNames[].value | string | The name. |
certificates[].keyUsage | array of string | Key usage extension bits. |
certificates[].extendedKeyUsage | array of string | Extended key usage purposes. |
certificates[].basicConstraints | object | null | |
certificates[].basicConstraints.ca | boolean | Whether this is a CA certificate. |
certificates[].basicConstraints.pathLength | integer | null | Max intermediate CAs below this one. |
certificates[].subjectKeyId | string | null | Subject key identifier, hex. |
certificates[].authorityKeyId | string | null | Authority key identifier, hex. |
certificates[].ocsp | array of string | OCSP responder URLs (AIA). |
certificates[].caIssuers | array of string | Issuer certificate URLs (AIA). |
certificates[].crlDistributionPoints | array of string | CRL URLs. |
certificates[].policies | array of string | Certificate policies (DV/OV/EV are named). |
certificates[].embeddedScts | boolean | True when Certificate Transparency SCTs are embedded. |
certificates[].selfSigned | boolean | True when subject equals issuer and the signature verifies with its own key. |
certificates[].fingerprints | object | |
certificates[].fingerprints.sha1 | string | SHA-1 of the DER, colon hex. |
certificates[].fingerprints.sha256 | string | SHA-256 of the DER, colon hex. |
certificates[].pem | string | The certificate re-encoded as PEM. |
chain | object | |
chain.links | array of object | One link per adjacent pair. |
chain.links[].child | integer | Index of the certificate. |
chain.links[].parent | integer | Index of the next certificate. |
chain.links[].issuerNameMatches | boolean | child.issuer equals parent.subject. |
chain.links[].signatureValid | boolean | child's signature verifies with parent's public key. |
chain.ordered | boolean | Every link matches by name and signature. |
chain.endsAtSelfSigned | boolean | The last certificate is self-signed (a root). |
chain.notes | array of string | Problems and observations about the chain. |
requests | array of object | Certificate signing requests (PKCS#10). |
requests[].subject | string | Requested subject DN. |
requests[].signatureAlgorithm | string | Signature algorithm. |
requests[].signatureValid | boolean | The CSR self-signature verifies (proves possession of the private key). |
requests[].publicKey | object | |
requests[].publicKey.algorithm | string | RSA, EC, Ed25519, X25519, or the algorithm OID name. |
requests[].publicKey.bits | integer | null | Key size in bits (RSA modulus, EC field size). |
requests[].publicKey.curve | string | null | Named curve for EC keys (P-256, …). |
requests[].publicKey.spkiSha256 | string | RFC 7469 pin: Base64(SHA-256(SubjectPublicKeyInfo)). |
requests[].subjectAltNames | array of object | Subject alternative names. |
requests[].subjectAltNames[].type | string | dns, ip, email, url, dn, … |
requests[].subjectAltNames[].value | string | The name. |
requests[].pem | string | The request re-encoded as PEM. |
hostname | object | null | |
hostname.name | string | Host name checked. |
hostname.coveredBy | array of integer | Certificates whose DNS SANs match. |
Errors
Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.
| Status | Code | When |
|---|---|---|
400 | invalid_parameter | at is not a valid date, or more than one data source is given. |
422 | unprocessable_input | No certificate or CSR is found, the data is malformed, or the input contains a private key (refused). |
400 | missing_parameter | A required parameter is absent. |
400 | unknown_parameter | A parameter name is not in the table above (typos are rejected, not ignored). |
413 | payload_too_large | The request body exceeds 1 MiB. |
405 | method_not_allowed | A method other than GET, POST or OPTIONS. |
Behaviour
- Idempotent: the same arguments always return the same result.
-
Requires a client ID and secret (authentication). Each call is
recorded as one metadata row against your client ID; inputs and outputs are never stored or
logged. Responses carry
cache-control: no-store. - CORS: any origin may call this endpoint from a browser, using your credentials.
Examples
Responses below were produced by running each request through this code at build time. Long strings are shortened.
Self-signed certificate, checking a host name
curl -X POST 'https://util.caruana.me/api/cert/decode' \
-H 'content-type: application/json' \
-d '{"input":"-----BEGIN CERTIFICATE-----\nMIIBYDCCARKgAwIBAgIQcuMlZ0gk8qldBRVY4uV0BTAFBgMrZXAwFjEUMBIGA1UE\nAxMLZXhhbXBsZS5jb20wHhcNMjYxMDE0MDA1MjM5WhcNMjcxMDE0MDA1MjM5WjAW\nMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAqMAUGAytlcAMhAHGVluSiNj6bqXsllRWY\nUFXc2JNxW9mDP9PntMYyVHeMo3YwdDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE\nAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFAmd\nd/YA6wQehHCnkI05mwtULXOMMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMAUGAytl\ncANBAKbfzTFPGlLacXH+cIikicbI4CSvJj/ZkCgMWJNjq649UzUHvJvhe2rQoLwM\nDFaoibsbMY3x6ucpRzC+yl9t7ww=\n-----END CERTIFICATE-----\n","hostname":"example.com"}'
Response 200
{
"certificates": [
{
"subject": "CN=example.com",
"issuer": "CN=example.com",
"serialNumber": "72:E3:25:67:48:24:F2:A9:5D:05:15:58:E2:E5:74:05",
"signatureAlgorithm": "Ed25519",
"validity": {
"notBefore": "2026-10-14T00:52:39.000Z",
"notAfter": "2027-10-14T00:52:39.000Z",
"status": "valid",
"daysRemaining": 364
},
"publicKey": {
"algorithm": "Ed25519",
"bits": 256,
"curve": null,
"spkiSha256": "TbzBk4Wus+EGmXKtvddPRWHXoFXx92/Z3awNPz3Vo9g="
},
"subjectAltNames": [
{
"type": "dns",
"value": "example.com"
}
],
"keyUsage": [
"digitalSignature"
],
"extendedKeyUsage": [
"TLS server authentication",
"TLS client authentication"
],
"basicConstraints": {
"ca": false,
"pathLength": null
},
"subjectKeyId": "099D77F600EB041E8470A7908D399B0B542D738C",
"authorityKeyId": null,
"ocsp": [],
"caIssuers": [],
"crlDistributionPoints": [],
"policies": [],
"embeddedScts": false,
"selfSigned": true,
"fingerprints": {
"sha1": "CE:B5:7C:D3:DE:FB:06:99:18:CE:D4:CE:60:7E:32:8A:8F:52:9A:8A",
"sha256": "E2:A2:01:81:60:37:51:F3:4A:8A:C8:6E:59:EA:86:5C:1B:09:CA:32:70:9D:33:31:EC:AD:E5:45:AC:89:47:E8"
},
"pem": "-----BEGIN CERTIFICATE-----\nMIIBYDCCARKgAwIBAgIQcuMlZ0gk8qldBRVY4uV0BTAFBgMrZXAwFjEUMBIGA1UE\nAxMLZXhhbXBsZS5jb20wHhcNMjY… (418 more characters)"
}
],
"chain": {
"links": [],
"ordered": true,
"endsAtSelfSigned": true,
"notes": []
},
"requests": [],
"hostname": {
"name": "example.com",
"coveredBy": [
0
]
}
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "cert_decode",
"arguments": {
"input": "-----BEGIN CERTIFICATE-----\nMIIBYDCCARKgAwIBAgIQcuMlZ0gk8qldBRVY4uV0BTAFBgMrZXAwFjEUMBIGA1UE\nAxMLZXhhbXBsZS5jb20wHhcNMjYxMDE0MDA1MjM5WhcNMjcxMDE0MDA1MjM5WjAW\nMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAqMAUGAytlcAMhAHGVluSiNj6bqXsllRWY\nUFXc2JNxW9mDP9PntMYyVHeMo3YwdDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE\nAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFAmd\nd/YA6wQehHCnkI05mwtULXOMMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMAUGAytl\ncANBAKbfzTFPGlLacXH+cIikicbI4CSvJj/ZkCgMWJNjq649UzUHvJvhe2rQoLwM\nDFaoibsbMY3x6ucpRzC+yl9t7ww=\n-----END CERTIFICATE-----\n",
"hostname": "example.com"
}
}
}