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

Reply via email to