JSPM

@brivora/crypto

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 5
  • Score
    100M100P100Q40102F
  • License AGPL-3.0-or-later

Post-quantum cryptography in 3 lines of TypeScript. The Stripe for PQC.

Package Exports

  • @brivora/crypto

Readme

@brivora/crypto

Post-quantum cryptography in 3 lines of TypeScript.

License: AGPL v3 Node.js


import { crypto } from '@brivora/crypto';
const keys = await crypto.createIdentity();
const signed = await crypto.sign(data, keys.privateKey);

What is this?

@brivora/crypto is an opinionated, batteries-included post-quantum cryptography library for JavaScript/TypeScript. The "Stripe for PQC."

  • Hybrid by default — Classical (Ed25519 + X25519) + Post-Quantum (ML-DSA-65 + ML-KEM-768). Both must be broken to compromise security.
  • NIST FIPS compliant — ML-KEM-768 (FIPS 203), ML-DSA-65 (FIPS 204), finalized August 2024.
  • Self-describing payloads — Every encrypted/signed payload includes version and algorithm metadata.
  • Zero configuration — Sensible defaults. No crypto PhD required.
  • Pure TypeScript — No native modules. No WASM. Works everywhere: Node.js, Deno, Bun, browsers.
  • Zero telemetry — No analytics. No network calls. Pure local computation.

Install

npm install @brivora/crypto
# or
pnpm add @brivora/crypto
# or
yarn add @brivora/crypto

Quick Start

Create an Identity

import { crypto } from '@brivora/crypto';

const identity = await crypto.createIdentity();
// {
//   publicKey: { classical: { signing, encryption }, pqc: { signing, encryption } },
//   privateKey: { classical: { signing, encryption }, pqc: { signing, encryption } },
//   fingerprint: 'a1b2c3d4...',
//   algorithm: 'hybrid-pqc-v1',
//   createdAt: '2026-02-13T...'
// }

Encrypt & Decrypt

// Alice encrypts a message for Bob
const encrypted = await crypto.encrypt('secret message', bob.publicKey);

// Bob decrypts
const plaintext = await crypto.decrypt(encrypted, bob.privateKey);
// Uint8Array → use new TextDecoder().decode(plaintext) for strings

Sign & Verify

// Sign data
const signed = await crypto.sign('important data', alice.privateKey);

// Verify signature
const { valid, data } = await crypto.verify(signed, alice.publicKey);
// valid: true, data: Uint8Array of original data

Key Rotation

const { newIdentity, migration } = await crypto.rotateKeys(oldIdentity);
// migration is a signed proof linking old key → new key

Key Derivation

const masterKey = crypto.randomBytes(32);
const encKey = crypto.deriveKey(masterKey, 'encryption');
const authKey = crypto.deriveKey(masterKey, 'authentication');
// Different contexts → different deterministic keys

Migrate from Ed25519

const upgraded = await crypto.upgradeKey({
  publicKey: existingEd25519PublicKey,
  secretKey: existingEd25519SecretKey,
});
// upgraded.identity is now a hybrid PQC identity
// upgraded.migration is a signed proof of the upgrade

PQC-Only Mode

// Disable classical crypto (PQC-only)
const encrypted = await crypto.encrypt(data, pubKey, { hybrid: false });
const signed = await crypto.sign(data, privKey, { hybrid: false });

API Reference

Identity

Method Description
crypto.createIdentity(options?) Create a new hybrid identity
crypto.exportKey(identity, format?) Serialize identity for storage
crypto.importKey(serialized) Restore identity from serialized form
crypto.exportPublicKey(identity) Export only the public key (safe to share)
crypto.importPublicKey(encoded) Import a shared public key

Encryption

Method Description
crypto.encrypt(data, recipientPublicKey, options?) Hybrid encrypt (X25519 + ML-KEM-768 + AES-256-GCM)
crypto.decrypt(encrypted, privateKey) Decrypt with your private key

Signatures

Method Description
crypto.sign(data, privateKey, options?) Hybrid sign (Ed25519 + ML-DSA-65)
crypto.verify(signed, publicKey?) Verify a signed payload

Key Management

Method Description
crypto.rotateKeys(oldIdentity, newIdentity?) Rotate keys with migration proof
crypto.deriveKey(masterKey, context, length?) HKDF-SHA256 key derivation

Migration

Method Description
crypto.upgradeKey(ed25519KeyPair) Upgrade Ed25519 → hybrid PQC

Utilities

Method Description
crypto.hash(data, algorithm?) SHA-256 (default), SHA-384/512, SHA3-256/512
crypto.randomBytes(length) CSPRNG random bytes
crypto.fingerprint(...keys) SHA-256 fingerprint of public keys

Algorithms

Algorithm Standard Usage
ML-KEM-768 FIPS 203 Key encapsulation (encryption)
ML-DSA-65 FIPS 204 Digital signatures
X25519 RFC 7748 Classical key exchange (hybrid)
Ed25519 RFC 8032 Classical signatures (hybrid)
AES-256-GCM FIPS 197 Symmetric encryption
HKDF-SHA256 RFC 5869 Key derivation
SHA-256 FIPS 180-4 Hashing, fingerprinting

How Hybrid Mode Works

Encryption (X25519 + ML-KEM-768)

  1. Generate ephemeral X25519 key pair
  2. Compute classical shared secret via X25519 ECDH
  3. Encapsulate PQC shared secret via ML-KEM-768
  4. Combine both secrets via HKDF-SHA256
  5. Encrypt plaintext with AES-256-GCM

An attacker must break both X25519 and ML-KEM-768 to recover the plaintext.

Signing (Ed25519 + ML-DSA-65)

  1. Sign data with Ed25519
  2. Sign data with ML-DSA-65
  3. Both signatures must verify for the payload to be valid

An attacker must forge both an Ed25519 and ML-DSA-65 signature.

Tree Shaking

Import only what you need:

// Only signing — no encryption code in your bundle
import { sign, verify, createIdentity } from '@brivora/crypto';

Security

  • Constant-time comparisons — All byte comparisons use constant-time algorithms to prevent timing side-channels.
  • CSPRNG — All random bytes from crypto.getRandomValues() (OS-level CSPRNG).
  • No network calls — Everything runs locally. Zero telemetry. Zero analytics.
  • Audited primitives — Built on @noble/post-quantum (audited by Cure53).

See SECURITY.md for our security policy and responsible disclosure process.

Requirements

  • Node.js 20+ (also works in Deno, Bun, and modern browsers)
  • Web Crypto API (globalThis.crypto.subtle)

Built On

License

AGPL-3.0-or-laterBrivora, LLC