Below On Jul 14, 2023, at 2:27 PM, Orie Steele <[email protected]<mailto:[email protected]>> wrote:
Inline: On Fri, Jul 14, 2023 at 3:42 PM lgl island-resort.com<http://island-resort.com/> <[email protected]<mailto:[email protected]>> wrote: On Jul 14, 2023, at 1:14 PM, Orie Steele <[email protected]<mailto:[email protected]>> wrote: You are correct: On Fri, Jul 14, 2023 at 2:48 PM lgl island-resort.com<http://island-resort.com/> <[email protected]<mailto:[email protected]>> wrote: On Jul 14, 2023, at 12:12 PM, Orie Steele <[email protected]<mailto:[email protected]>> wrote: Inline: On Fri, Jul 14, 2023 at 1:09 PM lgl island-resort.com<http://island-resort.com/> <[email protected]<mailto:[email protected]>> wrote: Looks to me that HPKE internally defines what “enc” should be. The formatting of “enc” is an internal HPKE issue. It happens to be a serialized public key produced by the HPKE SerializePublicKey() function, but no one but the HPKE libraries need to know that. Why would any thing other than an HPKE library ever look inside “enc”? Exactly, and since it's "opaque"... such a library can output whatever it likes... possibly randomly alternating between valid opaque representations.... No, it absolutely can not output whatever it likes. It can only output what RFC 9180 says and I don’t see any ambiguity in 9180 on what these bytes are. Maybe the confusion is because RFC 9180 is written in the form of a Python API? It is unconventional, but I don’t see any problems with it being ambiguous or non-interoperable so far. https://datatracker.ietf.org/doc/html/rfc9180#name-dh-based-kem-dhkem In the case of DH Kem, HPKE defined a new way to serialize a public key... which can be translated or not... depending on downstream implementer preference.... It also defined only DH Kems... https://datatracker.ietf.org/doc/html/rfc9180#kem-ids So how do we know what a non dh kem will output? HPKE libraries will know because the HPKE spec for the new KEM will say. COSE libraries don’t need to know. How do we know Kyber1024+Secp256k1 does not output a COSE KEY? I read https://datatracker.ietf.org/doc/html/draft-westerbaan-cfrg-hpke-xyber768d00-02#section-3.4 To learn that `enc` will be the concat of a DHKem and Kyber.... (and maybe this changes). I could write a draft that says "Kyber1024+Secp256k1" is like that but outputs a COSE Key instead... All I need to do is define the KEM functions... as functions of a known key serialization... What exactly is pkR? Can pkR be a JWK or a COSE Key? While pKR (and sKR) are in/out args for Seal() and Open() they are not transmitted in a COSE_Encrypt. So it doesn’t matter for COSE-HPKE what they are. I agree regarding COSE_Encrypt, but disagree regarding COSE Key and support for HPKE in COSE more generally. Yes of course COSE_Key is different. I suppose this is a down side of specifying a protocol with an API. API arguments that are transmitted protocol messages sit right next to arguments that are not with no distinction in the specification. Yes, but can be fixed in downstream specs... If people want to fix it. Note that pKR in 9180 is passed completely through and down into DH(). So the format of pKR passed into Seal() only has to be the same as the format consumed by DH(). DH() is just whatever DH API you have. These are all APIs here, not transmitted messages, so pKR could be a key handle or a pointer. Yes, and in the context of vanilla HPKE that seems excellent. When building a higher order API like for COSE-HPKE or JOSE-HPKE, you might prefer to.... exploit that these can be whatever... in order to build a safer API, possibly with some better upfront validation. I think there should be an intro paragraph in 9180 like this: This uses Python pseudo code to define the protocol where other documents might use ABNF, ASN.1 or CDDL. This has the advantage that the specification is tested as a real implementation. It has the disadvantage that it strongly suggests an API and a particular implementation. It is also does not clearly call out which arguments and return values are standardized protocol messages (e.g., enc, ct) and which are implementation-specific representations (e.g., pkR, skR). Implementors should feel free to design and implement their API differently (as long as the end behavior is interoperable). I mentioned pKR passing through just to make the point that nothing in 9180 specified the format of pKR. I have a suspicion that some significant chunk of the conflict around COSE-HPKE as some roots in HPKE being specified as an API. Note that IETF doesn’t usually standardize API. Often they are too platform, OS or language specific. Seems fine to do lots of the things you suggest below in your implementation. LL Consider the following DH Kem scenario: Sender discovers recipient public key in JWK or COSE Key. Sender passes the public key to an HPKE library, along with the plaintext. The library parses the key and checks the following: 1. the key supports hpke (specifically some registered kem id) 2. the key parameters are well formed (x, y length are correct for the kem id type) The library then calls Encap... maybe it passes the key in its current serialization... maybe it passes it in the HPKE serialization to a helper library, like for example: https://github.com/dajiaji/hpke-js#base-mode ^ in this library, you need to get an instance of "crypto key"... but... you might get that from an instance of "cose key" or "jwk"... A higher order API will throw if you try to get a crypto key for something that is not well formed, because operating on malformed keys is not a great thing to do... At the end of Encap, the lower level hpke api will return opaque bytes, according to the kem id spec. A higher order library might validate them... in case of a supply chain compromise, or for defense in depth, or just for sanity. That validation might look like: 1. confirming the enc is correct with respect to the kem id. 2. in the case enc is a serialized ecdsa public key, this means checking lengths on x or y.... The higher order library might choose to serialize enc after validating it. (of course it does not need to, it can just forward the opaque bytes, without even validating them... unless the higher order spec says otherwise...). The result is then serialized into the correct envelope format, modulo the layer and mode considerations for HPKE. HPKE requires you to validate kem inputs and outputs... https://datatracker.ietf.org/doc/html/rfc9180#section-4.1 But those are validations that apply to... the kem inputs and outputs.... not higher order key representations... If your higher order API has JWK and JWE or COSE KEY and COSE_Encrypt.... You might also want to validate those structures... possibly throwing errors before things even get to the HPKE validate functions. I don't read HPKE as "preventing" this... but some folks might not think doing that is "worth it", and HPKE is indeed constructed to not require this... just like how many folks prefer fire arms with no safety... and others prefer ones with biometric locks... The API I am looking for as a developer looks like this: encrypt = (publicKey: application/cose-key, message: ... some plaintext binary) => application/cose (COSE_Encrypt) decrypt = (privateKey: application/cose-key, message: application/cose) => ... some plaintext binary encrypt = (publicKey: application/jwk+json message: ... some binary) => application/jose (JWE-Like thing....) decrypt = (privateKey: application/jwk+json, message: application/jose) => ... some binary Internally, these APIs will call seal, and unseal, they will validate kem inputs and outputs, etc... they have to implement support for what the RFCs say for each kem. Externally, these APIs expose JOSE and COSE interfaces that are familiar and rely on registered media types, tags, and registered claim names. As an aside, of course hardware and software isolation will demand not passing serialized keys around... so of course you will have cases where a pointer gets snaked all the way through HPKE, as is the case for WebCrypto, and I assume https://github.com/dajiaji/hpke-js#base-mode In those cases you get a pointer to a private key that supports the operations, but you never pass a serialized private key to a decrypt api... You obviously can't validate a pointer to a private key.... so some of the validation assumed by HPKE is already not going to happen for isolated APIs, hardware, or remote kms... See https://datatracker.ietf.org/doc/html/rfc9180#section-8.2 Specifically this part: > As another example, some implementations of the DHKEM specified in this > document may choose to transform ValidationError from DH() into an EncapError > or DecapError from Encap() or Decap(), respectively, whereas others may > choose to raise ValidationError unmodified. Seems like throwing an Encap or Decap error when your higher order key serialization does not support HPKE could be a good idea... or I could be reading this sentence wrong. OS LL -- ORIE STEELE Chief Technology Officer www.transmute.industries<http://www.transmute.industries/> [https://ci3.googleusercontent.com/mail-sig/AIorK4xqtkj5psM1dDeDes_mjSsF3ylbEa5EMEQmnz3602cucAIhjLaHod-eVJq0E28BwrivrNSBMBc]<https://transmute.industries/>
_______________________________________________ COSE mailing list [email protected] https://www.ietf.org/mailman/listinfo/cose
