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

@sovereignbase/cryptosuite

v2.0.5

Published

JS/TS runtime-agnostic, post-quantum, crypto-agile cryptography toolkit with a declarative API for cipher messaging, message authentication, digital signatures, key agreement, and identifiers.

Readme

npm version CI codecov license

cryptosuite

JS/TS runtime-agnostic, quantum-safe, and agile cryptography toolkit with a declarative API for cipher messaging, message authentication, digital signatures, key agreement, and identifiers.

Compatibility

  • Runtimes: Tested on browsers, bun, deno, node, edge-runtimes.
  • Module format: ESM or CJS
  • Required globals / APIs: crypto, crypto.subtle, crypto.getRandomValues
  • Types: bundled .d.ts

Goals

  • Runtime-agnostic across modern JavaScript and TypeScript environments
  • Post-quantum by default
  • Crypto-agile, with room to add or replace algorithms as recommendations evolve while keeping already issued keys backwards compatible
  • Declarative API surface that expresses cryptographic intent clearly

Current algorithms

  • Identifier: SHA-384 or 48 random bytes, encoded as a fixed-length base64url string
  • Cipher messaging: AES-CTR-256
  • Message authentication: HMAC-SHA-256
  • Key agreement: ML-KEM-1024
  • Digital signatures: ML-DSA-87

Installation

npm install @sovereignbase/cryptosuite
# or
pnpm add @sovereignbase/cryptosuite
# or
yarn add @sovereignbase/cryptosuite
# or
bun add @sovereignbase/cryptosuite
# or
deno add jsr:@sovereignbase/cryptosuite
# or
vlt install jsr:@sovereignbase/cryptosuite

Usage

Identifiers

import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'

const discoveryHook = Bytes.fromString('resource discovery hook') // Uint8Array

const newResourceId = await Cryptographic.identifier.generate() // "64xb64urlchars..."
const discoveryId = await Cryptographic.identifier.derive(discoveryHook) // "64xb64urlchars..."
const ingressId = Cryptographic.identifier.validate(discoveryId) // "64xb64urlchars..." | false

Cipher messages

import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'

const messageBytes = Bytes.fromString('hello world') // Uint8Array

const cipherKey = await Cryptographic.cipherMessage.generateKey() // JsonWebKey

const sourceKeyMaterial = Bytes.fromString('deterministic key source') // Uint8Array
const salt = Bytes.fromString('deterministic salt source') // Uint8Array
const { cipherKey } = await Cryptographic.cipherMessage.deriveKey(
  sourceKeyMaterial,
  { salt }
) // {cipherKey: JsonWebKey, salt: Uint8Array}

const cipherMessage = await Cryptographic.cipherMessage.encrypt(
  cipherKey,
  messageBytes
) // {ciphertext: ArrayBuffer, iv: Uint8Array}
const roundtrip = await Cryptographic.cipherMessage.decrypt(
  cipherKey,
  cipherMessage
) // Uint8Array

const plainMessage = Bytes.toString(roundtrip) // 'hello world'

Message authentication

import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'

const messageBytes = Bytes.fromString('authenticated payload') // Uint8Array

const generatedMessageAuthenticationKey =
  await Cryptographic.messageAuthentication.generateKey() // JsonWebKey

const sourceKeyMaterial = Bytes.fromString('deterministic key source') // Uint8Array
const salt = Bytes.fromString('deterministic salt source') // Uint8Array

const { messageAuthenticationKey } =
  await Cryptographic.messageAuthentication.deriveKey(sourceKeyMaterial, {
    salt,
  }) // {messageAuthenticationKey: JsonWebKey, salt: Uint8Array}

const tag = await Cryptographic.messageAuthentication.sign(
  generatedMessageAuthenticationKey,
  messageBytes
) // ArrayBuffer

const verified = await Cryptographic.messageAuthentication.verify(
  generatedMessageAuthenticationKey,
  messageBytes,
  tag
) // boolean

Key agreement

import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'

const sourceKeyMaterial = Bytes.fromString('k'.repeat(64)) // Uint8Array, exactly 64 bytes

const { encapsulateKey, decapsulateKey } =
  await Cryptographic.keyAgreement.generateKeypair() // {encapsulateKey: JsonWebKey, decapsulateKey: JsonWebKey}

const deterministicKeypair =
  await Cryptographic.keyAgreement.deriveKeypair(sourceKeyMaterial) // {encapsulateKey: JsonWebKey, decapsulateKey: JsonWebKey}

const { keyOffer, cipherKey: senderCipherKey } =
  await Cryptographic.keyAgreement.encapsulate(encapsulateKey) // {keyOffer: {ciphertext: ArrayBuffer}, cipherKey: JsonWebKey}

const { cipherKey: receiverCipherKey } =
  await Cryptographic.keyAgreement.decapsulate(keyOffer, decapsulateKey) // {cipherKey: JsonWebKey}

Digital signatures

import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'

const sourceKeyMaterial = Bytes.fromString('s'.repeat(32)) // Uint8Array, exactly 32 bytes
const bytes = Bytes.fromString('signed payload') // Uint8Array
const { signKey, verifyKey } =
  await Cryptographic.digitalSignature.generateKeypair() // {signKey: JsonWebKey, verifyKey: JsonWebKey}

const deterministicKeypair =
  await Cryptographic.digitalSignature.deriveKeypair(sourceKeyMaterial) // {signKey: JsonWebKey, verifyKey: JsonWebKey}

const signature = await Cryptographic.digitalSignature.sign(signKey, bytes) // Uint8Array
const verified = await Cryptographic.digitalSignature.verify(
  verifyKey,
  bytes,
  signature
) // boolean

Runtime behavior

  • identifier.generate() requires crypto.getRandomValues
  • symmetric operations use WebCrypto
  • key agreement and digital signatures use @noble/post-quantum
  • unsupported crypto primitives throw typed CryptosuiteError codes

Security notes

  • AES-CTR does not provide integrity on its own
  • authenticate or sign ciphertexts at the protocol layer
  • never reuse a (key, iv) pair
  • treat JWKs and derived key material as secrets
  • sign a canonical byte representation, not loosely structured objects

Tests

  • Unit + integration tests run against the built artifact
  • Coverage targets dist/index.cjs and is enforced at 100%
  • E2E runtime suites currently run in:
    • Node ESM
    • Node CJS
    • Bun ESM
    • Bun CJS
    • Deno ESM
    • Edge Runtime ESM
    • Chromium
    • Firefox
    • WebKit
    • Mobile Chrome emulation
    • Mobile Safari emulation
  • The runtime suite currently exercises 20/20 public API scenarios per runtime:
    • 1 static wiring check
    • 19 public methods

Benchmarks

Latest local npm run bench run on 2026-03-24 with Node v22.14.0 (win32 x64):

| Benchmark | Result | | ----------------------------------- | --------------------------- | | identifier.generate | 3.50ms (57206.6 ops/sec) | | identifier.derive | 13.94ms (14349.8 ops/sec) | | identifier.validate | 0.33ms (609942.1 ops/sec) | | cipherMessage.generateKey | 23.03ms (8682.6 ops/sec) | | cipherMessage.deriveKey | 49.73ms (4021.6 ops/sec) | | cipherMessage.encrypt | 20.91ms (9566.5 ops/sec) | | cipherMessage.decrypt | 19.18ms (10425.0 ops/sec) | | messageAuthentication.generateKey | 24.58ms (8135.2 ops/sec) | | messageAuthentication.deriveKey | 12.51ms (15987.5 ops/sec) | | messageAuthentication.sign | 12.94ms (15460.4 ops/sec) | | messageAuthentication.verify | 14.96ms (13365.2 ops/sec) | | keyAgreement.generateKeypair | 43.89ms (455.7 ops/sec) | | keyAgreement.deriveKeypair | 35.21ms (568.1 ops/sec) | | keyAgreement.encapsulate | 43.76ms (457.0 ops/sec) | | keyAgreement.decapsulate | 45.16ms (442.9 ops/sec) | | digitalSignature.generateKeypair | 165.49ms (120.8 ops/sec) | | digitalSignature.deriveKeypair | 153.20ms (130.6 ops/sec) | | digitalSignature.sign | 431.41ms (46.4 ops/sec) | | digitalSignature.verify | 155.20ms (128.9 ops/sec) |

Command: npm run bench

Results vary by machine and Node version.

Credits

Post-quantum primitives are built on top of noble.

Thanks to Paul Miller for an unusually clear, well-engineered, and genuinely awesome project.

License

Apache-2.0