@pqc-sdk/core
v0.9.1
Published
Post-quantum cryptography SDK for JS/TS: X-Wing hybrid KEM by default, plus ML-KEM-768 and ML-DSA-65 (FIPS 203/204)
Maintainers
Readme
@pqc-sdk/core
Post-quantum cryptography for JS/TS with safe defaults and zero configuration. ML-KEM-768 (FIPS 203) + AES-256-GCM for hybrid encryption, ML-DSA-65 (FIPS 204) for signatures. Validated against the official NIST ACVP test vectors.
npm install @pqc-sdk/coreimport { pqc } from '@pqc-sdk/core';
const pair = await pqc.keys.generate();
const ciphertext = await pqc.encrypt('secret', pair.publicKey);
const plaintext = await pqc.decrypt(ciphertext, pair.secretKey);
const signer = await pqc.keys.generate({ algorithm: 'ml-dsa-65' });
const signature = await pqc.sign('document', signer.secretKey);
const valid = await pqc.verify('document', signature, signer.publicKey);
console.log(new TextDecoder().decode(plaintext), valid); // "secret" trueCompatibility
| Runtime | Support | Notes |
| ------------------ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Node 20+ | ✅ | ESM and CJS |
| Cloudflare Workers | ✅ | No nodejs_compat; 43 KiB gzip total worker upload, measured 2026-09-03 |
| Deno 2+ | ✅ | npm:@pqc-sdk/core |
| Bun | ⏳ not yet run | Expected to work (it targets Node compatibility), but no roundtrip has been executed there, so it is not claimed |
| React Native | ✅ | Requires react-native-get-random-values. Streaming additionally needs a Symbol.asyncIterator alias; the Web Streams adapters do not work on Hermes — use encryptStream/decryptStream |
| Browsers | ⏳ not yet run | Expected to work on any ES2022 target with WebCrypto, but no browser roundtrip has been executed, so it is not claimed |
No WASM or native addons: pure TypeScript on top of @noble/post-quantum.
Benchmarks
GitHub Actions ubuntu-latest (x86_64, Node 20), vitest bench means, July 2026:
| Operation | Time | Throughput | | ----------------- | ---------- | ---------- | | keygen ML-KEM-768 | 0.9 ms/op | 1175 ops/s | | encrypt (1 KiB) | 1.0 ms/op | 973 ops/s | | decrypt (1 KiB) | 1.3 ms/op | 743 ops/s | | encrypt (100 KiB) | 3.5 ms/op | 285 ops/s | | decrypt (100 KiB) | 3.7 ms/op | 269 ops/s | | keygen ML-DSA-65 | 2.9 ms/op | 345 ops/s | | sign (1 KiB) | 16.5 ms/op | 60 ops/s | | verify (1 KiB) | 3.2 ms/op | 310 ops/s |
CI re-runs these on every PR and fails on regressions above 2.5x the
committed baseline (bench/baseline.json in the repo — see
bench/README.md for how the baseline is refreshed).
Documentation
Full documentation at jeloercc.github.io/pqc-sdk.
Security
- We never implement primitives: ML-KEM/ML-DSA come from
@noble/post-quantumand AES-GCM from@noble/ciphers. The risk that is ours to carry is the layer around them — envelope format, key serialization, nonce derivation, fail-closed parsing — and How this is verified lists the suite covering each: NIST ACVP vectors, golden serialization vectors, parser fuzzing,fast-checkproperty tests and the streaming mutation matrix. - No memory zeroization: shared secrets, decrypted plaintext and
secret-key bytes are not wiped after use. JavaScript offers no reliable
primitive for it and
@nobledoes not zeroize either. @noble/post-quantumhas no independent audit yet (self-audit 04/2026). As with all JS, there are no strict constant-time guarantees. The reviews indocs/are internal and AI-assisted — not an independent third-party audit.- Security reports: see SECURITY.md — please do not open public issues.
