Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

260 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

In a browser, no build step — it is WebCrypto and nothing else:

<script type="module">
  import { createSelfSignedCertificate } from 'https://esm.run/micro509';
</script>

Two runnable examples:

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.

import { createSelfSignedCertificate, unwrap, verifyCertificateChain } from 'micro509';

const { certificate } = await createSelfSignedCertificate({
  subject: { commonName: 'app.example.com' },
  extensions: {
    subjectAltNames: [{ type: 'dns', value: 'app.example.com' }],
  },
});

const result = await verifyCertificateChain({
  leaf: certificate.pem,
  roots: [certificate.pem],
  allowSelfSignedLeaf: true,
  serviceIdentity: { type: 'dns', value: 'evil.example.com' },
});

if (!result.ok) {
  switch (result.error.code) {
    case 'certificate_expired':
      console.log('renew the certificate at index', result.error.index);
      break;
    case 'subject_alt_name_mismatch': {
      const { expected, actual } = result.error.details ?? {};
      console.log(`identity mismatch: wanted ${expected}, presented ${actual}`);
      break;
    }
    default:
      unwrap(result); // rethrows the typed error
  }
}

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 with each signer's certificate resolved, extract cert bags
  • CRLs — create, parse, verify, and check revocation status
  • Encrypted keys — PBES2 PKCS#8, legacy OpenSSL encrypted PEM, PKCS#1, SEC1, parameter inspection without the password
  • Key import/export — PKCS#8, SPKI, JWK, PKCS#1, SEC1 with generation for RSA, ECDSA, Ed25519
  • Detached signatures — sign and verify raw bytes, ECDSA DER/raw signature conversion
  • 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 { createSelfSignedCertificate, parseCertificatePem, unwrap } from 'micro509';

const { certificate } = await createSelfSignedCertificate({
  subject: { commonName: 'example.com' },
  extensions: { extendedKeyUsage: ['serverAuth'] },
});

const parsed = unwrap(parseCertificatePem(certificate.pem));
console.log(parsed.subject.values.commonName);
console.log(parsed.serialNumberHex);
console.log(parsed.extendedKeyUsage);

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

Verify a chain:

import { createSelfSignedCertificate, verifyCertificateChain } from 'micro509';

const { certificate } = await createSelfSignedCertificate({
  subject: { commonName: 'example.com' },
  extensions: {
    extendedKeyUsage: ['serverAuth'],
    subjectAltNames: [{ type: 'dns', value: 'example.com' }],
  },
});

// Self-signed leaf as its own root: development shape, explicit opt-in
const result = await verifyCertificateChain({
  leaf: certificate.pem,
  roots: [certificate.pem],
  purpose: 'serverAuth',
  serviceIdentity: { type: 'dns', value: 'example.com' },
  allowSelfSignedLeaf: true,
});

if (result.ok) {
  console.log(result.value.chain.length, result.value.leaf.serialNumberHex);
} 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', 'pss', 'oaep' (encryption)
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 + 9919 OCSP complete
RFC 9525 service identity complete
RFC 9618 policy validation complete
RFC 7468 PEM textual encodings complete
RFC 8410 + 9295 safe-curve profiles complete
PKCS containers: RFC 5652, 7292, 8018 partial

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 { signData, verifySignature } from 'micro509/crypto';
import { generateKeyPair } from 'micro509/keys';
import { pemDecode, pemEncode } from 'micro509/pem';
import { readDerRoot, decodeDerOid } from 'micro509/der';
import type { Micro509Error } from 'micro509/result';

The full stable subpath list lives in the API reference.

More docs

License

MIT

About

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

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages