On Thu, Sep 01, 2022 at 11:07:10AM -0500, Orie Steele wrote: > > However, the sender's ephemeral key depends on the recipient's public key > information, and there is no need to specify the many parameters such as > kty, crv, alg, etc. which is already determined by the recipient's public > key > > I have some experience with this part in JOSE, in the cases where the > sender and receiver must agree to a key type and algorithm, I prefer that > these be explicit, and I don't like inferring one party's key structures > from another party and assumptions about the cryptography...
What I do not like is checking if two separate pieces of information that must be the same are in fact equal. It is all too easy to forget to check. Better rig the crypto to guarantee error on mismatch. This prevents cutting corners. Reminds me that X.509 certificates encode the signature algorithm twice, and I saw some WebPKI CA(!) certificates that have the two places claim different signature algorithms. > I've seen problems where one party represents keys differently... for > example, EC with and without point compression... or 1 party has keys that > need to be converted to a standard format before a software library can be > used. As note, the EC2 stuff in COSE-HPKE needs exactly such conversion if you want to dump it on standard HPKE library. > I prefer to dump the key representations straight into off the shelf > software, which expects standard key formats, and will often complain if > parameters are missing (such as kty, crv, alg). My implementation actually dumps generic key representations directly to the HPKE library with no checking. The HPKE library will then barf if the representations are not valid. > For example: > > https://github.com/panva/jose/blob/main/docs/classes/jwe_compact_encrypt.CompactEncrypt.md#readme > > Takes a public key, which you get from: > > https://github.com/panva/jose/blob/main/docs/functions/key_import.importJWK.md#readme > > This example is not exactly the same for HPKE, but I think developers will > be assuming that these APIs will be similar. The APIs are not similar. Here is what the API looks like in my library: impl PrivateKey { pub fn load(kem: KEM, sk: &[u8], pk: Option<&[u8]>) -> Result<PrivateKey, HpkeError>; pub fn decapsulate(&self, kdfid: KDF, aeadid: AEAD, ek: &[u8], info: &[u8], auth: Option<&PublicKey>, psk: Option<(&[u8], &[u8])>) -> Result<DecryptContext, HpkeError>; } impl DecryptContext { pub fn decrypt(&mut self, ad: &[u8], msg: &[u8]) -> Result<Vec<u8>, HpkeError>; pub fn decrypt_to<'a>(&mut self, ad: &[u8], msg: &[u8], to: &'a mut [MaybeUninit<u8>]) -> Result<&'a [u8], HpkeError>; } Note that just about everything is octet string (&[u8] or Vec<u8>), since HPKE is defined that way. The encryption side is similar, with public and private keys exchanged, and decrypt replaced by encrypt. (The two decrypt functions differ in just who is responsible for allocating memory. The singleshot mode can be easily obtained by chaining decapsulate and decrypt using .and_then(), since the error types match.) -Ilari _______________________________________________ COSE mailing list [email protected] https://www.ietf.org/mailman/listinfo/cose
