crypto-pq 1.0.0: post-quantum cryptography in pure Rust
The first release of crypto-pq brings ML-KEM, FrodoKEM, ML-DSA, SLH-DSA, HSS/LMS and XMSS, with the hash functions, MACs and KDFs they build on, to one no_std Rust crate with no dependencies, built to a public specification.
crypto-pq 1.0.0 is on crates.io. It is a post-quantum
cryptography library written from scratch in Rust: the standardized key encapsulation
mechanisms and signature schemes, the stateful hash-based signatures, and the hash functions,
XOFs, MACs and KDFs they rest on, in one no_std crate with no dependencies.
[dependencies]
crypto-pq = "1"What it provides
| Family | Standard |
|---|---|
| ML-KEM-512, ML-KEM-768, ML-KEM-1024 | FIPS 203 |
| FrodoKEM-976 and FrodoKEM-1344, with eFrodoKEM, each with AES or SHAKE | ISO/IEC 18033-2:2006/Amd 2:2026 |
| ML-DSA-44, ML-DSA-65, ML-DSA-87, pure and HashML-DSA | FIPS 204 |
| SLH-DSA, all 12 parameter sets, pure and HashSLH-DSA | FIPS 205, RFC 9909 |
| HSS/LMS | RFC 8554, RFC 9858, NIST SP 800-208 |
| XMSS and XMSS^MT | RFC 8391, NIST SP 800-208 |
| SHA-2, SHA-3, SHAKE, cSHAKE, KMAC | FIPS 180-4, FIPS 202, NIST SP 800-185 |
| BLAKE2, BLAKE3, Ascon | RFC 7693, the BLAKE3 specification, NIST SP 800-232 |
| HMAC, HKDF | FIPS 198-1, RFC 5869 |
Keys import and export as raw bytes, and as DER and PEM where a standard encoding exists. Every algorithm family is a Cargo feature, so an application compiles only what it uses:
crypto-pq = { version = "1", default-features = false, features = ["ml-kem", "ml-dsa"] }
Key encapsulation takes three calls:
use crypto_pq::{KeyGenOptions, ML_KEM_768};
let pair = ML_KEM_768.generate_key_pair(&KeyGenOptions::default())?;
let encapsulation = pair.public_key.encapsulate()?;
let shared_secret = pair.private_key.decapsulate(&encapsulation.ciphertext)?;How it is built
- Pure Rust, no dependencies. Every algorithm is implemented in the crate, with no build script and no third-party code.
- Constant-time code. Code that handles secret data has no branch or memory access that depends on a secret. CI checks it under valgrind on x86-64 and ARM64, with every secret marked as undefined.
- Wiping. Private keys and every secret output are wiped when they are dropped.
- Optimized for each processor. Kernels for x86-64 (AVX2, SHA-NI, AES-NI) and ARM64 (NEON, AES, SHA-2, SHA-3) are selected at run time, with portable code on every target.
- Stateful signatures. HSS/LMS and XMSS keys keep their state in a store that the application provides. Each index is stored before its signature exists, and every signature is verified before it is released.
Built to a specification
crypto-pq implements a public specification that fixes every operation, size, byte format and error, and records the reason for each choice. The repository carries the compliance suite: NIST ACVP and CAVP vectors, C2SP Wycheproof, test vectors from the RFCs, known-answer tests, and cross-check files for every error case, option and format. CI runs it on every push on Linux, macOS and Windows, on x86-64 and ARM64, and under emulation on 32-bit x86, RISC-V and s390x. The full vector sets and long robustness runs run every week.
Releases that can be checked
Each release starts from a signed tag. The crate is built on x86-64 and ARM64 and the two builds are compared byte for byte; it carries a build provenance attestation and reaches crates.io through trusted publishing. The release page lists the crate and its SHA-256.
The crate’s version follows the specification: every 1.0.x release implements specification 1.0, and no 1.x release removes or changes a specified behaviour.
- Documentation: docs.rs/crypto-pq
- Source and specification: github.com/crypterial/crypto-pq
- Project page: crypto-pq