Designing an ML-KEM API that doesn't upset people
Working on a pure-Rust ML-KEM implementation for Orion forced me to confront the peculiarities of what the FIPS-203 standard allows in terms of storing private decapsulation keys. According to the standard, you may store: The seed d||z, which is used to derive both the private decapsulation key and its public counterpart. The serialized form of the private decapsulation key, which includes the public key, a hash thereof, and the FO-transform secret z. As pointed out by Sophie Schmieg in the excellent paper “Unbindable Kemmy Schmidt: ML-KEM is neither MAL-BIND-K-CT nor MAL-BIND-K-PK” and in her blog post “Unbindable Kemmy Schmidt”, option 2 has several disadvantages when it comes to binding the shared secret k to the ciphertext (MAL-BIND-K-CT) and to the encapsulation key (MAL-BIND-K-PK). While both of these models require an attacker to have access to the private decapsulation key—at which point it’s arguably “game over” anyway—it still seems worthwhile to design an ML-KEM API that minimizes hidden assumptions and potential pitfalls. ...