RustCrypto / KEMs

Collection of Key Encapsulation Mechanisms written in pure Rust
11 stars 8 forks source link

Missing KEMs #1

Open tarcieri opened 10 months ago

tarcieri commented 10 months ago

This is a tracking issue for KEMs we could potentially add to this repo:

Lacking a better place to put this, I'll stick it here, although if someone wants to implement it in earnest it could probably use its own repo since it isn't a proper "KEM":

tarcieri commented 10 months ago

There's already a pure Rust implementation of Kyber here: https://github.com/Argyle-Software/kyber

Unfortunately it doesn't yet implement the kem crate's API. I left a comment about that here: https://github.com/Argyle-Software/kyber/issues/30#issuecomment-1656085129

That said, since there is an existing pure Rust implementation of Kyber I think it might be more interesting to start with X25519Kyber768.

tarcieri commented 10 months ago

Hmm, I guess there's already an implementation of X25519Kyber768 in rust-hpke: https://github.com/bwesterb/rust-hpke/blob/1805102ab387fcbd15ec637fd741e1c4743d159c/src/kem/xyber768d00.rs#L127

@rozbb we're trying to decide what to do with this repo and I guess a big question is whether or not it makes sense to extract KEMs from something like rust-hpke into their own per-algorithm crates so they can be used in applications outside HPKE (though what those applications would be, I'm not sure)

BlackHoleFox commented 10 months ago

... though what those applications would be, I'm not sure

Perhaps something like post-quantum Noise (RWC 2023) or SSH would be good candidates. Snow even has some basic support for Kyber in it due to an older proposed Noise extension.

In general it seems like it'd be good for protocols that have their own public key exchanges/formats defined and won't be adopting HPKE.

tarcieri commented 10 months ago

Yeah, transport encryption seems like a good use case

bwesterb commented 9 months ago

Hmm, I guess there's already an implementation of X25519Kyber768 in rust-hpke: https://github.com/bwesterb/rust-hpke/blob/1805102ab387fcbd15ec637fd741e1c4743d159c/src/kem/xyber768d00.rs#L127

It's merged in an upstream branch: https://github.com/rozbb/rust-hpke/tree/unstable-pq-xyber

Note that there are unfortunately two variants of X25519Kyber768: the one used in TLS and the one used in HPKE.

The TLS variant was first and doesn't hash the X25519 ciphertext into the shared secret — the HPKE variant does. HPKE needs this to remain IND-CCA2 if either X25519 or Kyber is broken. For TLS this is not required, as it has a transcript.

Kyber hashes the ciphertext into the shared secret itself, so there is no need to do that in the hybrid. ML-KEM, the final version of Kyber, is expected not to hash the ciphertext into the shared secret. So for HPKE the hybrid with X25519 needs to hash both the X25519 ciphertext and the Kyber ciphertext.

I prefer to converge on the same hybrid for TLS and HPKE for ML-KEM, but those ciphertext hashes aren't completely negligible with respect to performance, so there is a decent chance the TLS working group will want to keep using its own hybrid.

tarcieri commented 9 months ago

My understanding is the output of the HPKE KEM is the concatenation of the Kyber and X25519 secrets, with the hashing performed by HPKE?

bwesterb commented 9 months ago

HPKE doesn't use X25519 directly, but DHKEM(X25519), which adds some hashing. So the X25519Kyber variant for HPKE also uses DHKEM(X25519) instead of X25519 itself.

oddcoder commented 1 week ago

would there be interest in adding KEMs other than the one standardized by NIST, in particular NTRU-prime and McEliece.

I also want to ask about the scope of RustCrypto, is it just to offer interfaces or also implementation? For some algorithms (like sha AEAD) I see rustcrypto offering full implementation but for other algorithms (x448 for instance) RustCrypor offers just interfaces. If it is the later, I can try offering some implementation in my free time if you accept PRs but please note I am not expert crypto implementer.

tarcieri commented 1 week ago

@oddcoder I've added NTRU Prime and Classic McEliece to the list.

We mostly provide algorithm implementations using a common interface (the kem crate in this repo's case).

However, in some cases, primarily https://github.com/rustcrypto/signatures, we have provided some common types that various implementations of the same algorithm can share. The main purpose of this is typically so things like hardware-backed implementations of signature algorithms can "plug in" in place of software implementations via traits.

oddcoder commented 1 week ago

Alright then noted, I assume that mean I can try to start implementing NTRU-Prime. Unfortunately I cannot offer proper time line because I do this in my free time. If there is common coding guidelines particular to RustCrypto or anything I should be aware of, please let me know.

rozbb commented 1 week ago

Some broad guidelines now that I've written a KEM impl.

I hope that's helpful and not just idle ranting

tarcieri commented 1 week ago

Use subtle for constant-time operations. For the PQC KEMs, the only part that needs it is the Fujisaki-Okamoto transform

Note: it's also useful for the recently discussed Kyber timing variability in poly_frommsg, where bitwise masking is being used to perform a conditional select. Instead you can use subtle to perform the conditional select using the ConditionallySelectable trait, which acts as an optimization barrier.