@blamejs/pki — pure-JavaScript PKI toolkit for Node.js
Every page in this reference is generated from the toolkit's own source comments. Zero npm runtime dependencies — the cryptography runs on Node's native node:crypto (classical and FIPS post-quantum), nothing vendored.
Quick start
npm install @blamejs/pki
var pki = require("@blamejs/pki");
var cert = pki.schema.x509.parse(pemText);
cert.subject.dn; // "CN=example.com, O=Example"
cert.validity.notAfter; // Date
cert.signatureAlgorithm.name; // "sha256WithRSAEncryption"
pki.schema.parse(der) detects which of the toolkit's registered formats the bytes encode — certificate, CRL, CSR, CMS, OCSP, PKCS#8, PKCS#12, timestamp token, and the rest — and routes to the owning parser. pki.schema.all() lists the registered formats.Common tasks
Read a certificate's subject, validity and extensions
var cert = pki.schema.x509.parse(pemOrDer);
cert.subject.dn; // "CN=example.com, O=Example"
cert.validity.notAfter; // Date
cert.serialNumberHex; // "75cb4dae..."
cert.extensions; // [ { oid, name: "subjectAltName", critical, value }, ... ]
Full reference for this namespace
Verify a CMS / PKCS#7 signature
var res = await pki.cms.verify(signedDer, { trustAnchors: [rootDer] });
res.valid; // every signer verified
res.eContentType; // "1.2.840.113549.1.7.1" -- the encapsulated type, as an OID
res.signers[0].ok; // this signer verified
res.trusted; // the signers chained to an anchor
Full reference for this namespace
Validate a certificate chain to a trust anchor
// Two shapes to get right. The path runs ANCHOR-ADJACENT FIRST and the TARGET LAST --
// the reverse of how a chain is usually written. And the anchor is an object built from the
// parsed root, not the root's DER (both take trustAnchors; cms.verify above passed an array, this
// passes a single anchor).
var root = pki.schema.x509.parse(rootDer);
var res = await pki.path.validate([intermediate, leaf], {
trustAnchors: {
name: root.subject,
publicKey: root.subjectPublicKeyInfo.bytes,
algorithm: root.subjectPublicKeyInfo.algorithm.oid, // the anchor's own key algorithm
},
time: new Date(),
});
res.valid; // true -- the verb throws on malformed input, so this is a real verdict
res.revocationChecked; // what was actually checked, not what was assumed
res.results[0].checks; // [ { name: "signature", ok }, { name: "nameChaining", ok }, ... ]
Full reference for this namespace
Check whether a certificate has been revoked
var crl = pki.schema.crl.parse(crlDer);
var revoked = crl.revokedCertificates.filter(function (r) {
return r.serialNumber === cert.serialNumber; // both are BigInt
});
revoked[0] && revoked[0].revocationDate; // Date
Full reference for this namespace
Create a certificate signing request
// sign(spec, key, opts) -- the signing key is the SECOND argument, not an option
var csrPem = await pki.csr.sign(
{ subject: "CN=example.com", subjectPublicKey: spkiDer },
{ key: keyDer },
{ pem: true }
);
Full reference for this namespace
Open a PKCS#12 keystore
// The password is a positional argument; omitting it is not the empty password
var store = await pki.pkcs12.open(p12Bytes, "changeit");
store.macVerified; // the integrity MAC checked out
Requirements
Node.js LTS, as shipped. The package is CommonJS and is published without a build step, so require("@blamejs/pki") loads the same JavaScript that lives in the repository. There is no TypeScript compilation, no bundler, and no transpilation between the source and the tarball. Cryptography runs on Node's built-in node:crypto, which covers the classical algorithms and the FIPS post-quantum ones, so no native module is compiled at install time.
Design tenets
- Zero runtime dependencies. The published package's dependency object is empty; the cryptography is Node's own
node:crypto. - Fail closed. Every verify path throws; malformed input is a typed
PkiErrorwith a stabledomain/reasoncode. - Strict DER. The codec rejects every non-DER shape and enforces size and depth caps before it walks a byte.
- Post-quantum first. ML-DSA, ML-KEM, and SLH-DSA resolve through the same OID-keyed registry as the classical algorithms.
- Standards are the contract. Every structure maps to a named RFC, and a parser round-trips a valid input to identical bytes.
Namespaces
Constants
Functional scale helpers (`C.TIME.*`, `C.BYTES.*`) plus the toolkit version and shared codec limits.
ASN.1 / DER
Strict, fail-closed DER decode / encode with a navigable node tree and typed readers + builders.
WebCrypto
A zero-dep, PQC-first W3C WebCrypto (`SubtleCrypto`) engine over `node:crypto`: ML-DSA and SLH-DSA signatures alongside the full classical algorithm set.
Schema
One declarative schema engine; every PKI format (X.509, CRL, ...) is a member composed on it. Detect-and-parse DER, or call a format directly.
X.509
Parse DER / PEM X.509 certificates into structured, validated fields with named algorithms, extensions, and real-`Date` validity windows.