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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@musicslayer/easy_ssl

v1.0.7

Published

Easily generate SSL certificates.

Downloads

4

Readme

Easy SSL

Easily generate SSL certificates

This code is an independent rewriting of the Root acme.js repository. The goal was to streamline the functionality and make the code easier to understand.

This code has no external dependencies, although it operates under a "bring your own challenge plugin" model. For example, if the domain you wish to create a certificate for is hosted by Cloudflare, you will need to provide a challenge plugin that can interact with the Cloudflare API. You may write your own, but it is recommended that you use the plugins written by Root. See this page for more information.

Installation Instructions

Package available on NPM.

> npm install @musicslayer/easy_ssl

Any Root challenge plugins that you use must also be installed. For example, if your domain is hosted on Cloudflare:

> npm install acme-dns-01-cloudflare

Example Usage

The three provided example apps demonstrate the basic workflow.

Account Key Creation

app_createAccountKeyAndKID.js will create a new private key and use that to create a Let's Encrypt account. The account private key and the KID (key ID) of the new account are written to a file to be accessed later.

[!IMPORTANT] This only needs to be done once. The same account can be reused to create more certificates.

Server Key Creation

app_createServerKey.js will create a new private key to represent the server that you are getting the certificate for. This private key is different than the private key for the account that we created before. The server private key is written to a file to be accessed later.

[!IMPORTANT] This step only needs to be done once per server that you are getting certificates for. The same server key can be reused to create more certificates.

Certificate Creation

app_createCertificate.js will create an SSL certificate signed by Let's Encrypt. The account private key, account KID, and the server private key from before are used.

An array of domains that we wish to certify is provided. Note that we will get one certificate that covers the set of domains, NOT an individual certificate per domain.

In this example, the domains are hosted by Cloudflare and thus we use the Root Cloudflare challenge plugin. We must provide a Cloudflare API key with "Zone:Zone:Read" and "Zone:DNS:Edit" permissions.

API

createPrivateKey(keyOptions)

Creates a public/private key pair. Only the private key is returned.

Arguments:

  • keyOptions is an object with the following fields:

    • kty = "EC"
    • shaBits = 224, 256, 384, or 512
    • crv = "P-224", "P-256", "P-384", or "P-521" (P-521 is NOT a typo! It really is called P-521 and not P-512.)

    OR

    • kty = "RSA"
    • shaBits = 224, 256, 384, or 512
    • modulusLength (e.g. 2048)
    • publicExponent (eg 0x10001)

kty is the keypair type, either "EC" (Elliptic Curve) or "RSA" (Rivest–Shamir–Adleman).

For both EC and RSA, shaBits is the number of bits in the SHA digest.

For EC, crv is the name of the elliptic curve used by the EC algorithm.

For RSA, modulusLength and publicExponent are both numbers used by the RSA algorithm.

[!IMPORTANT] Not all combinations are supported by Let's Encrypt. According to here, Let’s Encrypt only supports modulusLength = 2048, 3072, or 4096 and crv = "P-256" or "P-384". Also for EC, shaBits and crv must correspond to each other, so for example if you choose shaBits = 256, you must use crv = "P-256".

createAccount(accountKey, directoryUrl)

Creates a Let's Encrypt account.

Arguments:

  • accountKey is a private key generated from "createPrivateKey".
  • directoryUrl is a URL where the rest of the Let's Encrypt API URLs can be queried. Currently, the possible values for this are:
    • Production: "https://acme-v02.api.letsencrypt.org/directory"
    • Staging: "https://acme-staging-v02.api.letsencrypt.org/directory"

createCertificate(accountKey, serverKey, kid, directoryUrl, domains, challengePlugins)

Creates an SSL certificate signed by Let's Encrypt.

Arguments:

  • accountKey is a private key generated from "createPrivateKey".
  • serverKey is a private key generated from "createPrivateKey". This should be different from the account key.
  • kid is the key ID associated with the account.
  • directoryUrl is a URL where the rest of the Let's Encrypt API URLs can be queried. Currently, the possible values for this are:
    • Production: "https://acme-v02.api.letsencrypt.org/directory"
    • Staging: "https://acme-staging-v02.api.letsencrypt.org/directory"
  • domains is an array of domains that you wish to create the certificate for. Entries with wildcards such as "*.shop.yourdomain.com" are permitted.
  • challengePlugins is an object mapping different challenge types to a plugin that will be responsible for handling them (see section below for more information). It is highly recommended that you use the Root challenge plugins, although you can also create your own.

Challenge Plugins

The challengePlugins argument to "createCertificate" will look like this:

challengePlugins = {
	"dns-01": plugin_for_dns,
	"http-01": plugin_for_http
}

Where each type of challenge that we wish to handle is mapped to a challenge plugin that can handle it. In our examples, the Cloudflare plugin is a DNS plugin, so we map it with "dns-01". We omit the "http-01" entry since we do not provide a plugin to handle those types of challenges.

You must either omit an entry or map it to exactly one plugin i.e. you cannot provide an array of plugins. Also, the program itself will decide which plugins can be used, and which priority they will take if more than one are provided.

[!IMPORTANT] This code only supports "dns-01" and "http-01". Although the Root code does mention "tls-alpn-01", in my rewriting I decided not to provide any support for it.

Additional Tips

Deprecation Warnings

When running the examples with the Root Cloudflare challenge plugin, you may see the following printed to the console:

(node:13104) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated
(Use `node --trace-deprecation ...` to show where the warning was created)

This is caused by code within the plugin itself and can be ignored.

Domains

A typical use case is to create a single certificate that covers your domain and all possible subdomains. For example, "yourdomain.com", "shop.yourdomain.com", "support.shop.yourdomain.com", etc.

To achieve this, call "createCertificate" with domains set to:

domains = ["*.yourdomain.com", "yourdomain.com"]

The wildcard entry will cover all possible subdomains, but you must explicitly specify the base domain in order for that to be covered as well.