Code change:
The key exporter context contains the following fields: The Signature Algorithm and Port fields are encoded as unsigned <del> 16-bit integers in network byte order.  The Key ID, Scheme, Host, and Real fields are length prefixed strings; they are preceded by a Length field that represents their length in bytes.  These length fields are encoded using the variable-length integer encoding from QUIC and MUST be encoded in the minimum number of bytes necessary. </del> <ins> 16-bit integers in network byte order.  The Key ID, Public Key, Scheme, Host, and Real fields are length prefixed strings; they are preceded by a Length field that represents their length in bytes. These length fields are encoded using the variable-length integer encoding from QUIC and MUST be encoded in the minimum number of bytes necessary. The encoding of the public key is determined by the Signature Algorithm in use as follows: This document does not define the public key encodings for other algorithms.  In order for a SignatureScheme to be usable with the Signature HTTP authentication scheme, its public key encoding needs to be defined in a corresponding document. </ins> 4.2.

Related discussion:
text: Based on discussions with NAME NAME and others, there are potential key confusion attacks when the server is checking the signature using the wrong public key. I think the simplest solution is to add the public key to the TLS key exporter. That should solve the issue without increasing the amount of bytes sent on the wire
Including the public key in the exporter context makes it significantly harder to implement the server side of this. Including the hash of the public key in the signature appears to work also. I have a sketch model in Tamarin that doesn't find any attacks when the hash of the public key is in the signature, which gives me some confidence that it's doable, although NAME wasn't convinced. We should discuss this in the room at 117.
I agree with NAME The implementation complexity that comes from putting the public key in the exporter context is real, at least for some edge networks. I think we should pursue alternatives that don't weaken the security properties, even if they make the registration step a bit more explicit.
If this design makes implementation hard then we should totally change it. Can I ask you to elaborate on what causes this to be hard on the server side?
The basic problem in our particular case is that the component that terminates TLS and computes exported values is upstream of the component that has the public key. So when a request comes in with the header to the TLS terminator, the public key needs to get relayed back for computation. If, instead, the public key was signed, then the TLS terminator could simply forward the computed exporter without any sort of round trip. (I punched this in on my phone, but can draw pictures on a laptop if the above is not clear.) We don't necessarily need to cater to one implementation, but I would be surprised if this were not a common arrangement in practice.
Thanks, that makes sense. To explore the problem space: if we were to include the public key in both the context and a header parameter, would that work for your implementation? (That way the TLS terminator can call the exporter without a round trip.)
Yep, that would address the problem too.
SIGMA seems like it might be worth considering as an alternative. That is, sign the nonce, but then include a MAC that covers all of the relevant parameters.
Something like SIGMA should also work, but I'd like to minimize the number of primitives required to implement this.