Home

Awesome

noble-post-quantum

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

Take a glance at GitHub Discussions for questions and support.

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

We support all major platforms and runtimes. For Deno, ensure to use npm specifier. 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';
// import { ml_kem768 } from 'npm:@noble/post-quantum@0.1.0/ml-kem'; // Deno

ML-KEM / Kyber shared secrets

import { ml_kem512, ml_kem768, ml_kem1024 } from '@noble/post-quantum/ml-kem';
// [Alice] generates secret & public keys, then sends publicKey to Bob
const aliceKeys = ml_kem768.keygen();
const alicePub = aliceKeys.publicKey;

// [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(alicePub);

// 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';
const seed = new TextEncoder().encode('not a safe seed');
const aliceKeys = ml_dsa65.keygen(seed);
const msg = new Uint8Array(1);
const sig = ml_dsa65.sign(aliceKeys.secretKey, msg);
const isValid = ml_dsa65.verify(aliceKeys.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';

const aliceKeys = sph.keygen();
const msg = new Uint8Array(1);
const sig = sph.sign(aliceKeys.secretKey, msg);
const isValid = sph.verify(aliceKeys.publicKey, msg, sig);

Hash-based digital signature algorithm, defined in FIPS-205. See website and repo. We implement spec v3.1 with FIPS adjustments. Some wasm libraries use older specs.

[!NOTE]
SLH-DSA is slow: see benchmarks below

What should I use?

SpeedKey sizeSig sizeCreated inPopularized inPost-quantum?
RSANormal256B - 2KB256B - 2KB1970s1990sNo
ECCNormal32 - 256B48 - 128B1980s2010sNo
ML-KEMFast1.6 - 31KB1KB1990s2020sYes
ML-DSANormal1.3 - 2.5KB2.5 - 4.5KB1990s2020sYes
SLH-DSASlow32 - 128B17 - 50KB1970s2020sYes

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

ML-KEM and ML-DSA are lattice-based, so they're less "proven". There's some chance of advancement, which will break this algorithm class. SLH-DSA, while being slow, is built on top of older, conservative primitives.

Symmetrical algorithms like AES and ChaCha (available in noble-ciphers) suffer less from quantum computers. For AES, simply update from AES-128 to AES-256.

Security

The library has not been independently audited yet.

There is no protection against side-channel attacks. Keep in mind that even hardware versions ML-KEM are vulnerable.

If you see anything unusual: investigate and report.

Speed

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

OPs/secKeygenSigningVerificationShared secret
ECC ed2551910270511010501470
ML-KEM-76823002000
ML-DSA44670120620
SLH-DSA-SHA2-128f25010167

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
keygen
├─slh_dsa_sha2_128f x 245 ops/sec @ 4ms/op
├─slh_dsa_sha2_192f x 166 ops/sec @ 6ms/op
├─slh_dsa_sha2_256f x 64 ops/sec @ 15ms/op
├─slh_dsa_shake_128f x 35 ops/sec @ 28ms/op
├─slh_dsa_shake_192f x 23 ops/sec @ 41ms/op
├─slh_dsa_shake_256f x 9 ops/sec @ 110ms/op
├─slh_dsa_sha2_128s x 3 ops/sec @ 257ms/op
├─slh_dsa_sha2_192s x 2 ops/sec @ 381ms/op
└─slh_dsa_sha2_256s x 3 ops/sec @ 250ms/op
sign
├─slh_dsa_sha2_128f x 10 ops/sec @ 94ms/op
├─slh_dsa_sha2_192f x 6 ops/sec @ 163ms/op
├─slh_dsa_sha2_256f x 2 ops/sec @ 338ms/op
├─slh_dsa_shake_128f x 1 ops/sec @ 671ms/op
├─slh_dsa_shake_192f x 0 ops/sec @ 1088ms/op
├─slh_dsa_shake_256f x 0 ops/sec @ 2219ms/op
├─slh_dsa_sha2_128s x 0 ops/sec @ 1954ms/op
├─slh_dsa_sha2_192s x 0 ops/sec @ 3789ms/op
└─slh_dsa_sha2_256s x 0 ops/sec @ 3404ms/op
verify
├─slh_dsa_sha2_128f x 162 ops/sec @ 6ms/op
├─slh_dsa_sha2_192f x 111 ops/sec @ 9ms/op
├─slh_dsa_sha2_256f x 105 ops/sec @ 9ms/op
├─slh_dsa_shake_128f x 24 ops/sec @ 40ms/op
├─slh_dsa_shake_192f x 17 ops/sec @ 58ms/op
├─slh_dsa_shake_256f x 16 ops/sec @ 59ms/op
├─slh_dsa_sha2_128s x 495 ops/sec @ 2ms/op
├─slh_dsa_sha2_192s x 293 ops/sec @ 3ms/op
└─slh_dsa_sha2_256s x 220 ops/sec @ 4ms/op

Contributing & testing

  1. Clone the repository
  2. npm install to install build dependencies like TypeScript
  3. npm run build to compile TypeScript code
  4. npm run test will execute all main tests

Resources

Check out 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.