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

haechi-crypto-kms

v0.2.1

Published

KMS-backed cryptoProvider satellite for Haechi (keys.provider: external) — envelope encryption with an injected KMS client.

Downloads

607

Readme

haechi-crypto-kms

A KMS-backed cryptoProvider for Haechi's keys.provider: external path. It lives in the Haechi monorepo under satellites/ and is published independently as haechi-crypto-kms. Core (haechi) stays zero-runtime-dependency, and so does this satellite by default: a KMS-client SDK (e.g. @aws-sdk/client-kms) is an optional peer dependency, installed only by consumers who use that backend.

How it works

Envelope encryption: each encrypt generates a fresh AES-256-GCM data key, encrypts the plaintext locally, and wraps the data key with the KMS. The KMS master key never leaves the KMS. decrypt unwraps the data key via the KMS and decrypts locally. hmac derives a per-domain key from the KMS, preserving Haechi's domain-separation discipline (tokens, identity, policy bundles).

The envelope matches Haechi's contract (v, alg, kid, iv, ct, tag, aadHash) plus a wrappedKey. AAD is canonicalized with canonicalize imported directly from haechi/crypto (no local copy), so it is byte-for-byte identical to the core provider's AAD and passes assertCryptoProviderConformance.

Install

npm install haechi-crypto-kms        # peer: haechi >=0.8.0 <1.0.0

The satellite reuses your installed haechi instance (declared as a peer dependency), so there is a single crypto/identity surface.

The KMS client interface

Inject any client implementing:

{
  keyId: string,
  async wrap(dataKey: Buffer): string,          // KMS-encrypt a data key
  async unwrap(wrapped: string): Buffer,         // KMS-decrypt it
  async deriveHmacKey(domain: string): Buffer    // KMS-derived per-domain key
}

createInMemoryKms() is a process-local stand-in for examples/tests. For real custody, use the bundled AWS KMS client (below) or implement the same interface over another KMS / Vault.

AWS KMS (haechi-crypto-kms/aws)

import { createRuntime } from "haechi/runtime";
import { createKmsCryptoProvider } from "haechi-crypto-kms";
import { createAwsKmsClient } from "haechi-crypto-kms/aws";

const kms = createAwsKmsClient({
  keyId: "arn:aws:kms:us-east-1:123456789012:key/abcd…",
  region: "us-east-1",
  // Required ONLY if you tokenize/authenticate (i.e. need hmac): a base64url
  // KMS-encrypted 32-byte root. Omit for encrypt-only use.
  hmacRootCiphertext: process.env.HAECHI_HMAC_ROOT
});
const runtime = createRuntime({ keys: { provider: "external" }, /* ... */ }, {
  cryptoProvider: createKmsCryptoProvider({ kms })
});

The AWS client wraps a CSPRNG-generated 32-byte data key with KMS Encrypt/Decrypt (envelope encryption — the master key never leaves KMS) and derives per-domain HMAC keys with HKDF from a single KMS-decrypted root (deterministic, domain-separated, no per-token network call).

@aws-sdk/client-kms is an optional peer dependency. Install it only if you use the AWS path:

npm install haechi-crypto-kms @aws-sdk/client-kms

It is imported lazily, so consumers on the in-memory or an injected client never pull the SDK. For tests, inject createAwsKmsClient({ keyId, client }) with a { encrypt, decrypt } mock — no SDK or network required.

Google Cloud KMS (haechi-crypto-kms/gcp)

import { createGcpKmsClient } from "haechi-crypto-kms/gcp";

const kms = createGcpKmsClient({
  keyName: "projects/p/locations/global/keyRings/r/cryptoKeys/k",
  hmacRootCiphertext: process.env.HAECHI_HMAC_ROOT // base64url, Cloud KMS-encrypted 32-byte root; omit for encrypt-only
});

Same envelope model as AWS: a CSPRNG 32-byte data key is wrapped via the crypto-key's Encrypt/Decrypt. The SDK (@google-cloud/kms) is an optional peer, imported lazily and adapted from its array-return shape ([{ ciphertext }] / [{ plaintext }]) only when no client is injected. For tests, inject createGcpKmsClient({ keyName, client }) with an { encrypt({ name, plaintext }), decrypt({ name, ciphertext }) } mock.

Azure Key Vault (haechi-crypto-kms/azure)

import { createAzureKmsClient } from "haechi-crypto-kms/azure";

const kms = createAzureKmsClient({
  keyId: "https://my-vault.vault.azure.net/keys/my-key/version",
  wrapAlgorithm: "RSA-OAEP-256",                  // default
  hmacRootCiphertext: process.env.HAECHI_HMAC_ROOT // base64url, Azure-wrapped 32-byte root; omit for encrypt-only
});

Azure natively wraps/unwraps the data key via the vault key's CryptographyClient (no local GCM envelope of the data key). @azure/keyvault-keys + @azure/identity are optional peers, imported lazily and constructed with DefaultAzureCredential() only when no client is injected. For tests, inject createAzureKmsClient({ keyId, client }) with a { wrapKey(alg, key), unwrapKey(alg, encryptedKey) } mock.

HashiCorp Vault Transit (haechi-crypto-kms/vault)

import { createVaultKmsClient } from "haechi-crypto-kms/vault";

const kms = createVaultKmsClient({
  address: "https://vault.example.com:8200",      // https required (http only for an explicit loopback dev address)
  token: process.env.VAULT_TOKEN,
  keyName: "haechi-root",                          // a NON-DERIVED transit key (no per-context derivation)
  namespace: process.env.VAULT_NAMESPACE,         // optional (Vault Enterprise)
  hmacRootCiphertext: process.env.HAECHI_HMAC_ROOT // a "vault:v1:…" transit ciphertext of a 32-byte root; omit for encrypt-only
});

The dependency-lightest backend: zero optional peer — it talks to the Transit HTTP API with node: fetch only. wrap POSTs the data key as standard base64 to /v1/transit/encrypt/{keyName} and returns the vault:v1:… ciphertext verbatim; unwrap POSTs it to /v1/transit/decrypt/{keyName} and standard-base64-decodes data.plaintext back to the data key. The transit key must be non-derived so a fixed plaintext round-trips without a context.

The Vault egress is SSRF-hardened: every request parses address, requires https (loopback-http carve-out documented), runs a post-DNS lookupisBlockedAddress re-check (refusing private/loopback/link-local/metadata ranges incl. 169.254.169.254), and uses redirect: "error" + a bounded response body + a fetch timeout — defending against an operator VAULT_ADDR that rebinds to cloud metadata. isBlockedAddress is a satellite-local copy (a key-custody package must not depend on the auth package); inject fetchImpl/lookupImpl in tests.

Usage

import { createRuntime } from "haechi/runtime";
import { createKmsCryptoProvider, createInMemoryKms } from "haechi-crypto-kms";

const cryptoProvider = createKmsCryptoProvider({ kms: createInMemoryKms() });
const runtime = createRuntime({ keys: { provider: "external" }, /* ... */ }, { cryptoProvider });

Self-test

import { assertCryptoProviderConformance } from "haechi/crypto";
await assertCryptoProviderConformance(cryptoProvider); // throws on any contract violation

This satellite is not a production key provider on its own; createInMemoryKms holds a process-local master key. Use a real KMS client for custody.