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
- TurboSHAKE128
- TurboSHAKE256
- 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
For info on how to omit or include feature flags, see the cargo docs on features.
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
See the client-server example for an idea of how to use HPKE.
All changes in the last few versions can be found in CHANGELOG.md. We highlight recent ones below. This crate adheres to Semantic Versioning for all modules except for danger. We reserve the right to break the danger API with patch version updates. So if you are using the danger API, pin hpke to the patch version, e.g., by specifying =0.14.0.
- Completely overhauled feature flags (see feature flags section above)
- Switched all
*_in_placealgorithms to_inout, and replaced&mut [u8]withinout::InOut<'_, '_, u8> - Renamed every function that took an RNG to
*_with_rng, and removed therngparameter from the function with the original name (gated bygetrandom) - Replaced
generic-arraywithhybrid-array
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).
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.
This crate forces the user to decide at compile time which ciphersuite they wish to use. We do it this way for the sake of simplicity, and for the added static guarantees that you get when you use the type system.
If you do not know in advance which ciphersuites you will be using, e.g., for a protocol that does ciphersuite negotiation, then you should use the hpke-dispatch crate. This crates allows ciphersuite selection at runtime (this feature is sometimes known as "agility"). Purely for the sake of demonstration, we also have a sample implementation in the examples folder.
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.