npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

micro509

v0.11.0

Published

The zero-dependency TypeScript PKI toolkit for real certificate workflows.

Readme

micro509

NPM JSR Socket

A zero-dependency TypeScript PKI toolkit for certificates, verification, revocation, and PKCS workflows.

Zero dependencies. Tree-shakeable subpath entrypoints. Pure WebCrypto. Runs everywhere: Node, Bun, Deno, browsers, Cloudflare Workers.

Prerelease — API may change before 1.0.

Install

npm install micro509

Why micro509

JavaScript PKI libraries usually force a bad tradeoff: heavyweight standards toolkits, legacy crypto kitchen sinks, or narrow parsing utilities.

micro509 is the practical middle: a modern, WebCrypto-native PKI toolkit with zero runtime dependencies and typed APIs for the workflows most applications actually need.

It gives you one library for certificate and CSR creation, chain verification, service-identity matching, CRLs, OCSP, PKCS#7 SignedData, PFX/PKCS#12, PEM handling, and key import/export.

And when verification fails, you get typed results your code can act on: a typed error code for every failure mode, the failing certificate index, and structured failure details instead of false.

if (!result.ok) {
  // result.error.code: 'signature_invalid' | 'certificate_expired' | 'name_constraints_violated' | ...
  // result.error.index: which certificate in the chain failed
  // result.error.details: { expected, actual } for identity mismatches
}

Beyond verification, micro509 covers PKI surface that's hard to find in a single zero-dependency JS package:

  • OCSP — build requests, parse and validate responses, verify responder authorization
  • PFX / PKCS#12 — create and parse password-protected key+cert bundles
  • PKCS#7 / CMS — sign content, parse and verify SignedData, extract cert bags
  • CRLs — create, parse, verify, and check revocation status
  • Encrypted keys — PBES2 PKCS#8, legacy OpenSSL encrypted PEM, PKCS#1, SEC1
  • Key import/export — PKCS#8, SPKI, JWK, PKCS#1, SEC1 with generation for RSA, ECDSA, Ed25519
  • Service identity — wildcard DNS, IPv6 normalization, URI-ID, SRV-ID, explicit CN opt-in

Narrow defaults, explicit escape hatches — dangerous operations like CN fallback or self-signed leaf acceptance require opt-in. All with no any, no type assertions, no non-null assertions, and no runtime DI frameworks that break edge runtimes.

Quick start

Create a self-signed certificate:

import { createSelfSignedCertificate } from 'micro509';

const { certificate, keyPair } = await createSelfSignedCertificate({
  subject: {
    commonName: 'example.com',
    organization: 'Acme',
    country: 'US',
  },
  validity: { days: 30 },
  extensions: {
    keyUsage: ['digitalSignature', 'keyEncipherment'],
    subjectAltNames: [
      { type: 'dns', value: 'example.com' },
      { type: 'dns', value: 'www.example.com' },
    ],
  },
});

console.log(certificate.pem);
console.log(await keyPair.exportPkcs8Pem());

Create a CSR:

import { createCertificateSigningRequest, generateKeyPair } from 'micro509';

const keyPair = await generateKeyPair({ kind: 'ed25519' });
const csr = await createCertificateSigningRequest({
  subject: { commonName: 'csr.example' },
  publicKey: keyPair.publicKey,
  signerPrivateKey: keyPair.privateKey,
  extensions: {
    subjectAltNames: [{ type: 'dns', value: 'csr.example' }],
  },
});

console.log(csr.pem);

Parse a certificate:

import { parseCertificatePem, unwrap } from 'micro509';

// Using certificate from previous example
const parsed = unwrap(parseCertificatePem(certificate.pem));
console.log(parsed.subject.values.commonName);
console.log(parsed.extendedKeyUsage);
console.log(parsed.authorityInfoAccess);

parseCertificatePem returns a typed Result — check result.ok, or unwrap() to throw on malformed input.

Verify a chain:

import { verifyCertificateChain } from 'micro509';

// Assuming you have a self-signed certificate used as both leaf and root; no intermediates
const result = await verifyCertificateChain({
  leaf: certificate.pem,
  intermediates: [],
  roots: [certificate.pem], // Using self-signed cert as root for demo
  purpose: 'serverAuth',
  serviceIdentity: { type: 'dns', value: 'example.com' },
});

if (result.ok) {
  console.log(result.value.chain.length);
} else {
  console.log(result.error.code);
}

Runtime support

| Runtime | Status | Notes | | ------- | --------- | -------------------------------------------------- | | Node | supported | modern Node with WebCrypto globals (tested on 24+) | | Bun | supported | Bun 1.3+ | | Deno | supported | requires WebCrypto and web text/base64 globals | | Browser | supported | modern browsers only | | Worker | supported | same WebCrypto and text/base64 globals required |

The core stays ESM-only and side-effect-free.

Algorithm support

| Area | Shipped support | | ------------------------------ | -------------------------------------------------------------------- | | Certificate and CSR signatures | RSA PKCS#1 v1.5, RSA-PSS, ECDSA P-256 / P-384 / P-521, Ed25519 | | RSA key APIs | scheme: 'pkcs1-v1_5' | | ECDSA key APIs | P-256, P-384, P-521 | | Encrypted PKCS#8 and PFX | PBES2 with AES-CBC plus PBKDF2 HMAC-SHA1/HMAC-SHA256 | | Encrypted traditional PEM | AES-128-CBC, AES-192-CBC, AES-256-CBC for RSA and EC private keys |

micro509 focuses on algorithms that are broadly interoperable in modern X.509 and WebCrypto-backed runtimes.
It intentionally excludes niche, blockchain-specific, or key-agreement-only primitives from the core API unless they are needed for a PKI workflow the library explicitly supports.

Standards status

| Area | Status | | -------------------------- | -------- | | RFC 5280 path validation | complete | | RFC 6960 OCSP | complete | | RFC 6125 service identity | complete | | RFC 9618 policy validation | complete |

See docs/PKIX-SCOPE.md for the detailed scope boundary and the API reference for the public module surface.

Imports

Use the root package for most applications:

import { createCertificate, parseCertificatePem, verifyCertificateChain } from 'micro509';

Use domain entrypoints when you want exhaustive advanced types or a narrower workflow surface:

import { parseCertificatePem } from 'micro509/x509';
import { verifyCertificateChain, matchServiceIdentity } from 'micro509/verify';
import { createOcspRequest, checkCertificateRevocation } from 'micro509/revocation';
import { createPfx } from 'micro509/pkcs';
import { generateKeyPair } from 'micro509/keys';
import { pemDecode, pemEncode } from 'micro509/pem';
import type { Micro509Error } from 'micro509/result';

The full stable subpath list lives in the API reference.

More docs

License

MIT