This is an implementation of the HPKE hybrid encryption standard (RFC 9180).
This implementation complies with the HPKE standard (RFC 9180). It also implements the pure post-quantum KEMs defined in draft-ietf-hpke-pq-04, and the hybrid post-quantum KEMs defined in draft-connolly-cfrg-xwing-kem-10, draft-irtf-cfrg-concrete-hybrid-kems-03, and draft-irtf-cfrg-hybrid-kems-11 (this is all quite confusing, see Filippo's summary of it).
Here are all the primitives listed in the spec. The primitives with checked boxes are the ones that are implemented.
- Classical KEMs
- DHKEM(Curve25519, HKDF-SHA256)
- DHKEM(Curve448, HKDF-SHA512)
- DHKEM(P-256, HKDF-SHA256)
- DHKEM(P-384, HKDF-SHA384)
- DHKEM(P-521, HKDF-SHA512)
- Post-quantum and hybrid KEMs
- ML-KEM-768
- ML-KEM-1024
- MLKEM768-X25519, aka X-Wing
- MLKEM768-P256
- MLKEM1024-P384
- KDFs
- HKDF-SHA256
- HKDF-SHA384
- HKDF-SHA512
- SHAKE128
- SHAKE256
- AEADs
- AES-GCM-128
- AES-GCM-256
- ChaCha20Poly1305
The feature flags in this crate allow end-users to avoid pulling in dependencies they don't want. We thus take an additive approach to features: if you want hybrid post-quantum KEMs, you need to pull in the individual features it relies on. All is explained below.
Default features flags: getrandom, alloc, chacha, x25519, mlkem. Note this combination means that XWing is enabled by default, as well as all (Turbo)SHAKE KDFs.
alloc- Exposes allocating methods likeAeadCtxR::open()andAeadCtxS::seal()getrandom(default) - Enables top-level functions that usegetrandomfor random number generation, rather than taking in an explicit RNG- AEADs:
chacha— Enables ChaCha20-Poly1305aes— Enables AES-GCM-128/256
- KEMs:
x25519— Enables the X25519 DHKEM (also enableshkdfsha2)nistp— Enables the ECDH-NIST P-256, P-384, and P-521 DHKEMs (also enableshkdfsha2)mlkem— Enables the ML-KEM-768 and ML-KEM-1024 post-quantum KEMs (also enablesshake)
- KDFs:
hkdfsha2— Enables HKDF-SHA256/384/512shake— Enables SHAKE128/256 and TurboSHAKE128/256
kat- Used only to enabled known-answer tests, which requirestd. Only use withcargo test
We list the additional functionality that certain feature combinations enable:
x25519,mlkem(default) — Enables the ML-KEM-768+X25519 (aka XWing) hybrid post-quantum KEMnistp,mlkem— Enables the ML-KEM + NIST-P hybrid post-quantum KEMs
For info on how to omit or include feature flags, see the cargo docs on features.
See the client-server example for an idea of how to use HPKE.
- Renamed every function that took an RNG to
*_with_rng, and removed therngparameter from the function with the original name (gated bygetrandom) - Feature-gated AES-GCM and ChaCha20Poly1305 behind
aesandchachafeatures, respectively
- Updated
randandrand_coredependencies - Replaced
generic-arraywithhybrid-array - Renamed all
_in_placesymmetric encryption/decryption algorithms to_inout. Also replaced&mut [u8]inputs in these functions withinout::InOut<'_, '_, u8>. - Bumped MSRV to 1.85.0 (2025-02-20)
PskBundlenow has a constructor that validates that the inputs are either both empty or nonempty.rand_corewas updated to v0.9
The serde_impls feature was removed. If you were using this and require backwards compatible serialization/deserialization, see the wiki page here.
The current minimum supported Rust version (MSRV) is 1.85.0 (2025-02-20).
See CHANGELOG.md for a list of changes made throughout past versions.
To run all tests, execute cargo test --all-features. This includes known-answer tests.
Classical (i.e., non-post-quantum) ciphersuites test against test-vectors/origrfc-COMMIT_ID.json,where COMMIT_ID is the short commit of the version of the spec that the test vectors came from. The finalized spec uses commit 5f503c5. See the reference implementation for information on how to generate a test vector.
Post-quantum ciphersuites (including hybrid), test against test-vectors/pq-COMMIT_ID.json in the same way. The commit ID refers to the reference implementation repo of the PQ extension standard.
Hybrid ciphersuites are additionally tested against test-vectors/hybrid-COMMIT_ID.json. The commit ID refers to the concrete hybrid HPKE spec repo.
To run all benchmarks, execute cargo bench --all-features. If you set your own feature flags, the benchmarks will still work, and run the subset of benches that it is able to. The results of a benchmark can be read as a neat webpage at target/criterion/report/index.html.
Ciphersuites benchmarked:
- Classical NIST Ciphersuite with 128-bit security: AES-GCM-128, HKDF-SHA256, ECDH-P256
- Classical Non-NIST Ciphersuite with 128-bit security: ChaCha20-Poly1305, HKDF-SHA256, X25519
- Pure-PQ NIST Ciphersuite with 128-bit security: AES-GCM-128, SHAKE128, MLKEM768
- Pure-PQ NIST Ciphersuite with 256-bit security: AES-GCM-256, SHAKE256, MLKEM1024
- Hybrid-PQ NIST Ciphersuite with 128-bit security: AES-GCM-128, SHAKE128, MLKEM768-P256
- Hybrid-PQ NIST Ciphersuite with 256-bit security: AES-GCM-256, SHAKE256, MLKEM1024-P384
- Hybrid-PQ Non-NIST Ciphersuite with 128-bit security: ChaCha20-Poly1305, TurboSHAKE128, XWing
Functions benchmarked in each ciphersuite:
Kem::gen_keypairsetup_senderwith OpModes of Base, Auth, Psk, and AuthPsk (Auth* modes omitted if unsupported)setup_receiverwith OpModes of Base, Auth, Psk, and AuthPsk (Auth* modes omitted if unsupported)AeadCtxS::sealwith plaintext length 64 and AAD length 64AeadCtxR::openwith ciphertext length 64 and AAD length 64
To the authors' knowledge, nobody has performed a paid audit of this crate. However, Cloudflare did a security review of version 0.8, saying:
The HPKE implementation we decided on comes with the caveat of not yet being formally audited, so we performed our own internal security review. We analyzed the cryptography primitives being used and the corresponding libraries. Between the composition of said primitives and secure programming practices like correctly zeroing memory and safe usage of random number generators, we found no security issues.
A definition: crypto agility refers to the ability of a cryptosystem or protocol to vary its underlying primitives. For example, TLS has "crypto agility" in that you can run the protocol with many different ciphersuites.
This crate does not support crypto agility out of the box. This is because the cryptographic primitives are encoded as types satisfying certain constraints, and types need to be determined at compile time (broadly speaking). Purely for the sake of demonstration, there is a sample implementation in the examples folder. The sample implementation is messy because agility is messy.
If you want agility, you can use the hpke-dispatch crate.
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.