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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@noble/post-quantum

v0.4.0

Published

Auditable & minimal JS implementation of post-quantum public-key cryptography: FIPS 203, 204, 205

Downloads

4,009

Readme

noble-post-quantum

Auditable & minimal JS implementation of post-quantum public-key cryptography.

  • 🔒 Auditable
  • 🔻 Tree-shakeable: unused code is excluded from your builds
  • 🔍 Reliable: tests ensure correctness
  • 🦾 ML-KEM & CRYSTALS-Kyber: lattice-based kem from FIPS-203
  • 🔋 ML-DSA & CRYSTALS-Dilithium: lattice-based signatures from FIPS-204
  • 🐈 SLH-DSA & SPHINCS+: hash-based Winternitz signatures from FIPS-205
  • 🪶 37KB (15KB gzipped) for everything with bundled hashes

Take a glance at GitHub Discussions for questions and support.

[!IMPORTANT] NIST published IR 8547, prohibiting classical cryptography (RSA, DSA, ECDSA, ECDH) after 2035. Australian ASD does same thing after 2030. Take it into an account while designing a new cryptographic system.

This library belongs to noble cryptography

noble cryptography — high-security, easily auditable set of contained cryptographic libraries and tools.

Usage

npm install @noble/post-quantum

deno add jsr:@noble/post-quantum

deno doc jsr:@noble/post-quantum # command-line documentation

We support all major platforms and runtimes. For React Native, you may need a polyfill for getRandomValues. A standalone file noble-post-quantum.js is also available.

// import * from '@noble/post-quantum'; // Error: use sub-imports instead
import { ml_kem512, ml_kem768, ml_kem1024 } from '@noble/post-quantum/ml-kem';
import { ml_dsa44, ml_dsa65, ml_dsa87 } from '@noble/post-quantum/ml-dsa';
import {
  slh_dsa_sha2_128f,
  slh_dsa_sha2_128s,
  slh_dsa_sha2_192f,
  slh_dsa_sha2_192s,
  slh_dsa_sha2_256f,
  slh_dsa_sha2_256s,
  slh_dsa_shake_128f,
  slh_dsa_shake_128s,
  slh_dsa_shake_192f,
  slh_dsa_shake_192s,
  slh_dsa_shake_256f,
  slh_dsa_shake_256s,
} from '@noble/post-quantum/slh-dsa';

ML-KEM / Kyber shared secrets

import { ml_kem512, ml_kem768, ml_kem1024 } from '@noble/post-quantum/ml-kem';
import { randomBytes } from '@noble/post-quantum/utils';

// 1. [Alice] generates secret & public keys, then sends publicKey to Bob
const seed = randomBytes(64); // seed is optional
const aliceKeys = ml_kem768.keygen(seed);

// 2. [Bob] generates shared secret for Alice publicKey
// bobShared never leaves [Bob] system and is unknown to other parties
const { cipherText, sharedSecret: bobShared } = ml_kem768.encapsulate(aliceKeys.publicKey);

// 3. [Alice] gets and decrypts cipherText from Bob
const aliceShared = ml_kem768.decapsulate(cipherText, aliceKeys.secretKey);

// Now, both Alice and Both have same sharedSecret key
// without exchanging in plainText: aliceShared == bobShared

// Warning: Can be MITM-ed
const carolKeys = kyber1024.keygen();
const carolShared = kyber1024.decapsulate(cipherText, carolKeys.secretKey); // No error!
notDeepStrictEqual(aliceShared, carolShared); // Different key!

Lattice-based key encapsulation mechanism, defined in FIPS-203.

See website and repo. There are some concerns with regards to security: see djb blog and mailing list. Old, incompatible version (Kyber) is not provided. Open an issue if you need it.

[!WARNING] Unlike ECDH, KEM doesn't verify whether it was "Bob" who've sent the ciphertext. Instead of throwing an error when the ciphertext is encrypted by a different pubkey, decapsulate will simply return a different shared secret. ML-KEM is also probabilistic and relies on quality of CSPRNG.

ML-DSA / Dilithium signatures

import { ml_dsa44, ml_dsa65, ml_dsa87 } from '@noble/post-quantum/ml-dsa';
import { utf8ToBytes, randomBytes } from '@noble/post-quantum/utils';
const seed = randomBytes(32); // seed is optional
const keys = ml_dsa65.keygen(seed);
const msg = utf8ToBytes('hello noble');
const sig = ml_dsa65.sign(keys.secretKey, msg);
const isValid = ml_dsa65.verify(keys.publicKey, msg, sig);

Lattice-based digital signature algorithm, defined in FIPS-204. See website and repo. The internals are similar to ML-KEM, but keys and params are different.

SLH-DSA / SPHINCS+ signatures

import {
  slh_dsa_sha2_128f,
  slh_dsa_sha2_128s,
  slh_dsa_sha2_192f,
  slh_dsa_sha2_192s,
  slh_dsa_sha2_256f,
  slh_dsa_sha2_256s,
  slh_dsa_shake_128f,
  slh_dsa_shake_128s,
  slh_dsa_shake_192f,
  slh_dsa_shake_192s,
  slh_dsa_shake_256f,
  slh_dsa_shake_256s,
} from '@noble/post-quantum/slh-dsa';
import { utf8ToBytes } from '@noble/post-quantum/utils';

const keys2 = sph.keygen();
const msg2 = utf8ToBytes('hello noble');
const sig2 = sph.sign(keys2.secretKey, msg2);
const isValid2 = sph.verify(keys2.publicKey, msg2, sig2);

Hash-based digital signature algorithm, defined in FIPS-205. See website and repo. We implement spec v3.1 with FIPS adjustments.

There are many different kinds, but basically sha2 / shake indicate internal hash, 128 / 192 / 256 indicate security level, and s /f indicate trade-off (Small / Fast). SLH-DSA is slow: see benchmarks for key size & speed.

What should I use?

| | Speed | Key size | Sig size | Created in | Popularized in | Post-quantum? | | ------- | ------ | ----------- | ----------- | ---------- | -------------- | ------------- | | RSA | Normal | 256B - 2KB | 256B - 2KB | 1970s | 1990s | No | | ECC | Normal | 32 - 256B | 48 - 128B | 1980s | 2010s | No | | ML-KEM | Fast | 1.6 - 31KB | 1KB | 1990s | 2020s | Yes | | ML-DSA | Normal | 1.3 - 2.5KB | 2.5 - 4.5KB | 1990s | 2020s | Yes | | SLH-DSA | Slow | 32 - 128B | 17 - 50KB | 1970s | 2020s | Yes | | FN-DSA | Slow | 0.9 - 1.8KB | 0.6 - 1.2KB | 1990s | 2020s | Yes |

We suggest to use ECC + ML-KEM for key agreement, ECC + SLH-DSA for signatures.

ML-KEM and ML-DSA are lattice-based. SLH-DSA is hash-based, which means it is built on top of older, more conservative primitives. NIST guidance for security levels:

  • Category 3 (~AES-192): ML-KEM-768, ML-DSA-65, SLH-DSA-[SHA2/shake]-192[s/f]
  • Category 5 (~AES-256): ML-KEM-1024, ML-DSA-87, SLH-DSA-[SHA2/shake]-256[s/f]

NIST recommends to use cat-3+, while australian ASD only allows cat-5 after 2030.

For hashes, use SHA512 or SHA3-512 (not SHA256); and for ciphers ensure AES-256 or ChaCha.

Security

The library has not been independently audited yet.

If you see anything unusual: investigate and report.

Constant-timeness

There is no protection against side-channel attacks. We actively research how to provide this property for post-quantum algorithms in JS. Keep in mind that even hardware versions ML-KEM are vulnerable.

Supply chain security

  • Commits are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures
  • Releases are transparent and built on GitHub CI. Make sure to verify provenance logs
  • Rare releasing is followed to ensure less re-audit need for end-users
  • Dependencies are minimized and locked-down: any dependency could get hacked and users will be downloading malware with every install.
    • We make sure to use as few dependencies as possible
    • Automatic dep updates are prevented by locking-down version ranges; diffs are checked with npm-diff
  • Dev Dependencies are disabled for end-users; they are only used to develop / build the source code

For this package, there is 1 dependency; and a few dev dependencies:

  • noble-hashes provides cryptographic hashing functionality
  • micro-bmark, micro-should and jsbt are used for benchmarking / testing / build tooling and developed by the same author
  • prettier, fast-check and typescript are used for code quality / test generation / ts compilation. It's hard to audit their source code thoroughly and fully because of their size

Randomness

We're deferring to built-in crypto.getRandomValues which is considered cryptographically secure (CSPRNG).

In the past, browsers had bugs that made it weak: it may happen again. Implementing a userspace CSPRNG to get resilient to the weakness is even worse: there is no reliable userspace source of quality entropy.

Speed

Noble is the fastest JS implementation of post-quantum algorithms. WASM libraries can be faster.

| OPs/sec | Keygen | Signing | Verification | Shared secret | | ----------------- | ------ | ------- | ------------ | ------------- | | ECC x/ed25519 | 10270 | 5110 | 1050 | 1470 | | ML-KEM-768 | 2300 | | | 2000 | | ML-DSA65 | 386 | 120 | 367 | | | SLH-DSA-SHA2-192f | 166 | 6 | 111 | |

For SLH-DSA, SHAKE slows everything down 8x, and -s versions do another 20-50x slowdown.

Detailed benchmarks on Apple M2:

ML-KEM
keygen
├─ML-KEM-512 x 3,784 ops/sec @ 264μs/op
├─ML-KEM-768 x 2,305 ops/sec @ 433μs/op
└─ML-KEM-1024 x 1,510 ops/sec @ 662μs/op
encrypt
├─ML-KEM-512 x 3,283 ops/sec @ 304μs/op
├─ML-KEM-768 x 1,993 ops/sec @ 501μs/op
└─ML-KEM-1024 x 1,366 ops/sec @ 731μs/op
decrypt
├─ML-KEM-512 x 3,450 ops/sec @ 289μs/op
├─ML-KEM-768 x 2,035 ops/sec @ 491μs/op
└─ML-KEM-1024 x 1,343 ops/sec @ 744μs/op

ML-DSA
keygen
├─ML-DSA44 x 669 ops/sec @ 1ms/op
├─ML-DSA65 x 386 ops/sec @ 2ms/op
└─ML-DSA87 x 236 ops/sec @ 4ms/op
sign
├─ML-DSA44 x 123 ops/sec @ 8ms/op
├─ML-DSA65 x 120 ops/sec @ 8ms/op
└─ML-DSA87 x 78 ops/sec @ 12ms/op
verify
├─ML-DSA44 x 618 ops/sec @ 1ms/op
├─ML-DSA65 x 367 ops/sec @ 2ms/op
└─ML-DSA87 x 220 ops/sec @ 4ms/op

SLH-DSA (_shake is 8x slower):

| | sig size | keygen | sign | verify | | --------- | -------- | ------ | ------ | ------ | | sha2_128f | 18088 | 4ms | 90ms | 6ms | | sha2_128s | 7856 | 260ms | 2000ms | 2ms | | sha2_192f | 35664 | 6ms | 160ms | 9ms | | sha2_192s | 16224 | 380ms | 3800ms | 3ms | | sha2_256f | 49856 | 15ms | 340ms | 9ms | | sha2_256s | 29792 | 250ms | 3400ms | 4ms |

Contributing & testing

  • npm install && npm run build && npm test will build the code and run tests.
  • npm run lint / npm run format will run linter / fix linter issues.
  • npm run bench will run benchmarks, which may need their deps first (npm run bench:install)
  • npm run build:release will build single file

Check out github.com/paulmillr/guidelines for general coding practices and rules.

See paulmillr.com/noble for useful resources, articles, documentation and demos related to the library.

License

The MIT License (MIT)

Copyright (c) 2024 Paul Miller (https://paulmillr.com)

See LICENSE file.