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 🙏

© 2025 – Pkg Stats / Ryan Hefner

selfsigned

v5.2.0

Published

Generate self signed certificates private and public keys

Readme

selfsigned

Generate self-signed X.509 certificates using Node.js native crypto.

Install

npm install selfsigned

Requirements

  • Node.js >= 15.6.0 (for native WebCrypto support)

Usage

Version 5.0 is async-only. The generate() function now returns a Promise.

const selfsigned = require('selfsigned');

const attrs = [{ name: 'commonName', value: 'contoso.com' }];
const pems = await selfsigned.generate(attrs);
console.log(pems);

Output

{
  private: '-----BEGIN PRIVATE KEY-----\n...',
  public: '-----BEGIN PUBLIC KEY-----\n...',
  cert: '-----BEGIN CERTIFICATE-----\n...',
  fingerprint: 'XX:XX:XX:...'
}

Options

const pems = await selfsigned.generate(null, {
  keySize: 2048, // the size for the private key in bits (default: 2048)
  notBeforeDate: new Date(), // start of certificate validity (default: now)
  notAfterDate: new Date('2026-01-01'), // end of certificate validity (default: notBeforeDate + 365 days)
  algorithm: 'sha256', // sign the certificate with specified algorithm (default: 'sha1')
  extensions: [{ name: 'basicConstraints', cA: true }], // certificate extensions array
  clientCertificate: true, // generate client cert (default: false) - can also be an options object
  ca: { key: '...', cert: '...' }, // CA key and cert for signing (default: self-signed)
  passphrase: 'secret' // encrypt the private key with a passphrase (default: none)
});

Setting Custom Validity Period

Use notBeforeDate and notAfterDate to control certificate validity:

// Using date-fns
const { addDays, addYears } = require('date-fns');

const pems = await selfsigned.generate(null, {
  notBeforeDate: new Date(),
  notAfterDate: addDays(new Date(), 30) // Valid for 30 days
});

// Or with vanilla JS
const notBefore = new Date();
const notAfter = new Date(notBefore);
notAfter.setFullYear(notAfter.getFullYear() + 2); // Valid for 2 years

const pems = await selfsigned.generate(null, {
  notBeforeDate: notBefore,
  notAfterDate: notAfter
});

Supported Algorithms

  • sha1 (default)
  • sha256
  • sha384
  • sha512

Using Your Own Keys

You can avoid key pair generation by specifying your own keys:

const pems = await selfsigned.generate(null, {
  keyPair: {
    publicKey: '-----BEGIN PUBLIC KEY-----...',
    privateKey: '-----BEGIN PRIVATE KEY-----...'
  }
});

Encrypting the Private Key

You can encrypt the private key with a passphrase using AES-256-CBC:

const pems = await selfsigned.generate(null, {
  passphrase: 'my-secret-passphrase'
});

// The private key will be in encrypted PKCS#8 format:
// -----BEGIN ENCRYPTED PRIVATE KEY-----
// ...
// -----END ENCRYPTED PRIVATE KEY-----

To use the encrypted key, provide the passphrase:

const crypto = require('crypto');

// Decrypt the key
const privateKey = crypto.createPrivateKey({
  key: pems.private,
  passphrase: 'my-secret-passphrase'
});

// Or use directly with HTTPS server
const https = require('https');
https.createServer({
  key: pems.private,
  passphrase: 'my-secret-passphrase',
  cert: pems.cert
}, app).listen(443);

Signing with a CA

You can generate certificates signed by an existing Certificate Authority instead of self-signed certificates. This is useful for development environments where you want browsers to trust your certificates.

const fs = require('fs');
const selfsigned = require('selfsigned');

const pems = await selfsigned.generate([
  { name: 'commonName', value: 'localhost' }
], {
  algorithm: 'sha256',
  ca: {
    key: fs.readFileSync('/path/to/ca.key', 'utf8'),
    cert: fs.readFileSync('/path/to/ca.crt', 'utf8')
  }
});

The generated certificate will be signed by the provided CA and will include:

  • Subject Alternative Name (SAN) extension with DNS name matching the commonName
  • For localhost, an additional IP SAN for 127.0.0.1
  • Key Usage: digitalSignature, keyEncipherment
  • Extended Key Usage: serverAuth, clientAuth

Using with mkcert

mkcert is a simple tool for making locally-trusted development certificates. Combining it with selfsigned provides an excellent developer experience:

  • No certificate files to manage - generate trusted certificates on-the-fly at server startup
  • No git-ignored cert files - nothing to store, share, or accidentally commit
  • Browsers trust the certificates automatically - no security warnings during development
const https = require('https');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const selfsigned = require('selfsigned');

// Get mkcert's CA (requires: brew install mkcert && mkcert -install)
const caroot = execSync('mkcert -CAROOT', { encoding: 'utf8' }).trim();

const pems = await selfsigned.generate([
  { name: 'commonName', value: 'localhost' }
], {
  algorithm: 'sha256',
  ca: {
    key: fs.readFileSync(path.join(caroot, 'rootCA-key.pem'), 'utf8'),
    cert: fs.readFileSync(path.join(caroot, 'rootCA.pem'), 'utf8')
  }
});

// Start server with browser-trusted certificate - no files written to disk
https.createServer({ key: pems.private, cert: pems.cert }, app).listen(443);

See examples/https-server-mkcert.js for a complete working example.

Attributes

Attributes follow the X.509 standard:

const attrs = [
  { name: 'commonName', value: 'example.org' },
  { name: 'countryName', value: 'US' },
  { shortName: 'ST', value: 'Virginia' },
  { name: 'localityName', value: 'Blacksburg' },
  { name: 'organizationName', value: 'Test' },
  { shortName: 'OU', value: 'Test' }
];

Generate Client Certificates

For environments where servers require client certificates, you can generate client keys signed by the original (server) key:

const pems = await selfsigned.generate(null, { clientCertificate: true });
console.log(pems);

Output includes additional client certificate fields:

{
  private: '-----BEGIN PRIVATE KEY-----\n...',
  public: '-----BEGIN PUBLIC KEY-----\n...',
  cert: '-----BEGIN CERTIFICATE-----\n...',
  fingerprint: 'XX:XX:XX:...',
  clientprivate: '-----BEGIN PRIVATE KEY-----\n...',
  clientpublic: '-----BEGIN PUBLIC KEY-----\n...',
  clientcert: '-----BEGIN CERTIFICATE-----\n...'
}

Client Certificate Options

The clientCertificate option can be true for defaults, or an options object for full control:

const pems = await selfsigned.generate(null, {
  clientCertificate: {
    cn: 'jdoe',                              // common name (default: 'John Doe jdoe123')
    keySize: 4096,                           // key size in bits (default: 2048)
    algorithm: 'sha256',                     // signature algorithm (default: inherits from parent or 'sha1')
    notBeforeDate: new Date(),               // validity start (default: now)
    notAfterDate: new Date('2026-01-01')     // validity end (default: notBeforeDate + 1 year)
  }
});

Simple example with just a custom CN:

const pems = await selfsigned.generate(null, {
  clientCertificate: { cn: 'FooBar' }
});

PKCS#7 Support

PKCS#7 formatting is available through a separate module for better tree-shaking:

const selfsigned = require('selfsigned');
const { createPkcs7 } = require('selfsigned/pkcs7');

const pems = await selfsigned.generate(attrs);
const pkcs7 = createPkcs7(pems.cert);
console.log(pkcs7); // PKCS#7 formatted certificate

You can also create PKCS#7 for client certificates:

const pems = await selfsigned.generate(null, { clientCertificate: true });
const clientPkcs7 = createPkcs7(pems.clientcert);

Migration from v4.x

Version 5.0 introduces breaking changes:

Breaking Changes

  1. Async-only API: The generate() function is now async and returns a Promise. Synchronous generation is no longer supported.
  2. No callback support: Callbacks have been removed. Use async/await or .then().
  3. Minimum Node.js version: Now requires Node.js >= 15.6.0 (was >= 10).
  4. Dependencies: Replaced node-forge with @peculiar/x509 and pkijs (66% smaller bundle size).
  5. days option removed: Use notAfterDate instead. Default validity is 365 days from notBeforeDate.

Migration Examples

Old (v4.x):

// Sync
const pems = selfsigned.generate(attrs, { days: 365 });

// Callback
selfsigned.generate(attrs, { days: 365 }, function(err, pems) {
  if (err) throw err;
  console.log(pems);
});

New (v5.x):

// Async/await (default 365 days validity)
const pems = await selfsigned.generate(attrs);

// Custom validity with notAfterDate
const notAfter = new Date();
notAfter.setDate(notAfter.getDate() + 30); // 30 days
const pems = await selfsigned.generate(attrs, { notAfterDate: notAfter });

// Or with .then()
selfsigned.generate(attrs)
  .then(pems => console.log(pems))
  .catch(err => console.error(err));

License

MIT