JS/TS runtime-agnostic, quantum-safe, and agile cryptography toolkit with a declarative API for cipher messaging, message authentication, digital signatures, and key agreement.
crypto, crypto.subtle, crypto.getRandomValues.d.tsAES-GCM-256HMAC-SHA-256X25519-ML-KEM-768Ed25519-ML-DSA-65npm 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
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
) // JsonWebKey
const cipherMessage = await Cryptographic.cipherMessage.encrypt(
cipherKey,
messageBytes
) // {ciphertext: Uint8Array, iv: Uint8Array}
const roundtrip = await Cryptographic.cipherMessage.decrypt(
cipherKey,
cipherMessage
) // Uint8Array
const plainMessage = Bytes.toString(roundtrip) // 'hello world'
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) // JsonWebKey
const tag = await Cryptographic.messageAuthentication.sign(
generatedMessageAuthenticationKey,
messageBytes
) // Uint8Array
const verified = await Cryptographic.messageAuthentication.verify(
generatedMessageAuthenticationKey,
messageBytes,
tag
) // boolean
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const sourceKeyMaterial = Bytes.fromString('k'.repeat(32)) // Uint8Array, exactly 32 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: Uint8Array}, cipherKey: JsonWebKey}
const { cipherKey: receiverCipherKey } =
await Cryptographic.keyAgreement.decapsulate(keyOffer, decapsulateKey) // {cipherKey: JsonWebKey}
import { Cryptographic } from '@sovereignbase/cryptosuite'
import { Bytes } from '@sovereignbase/bytecodec'
const sourceKeyMaterial = Bytes.fromString('s'.repeat(64)) // Uint8Array, exactly 64 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
info value for domain separationnoble hybrid primitivesUint8ArrayCryptosuiteError codesAES-GCM provides confidentiality and message integrity for each ciphertext(key, iv) pairLatest local npm run test run on 2026-08-29 with Node v24.16.0 (win32 x64):
63/63 unit and integration tests passed100% for statements, branches, functions, and lines17/17 public API scenarios per runtime:
Latest local npm run bench run on 2026-08-29 with Node v24.16.0 (win32 x64).
| Benchmark | ops | ms | ms/op | ops/sec |
|---|---|---|---|---|
cipherMessage.generateKey |
100 | 17.36 | 0.1736 | 5759.77 |
cipherMessage.deriveKey |
100 | 41.96 | 0.4196 | 2383.23 |
cipherMessage.encrypt |
100 | 18.99 | 0.1899 | 5264.71 |
cipherMessage.decrypt |
100 | 18.93 | 0.1893 | 5282.15 |
messageAuthentication.generateKey |
100 | 18.20 | 0.1820 | 5494.17 |
messageAuthentication.deriveKey |
100 | 38.44 | 0.3844 | 2601.46 |
messageAuthentication.sign |
100 | 8.57 | 0.0857 | 11672.70 |
messageAuthentication.verify |
100 | 7.58 | 0.0758 | 13199.93 |
keyAgreement.generateKeypair |
100 | 312.30 | 3.1230 | 320.20 |
keyAgreement.deriveKeypair |
100 | 244.60 | 2.4460 | 408.84 |
keyAgreement.encapsulate |
100 | 990.29 | 9.9029 | 100.98 |
keyAgreement.decapsulate |
100 | 803.80 | 8.0380 | 124.41 |
digitalSignature.generateKeypair |
100 | 500.13 | 5.0013 | 199.95 |
digitalSignature.deriveKeypair |
100 | 384.87 | 3.8487 | 259.83 |
digitalSignature.sign |
100 | 1922.69 | 19.2269 | 52.01 |
digitalSignature.verify |
100 | 626.36 | 6.2636 | 159.65 |
Results vary by machine and Node version.
Post-quantum primitives are built on top of noble.
Thanks to Paul Miller for an unusually clear, well-engineered, and genuinely awesome project.
Apache-2.0