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

base-acme-client

v30.0.3

Published

Implementation of the Automatic Certificate Management Environment in Javascript (RFC8555)

Downloads

3,010

Readme

Automatic Certificate Management Environment (ACME)

A module for interacting with ACME servers for automated SSL/TLS certificate issuance and management.

Exports

import * as bac from 'base-acme-client'; // ES6

newDirectory

Fetches the directory information from an ACME server.

/**
 * Fetches the directory information from an ACME server.
 * @async
 * 
 * @param {string} mainDirectoryUrl - The URL of the ACME server's directory endpoint
 * 
 * @returns {Promise<Object>} An object containing the directory information or an error
 * @property {Object|null} get - The parsed directory JSON or null
 * 
 * @property {null|Object} error - The error response if the request was unsuccessful
 */
export async function newDirectory(mainDirectoryUrl) { /*...*/ }

newNonce

Retrieves a new nonce from the ACME server.

/**
 * Retrieves a new nonce from the ACME server.
 * @async
 * 
 * @param {string} [newNonceUrl] - ACME Directory URL to fetch a new nonce.
 * 
 * @returns {Promise<Object>} An object containing the nonce or error details
 * @property {string|null} nonce - A new replay nonce for subsequent requests
 * 
 * @property {null|Object} error - The error response if the request was unsuccessful
 */
export async function newNonce(newNonceUrl) { /*...*/ }

createJsonWebKey

Creates a JSON Web Key (JWK) from a public key.

/**
 * Creates a JSON Web Key (JWK) from a public key.
 * @async
 * 
 * @param {Object} publicKey - The public key to convert to JWK format
 * 
 * @returns {Promise<Object>} An object containing the JWK and its thumbprint
 * @property {Object} key - The JSON Web Key representation
 * @property {string} print - Base64URL encoded thumbprint of the key
 */
export async function createJsonWebKey(publicKey) { /*...*/ }

createAccount

Creates a new account on the ACME server.

/**
 * Creates a new account on the ACME server.
 * @async
 * 
 * @param {string} nonce - The replay nonce from the server
 * @param {string} newAccountUrl - The URL for creating a new account
 * @param {Object} privateKey - The private key for signing the request
 * @param {Object} jsonWebKey - The JSON Web Key representing the account's public key
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * 
 * @returns {Promise<Object>} An object containing the account creation result
 * @property {Object|null} get - The created account details
 * @property {string|null} location - The location URL of the created account
 * @property {string|null} nonce - A new replay nonce for subsequent requests
 * 
 * @property {null|Object} error - Error details if account creation fails
 */
export async function createAccount(nonce, newAccountUrl, privateKey, jsonWebKey) { /*...*/ }

createOrder

Creates a new order for certificate issuance on the ACME server.

/**
 * Creates a new order for certificate issuance on the ACME server.
 * @async
 * 
 * @param {string} kid - Key Identifier for the account
 * @param {string} nonce - The replay nonce from the server
 * @param {Object} privateKey - The private key for signing the request
 * @param {string[]} identifiers - Domain names to be included in the certificate
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * 
 * @returns {Promise<Object>} An object containing the order creation result
 * @property {Object|null} get - The created order details
 * @property {string|null} location - The location URL of the created order
 * @property {string|null} nonce - A new replay nonce for subsequent requests
 * 
 * @property {null|Object} error - Error details if order creation fails
 */
export async function createOrder(kid, nonce, privateKey, newOrderUrl, identifiers) { /*...*/ }

finalizeOrder

Finalizes a certificate order by submitting a Certificate Signing Request (CSR).

/**
 * Finalizes a certificate order by submitting a Certificate Signing Request (CSR).
 * @async
 * 
 * @param {string} commonName - The primary domain name for the certificate
 * @param {string} kid - Key Identifier for the account
 * @param {string} nonce - The replay nonce from the server
 * @param {Object} privateKey - The private key for signing the request
 * @param {Object} publicKeySign - Public key used for signing the CSR
 * @param {Object} privateKeySign - Private key used for signing the CSR
 * @param {string} finalizeUrl - The URL for finalizing the order
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * @param {string[]} dnsNames - Additional DNS names to be included in the certificate
 * 
 * @returns {Promise<Object>} An object containing the order finalization result
 * @property {Object|null} get - The finalized order details
 * @property {string|null} location - The location URL of the finalized order
 * @property {string|null} nonce - A new replay nonce for subsequent requests
 * 
 * @property {null|Object} error - Error details if finalization fails
 */
export async function finalizeOrder(commonName, kid, nonce, privateKey, publicKeySign, privateKeySign, finalizeUrl, dnsNames) { /*...*/ }

postAsGet

Performs a POST-as-GET request to retrieve order or authorization status.

/**
 * Performs a POST-as-GET request to retrieve order or authorization status.
 * @async
 * 
 * @param {string} kid - Key Identifier for the account
 * @param {string} nonce - The replay nonce from the server
 * @param {Object} privateKey - The private key for signing the request
 * @param {string} url - The URL to retrieve status from
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * 
 * @returns {Promise<Object>} An object containing the retrieved information
 * @property {Object|null} get - The retrieved resource details
 * @property {string|null} location - The location URL of the resource
 * @property {string|null} nonce - A new replay nonce for subsequent requests
 * 
 * @property {null|Object} error - Error details if retrieval fails
*/
export async function postAsGet(kid, nonce, privateKey, url) { /*...*/ }

postAsGetChal

Performs a POST-as-GET request for challenges

/**
 * Performs a POST-as-GET request for challenges
 * @async
 * 
 * @param {string} kid - Key Identifier for the account
 * @param {string} nonce - The replay nonce from the server
 * @param {Object} privateKey - The private key for signing the request
 * @param {string} url - The URL to retrieve challenge details from
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * 
 * @returns {Promise<Object>} An object containing the challenge details
 * @property {Object|null} get - The retrieved challenge details
 * @property {string|null} location - The location URL of the challenge
 * @property {string|null} nonce - A new replay nonce for subsequent requests
 * 
 * @property {null|Object} error - Error details if retrieval fails
 */
export async function postAsGetChal(kid, nonce, privateKey, url) { /*...*/ }

signPayloadJson

Signs a JSON payload for ACME server requests.

/**
 * Signs a JSON payload for ACME server requests.
 * @async
 * 
 * @param {Object} payload - The payload to be signed
 * @param {Object} protectedHeader - The protected header containing metadata
 * @param {Object} privateKey - The private key used for signing
 * 
 * @returns {Promise<string>} A JSON Web Signature (JWS) string
 */
export async function signPayloadJson(payload, protectedHeader, privateKey) { /*...*/ }

signPayload

Signs a payload for ACME server requests.

/**
 * Signs a payload for ACME server requests.
 * @async
 * 
 * @param {string|Object} payload - The payload to be signed
 * @param {Object} protectedHeader - The protected header containing metadata
 * @param {Object} privateKey - The private key used for signing
 * 
 * @returns {Promise<string>} A JSON Web Signature (JWS) string
 */
export async function signPayload(payload, protectedHeader, privateKey) { /*...*/ }

formatPublicKey

Formats a PEM-encoded public key to a key object.

/**
 * Formats a PEM-encoded public key to a key object.
 * 
 * @param {string} pem - The PEM-encoded public key
 * 
 * @returns {Object} A formatted public key object
 */
export function formatPublicKey(pem) { /*...*/ }

formatPrivateKey

Formats a PEM-encoded private key to a key object.

/**
 * Formats a PEM-encoded private key to a key object.
 * 
 * @param {string} pem - The PEM-encoded private key
 * 
 * @returns {Object} A formatted private key object
 */
export function formatPrivateKey(pem) { /*...*/ }

base64urlEncode

Encodes input to a base64url-encoded string.

/**
 * Encodes input to a base64url-encoded string.
 *
 * @param {string|Uint8Array} input - The input to encode
 * 
 * @returns {string} A base64url-encoded string
 */
export function base64urlEncode(input) { /*...*/ }

hexToBytes

Converts a hexadecimal string to a Uint8Array of bytes.

/**
 * Converts a hexadecimal string to a Uint8Array of bytes.
 * 
 * @param {string} hex - The hexadecimal string to convert. It should contain an even number of characters.
 * 
 * @returns {Uint8Array} A Uint8Array containing the byte values represented by the hexadecimal string.
 * @throws {Error} Throws an error if the input string has an odd length or contains invalid hexadecimal characters.
 */
export function hexToBytes(hex) { /*...*/ }

getNextNonce

Retrieves the next nonce for ACME protocol requests.

/**
 * Retrieves the next nonce for ACME protocol requests.
 *
 * If a replay nonce is provided in the headers, it will return that nonce.
 * Otherwise, it will request a new nonce from the ACME directory.
 *
 * @async
 * 
 * @param {Headers} headers - The headers object containing the replay nonce.
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * 
 * @returns {Promise<string|null>} A promise that resolves to the next nonce as a string,
 *                                  or null if no nonce is available.
 */
export async function getNextNonce(headers, acmeDirectory) { /*...*/ }

fetchRequest

Sends a signed request to the ACME server.

/**
 * Sends a signed request to the ACME server.
 * @async
 * 
 * @param {string} method - The HTTP method to use (e.g., 'GET', 'POST')
 * @param {string} url - The URL to send the request to
 * @param {string} signedData - The signed payload to send
 * 
 * @returns {Promise<Response>} The response from the server
 */
export async function fetchRequest(method, url, signedData) { /*...*/ }

fetchSuggestedWindow

Fetches the suggested renewal window information for a certificate from the specified URL.

/**
 * Fetches the suggested renewal window information for a certificate from the specified URL.
 * @async
 * 
 * @param {string} renewalInfoUrl - The base URL for fetching renewal information.
 * @param {string} aki- The Authority Key Identifier in hexadecimal format.
 * @param {string} serial - The serial number in hexadecimal format.
 * 
 * @returns {Promise<Object>} A promise that resolves to the parsed JSON of the suggested window
 * @property {Object|null} get - The retrieved suggested window
 * 
 * @property {null|Object} error - Error details if retrieval fails
 * 
 * @throws {Error} Throws an error if the fetch operation fails.
 */
export async function fetchSuggestedWindow(renewalInfoUrl, aki, serial) { /*...*/ }

fetchAndRetryUntilOk

Fetch a resource with multiple retry attempts and progressive backoff.

/**
 * Fetch a resource with multiple retry attempts and progressive backoff.
 * @async
 * 
 * @param {string|Request} fetchInput - The URL or Request object to fetch
 * @param {Object} init - optional fetch init object
 * @param {number} [attempts=6] - Maximum number of fetch attempts
 * @param {boolean} silent - true to suppress console output on failure attempt
 * 
 * @returns {Promise<Response|undefined>} The response or undefined if all attempts fail
 * 
 * @description
 * This function attempts to fetch a resource with the following characteristics:
 * - Starts with one fetch attempt
 * - Increments attempts progressively
 * - Implements an increasing delay between failed attempts (650ms * attempt number)
 * - Logs any caught exceptions
 * - Returns immediately on a successful (ok) response
 * - Returns the last response or undefined if all attempts are exhausted
 * 
 * @example
 * const response = await fetchAndRetyUntilOk('https://api.example.com/data');
 * if (response && response.ok) {
 *   const data = await response.json();
 *   // Process successful response
 * }
 */
export async function fetchAndRetryUntilOk(fetchInput, init, attempts = 6, silent = false) { /*...*/ }

fetchAndRetryProtectedUntilOk

Fetch a protected resource with multiple retry attempts and progressive backoff.

/**
 * Fetch a protected resource with multiple retry attempts and progressive backoff.
 * @async
 *
 * @param {Object} payload - The payload to be sent with the request
 * @param {Object} protectedHeader - The protected header containing metadata for the request
 * @param {Object} privateKey - The private key for signing the request
 * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations
 * @param {number} [attempts=6] - Maximum number of fetch attempts (default: 6)
 * @param {boolean} silent - true to suppress console output on failure attempt
 * 
 * @returns {Promise<Response|undefined>} The response or undefined if all attempts fail
 *
 * @description
 * This function attempts to fetch a protected resource with the following characteristics:
 * - Starts with one fetch attempt
 * - Increments attempts progressively
 * - Implements an increasing delay between failed attempts (650ms * attempt number)
 * - Logs any caught exceptions
 * - Returns immediately on a successful (ok) response
 * - Returns the last response or undefined if all attempts are exhausted
 *
 * @example
 * const response = await fetchAndRetryProtectedUntilOk(
 *   payload, 
 *   protectedHeader, 
 *   privateKey, 
 *   acmeDirectory
 * );
 * if (response && response.ok) {
 *   const data = await response.json();
 *   // Process successful response
 * }
 */
export async function fetchAndRetryProtectedUntilOk(payload, protectedHeader, privateKey, acmeDirectory, attempts = 3, silent = false) { /*...*/ }

Errors/Exceptions

Errors and Exceptions will be returned in an object

// Exceptions
{
  error: {
    type: 'bac:exception:methodName',
    detail: Error: SyntaxError: Unexpected end of input
        at file:///base-acme-client.js:666:11
        at ModuleJob.run (node:internal/modules/esm/module_job:271:25)
        at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:547:26)
        at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:116:5),
    status: 777777
  }
}

// Error from the Base ACME Client
{
  error: {
    type: 'bac:failed:methodName',
    detail: 'Could not complete methodName after multiple attempts',
    status: 777777
  }
}

// Error from the ACME Server
{
  error: {
    type: 'urn:ietf:params:acme:error:orderNotReady',
    detail: `Order's status ("valid") is not acceptable for finalization`,
    status: 403
  }
}

Full Working Examples

This module is used by Lets Encrypt ACME Client and Server SSL