Read the certificates
your software trusts

Parse, verify and build X.509: strict DER, complete RFC 5280, §6 path validation with CRL and OCSP, CMS and RFC 3161 timestamps, PKCS#8 and PKCS#12 — every signature through Web Crypto, zero runtime dependencies, on Node, browsers, Deno, Bun and Workers.

CI status CodeQL status OpenSSF Scorecard npm version npm provenance signed MIT licence Zero runtime dependencies 100% coverage TypeScript strict
npm install pkinative
npm install --global pkinative-cli
npx -y pkinative-mcp

On npm with provenance since 1.0.0, under semantic versioning: a minor release only adds.

30 361
x509-limbo certificates
1 530
Wycheproof vectors
100 %
Branch coverage
0
Runtime dependencies

Why pkinative

A reader for hostile bytes and a verifier that owns no secret arithmetic — complete on the profile it claims and explicit about the profile it does not.

Strict by default

DER admits one encoding per value, and every X.690 §10–11 violation throws. Two encodings of one value is how a signature covers bytes two parsers read differently. BER is an explicit opt-in.

Zero dependencies, every runtime

Nothing to audit but this. No node: import, no process, no filesystem, no network — checked on the shipped bundle. The same build runs on Node, browsers, Deno, Bun and Workers, and tree-shakes: the OID name registry never enters a parser's bundle.

Safe on hostile input

Every loop over untrusted bytes consults a named, CWE-tagged limit. The decoder is iterative, so nesting depth ends in a typed error and never in a stack overflow.

Complete on RFC 5280

Every field and all nineteen extension kinds — the seventeen of RFC 5280, OCSP no-check and the SCT list — decoded and typed — not a subset with the awkward ones left as raw bytes. Certificates and PKCS#10 requests are read, verified and built with the same readers, codes and bounds.

Every signature through Web Crypto

Certificates, certification requests, CRLs, OCSP responses, CMS signers and timestamps are verified by one call into the host's Web Crypto — RSA, ECDSA, Ed25519, and Ed448 where the host has it. No signing, no key generation, no arithmetic on secret material in TypeScript; hashing, SHAKE256 included, covers public data only.

Paths and revocation

RFC 5280 §6 path validation — name constraints, policies, key usage — plus CRL and OCSP. verifyCertificateChain composes them and answers with stable reason codes, not exceptions.

CMS, timestamps, keys

RFC 5652 SignedData and RFC 3161 timestamps, created and verified; PKCS#8 and PKCS#12 under PBES2, opened into non-extractable Web Crypto keys.

Honest about profiles

A structural violation throws; a profile deviation real issuers commit becomes a diagnostic carrying its RFC clause. Never both, and never silence.

Built for agents

Stable machine-readable error and reason codes, a diagnostics channel, llms.txt, a generated API manifest and gate rules that prove an agent can use every export from the docs alone — and an MCP server that hands an assistant 34 typed tools.

Pick your surface

One zero-dependency engine, three ways to call it — the verdicts and the codes are the same, so the choice is about who is calling. The capability × surface matrix →

pkinative v1.0.0

The library

You write application code — Node.js, a browser, Deno, Bun or a Worker. The whole surface: readers, writers, path validation, revocation, CMS and timestamps, PKCS#8 and PKCS#12, every signature through Web Crypto, 57 error codes and a verdict for every refusal.

npm install pkinative

pkinative-cli v1.0.0 · binary pkinative

The CLI

You drive a shell, a CI job or a container. The pkinative-cli command has 18 commands and 53 invocations, a --json envelope whose 13 error classes carry the PKI_* code verbatim, exit codes 0, 1 and 2, JSON Schemas and shell completion. Offline, and never a password on the command line.

npm install --global pkinative-cli

pkinative-mcp v1.0.0

The MCP server

You give an AI assistant tools — Claude Desktop, Claude Code, Cursor, VS Code. The MCP server registers 34 tools with strict schemas and seven prompts, serves sandboxed file resources over stdio or loopback Streamable HTTP, returns a negative verdict as data, and makes no network call.

npx -y pkinative-mcp

Three calls

Every example below is an executable recipe, run and asserted on every test run.

import { decodePem, formatDistinguishedName, getExtension, parseCertificate } from 'pkinative';

for (const { bytes } of decodePem(pemText, { label: 'CERTIFICATE' })) {
    const cert = parseCertificate(bytes);
    console.log(formatDistinguishedName(cert.subject));
    console.log(new Date(cert.validity.notAfter.epochMilliseconds).toISOString());
    console.log(getExtension(cert, 'subjectAltName')?.names.length ?? 0);
}
import { decodeExtensionValue, getExtension, parseCertificate } from 'pkinative';

// Nineteen extension kinds, each typed by its `kind`.
const cert = parseCertificate(der);
getExtension(cert, 'basicConstraints')?.cA;
getExtension(cert, 'keyUsage')?.usages;
getExtension(cert, 'nameConstraints')?.permittedSubtrees;

// Or keep them encoded, and decode only what you need.
const lazy = parseCertificate(der, { decodeExtensions: false });
decodeExtensionValue(lazy.extensions[0].oid, lazy.extensions[0].valueDer);
import { parseCertificate, PkiError, PkiLimitError } from 'pkinative';

try {
    // A caller that expects small certificates can say so; every other
    // limit keeps its default.
    parseCertificate(untrusted, { limits: { maxExtensions: 4 } });
} catch (error) {
    if (error instanceof PkiLimitError) console.error(error.code, error.limit);
    else if (error instanceof PkiError) console.error(error.code);
    else throw error;  // a TypeError escaping the parser would be a bug
}

Every export named here is in api.json; the runnable sources are in llms-recipes.txt.

How it compares

Registry facts and documented scope — no benchmark of someone else's library, no opinion about their code.

Dependencies, bundled types and module format of the other libraries were read on 2026-09-19 from the npm registry (comparison-2026-09-19.json, a dated snapshot whose pkinative row predates 1.0). The capability rows are each project's documented scope, and pkinative's column describes 1.0. The choosing guide details the differences and says when another library is the right answer.
Librarypkinativenode-forgeasn1js@peculiar/x509pkijsjsrsasignmicro509
Runtime dependencies00311600
Types bundled✓✗✓✓✓✗✓
ES modules✓✗✓✓✓✗✓
Strict DER by default✓✗✗✗✗✗✗
Signature verification✓✓✗✓✓✓✓
Path validation✓✓✗✗✓✗✗

Performance

Measured, with the machine named. Numbers without a run context are not evidence.

Operations per second

computeFingerprint
51 974
decodeAsn1 — leaf
22 361
parseCertificate — envelope
11 720
decodePem — 6 certs
7 208
parseCertificate — full
5 895

Node.js 22.17.0, win32 x64, Intel Core i7-4510U at 2.00 GHz — a 2014 laptop, with other applications open. A real end-entity certificate with all ten of its extensions decoded takes about 0.17 ms; roughly half of that is the extensions, which decodeExtensions: false skips. Full table, with the relative error of every row, in bench/RESULTS.md.

Small, layered, tree-shakeable

Fourteen layers, every import pointing down — and seven imports refused on purpose.

For AI agents

Every failure is a typed error with a stable code you can branch on. Every export, its module, signature and thrown errors are in a generated manifest. Seven gate rules prove an agent can name and use every export from the published documentation alone — not as a claim, as a check that fails.

An agent that should not write code has two doors to the same engine: pkinative-mcp, an MCP server with 34 tools and seven prompts, whose refusals carry the PKI_* code and whose negative verdicts are data; and pkinative-cli, whose --json contract puts one envelope on stderr and the report on stdout. Both run offline and refuse what the library refuses.

Agent brief

Origin

pkinative is the third library of the native family, after pdfnative and zipnative. It began as pdfnative's PAdES signature stack, where an ASN.1 decoder that guessed was a liability, and became the library that reads the certificate rather than the one that trusts it.

The same doctrine runs through all three: zero runtime dependencies, one quality gate, conformance against corpora the project did not write, and human review before anything is published.