<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.39 (Ruby 3.4.9) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-schinazi-httpbis-ohttp-pfs-01" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.34.0 -->
  <front>
    <title abbrev="Perfect Forward Secure OHTTP">A Perfect Forward Secure Extension to Oblivious HTTP</title>
    <seriesInfo name="Internet-Draft" value="draft-schinazi-httpbis-ohttp-pfs-01"/>
    <author initials="D." surname="Schinazi" fullname="David Schinazi">
      <organization>Google LLC</organization>
      <address>
        <email>dschinazi.ietf@gmail.com</email>
      </address>
    </author>
    <date year="2026" month="July" day="22"/>
    <area>Web and Internet Transport</area>
    <workgroup>HTTP</workgroup>
    <keyword>oblivious</keyword>
    <keyword>HTTP</keyword>
    <keyword>configuration</keyword>
    <keyword>extension</keyword>
    <abstract>
      <?line 40?>

<t>Oblivious HTTP (OHTTP) is a protocol for forwarding encrypted HTTP messages.
It does not provide Perfect Forward Secrecy (PFS). Chunked OHTTP expands
OHTTP to be suitable for longer-lived streams, but still does not offer PFS.
Combined, this is leading sensitive traffic to de deployed at scale without
PFS. This document proposes a solution.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://DavidSchinazi.github.io/draft-schinazi-httpbis-ohttp-pfs/draft-schinazi-httpbis-ohttp-pfs.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-schinazi-httpbis-ohttp-pfs/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        HTTP Working Group mailing list (<eref target="mailto:ietf-http-wg@w3.org"/>),
        which is archived at <eref target="https://lists.w3.org/Archives/Public/ietf-http-wg/"/>.
        Working Group information can be found at <eref target="https://httpwg.org/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/DavidSchinazi/draft-schinazi-httpbis-ohttp-pfs"/>.</t>
    </note>
  </front>
  <middle>
    <?line 48?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>Oblivious HTTP (<xref target="OHTTP"/>) is a protocol for forwarding encrypted
HTTP messages. It does not provide Perfect Forward Secrecy (PFS). Chunked
OHTTP (<xref target="CHUNKED"/>) expands OHTTP to be
suitable for longer-lived streams, but still does not offer PFS.</t>
      <t>Unfortunately, providing a streaming abstraction over OHTTP makes it an
attractive tool to provide privacy. This is leading application designers
to build Remote Procedure Call (RPC) systems over this bidirectional
stream, without realizing the security cost of losing PFS.</t>
      <t>When PFS is needed, a simpler solution is to avoid OHTTP entirely and
instead use TLS (<xref target="TLS"/>) over HTTP CONNECT
(see <xref section="9.3.6" sectionFormat="of" target="HTTP"/>). However, completing the TLS
handshake takes a full round trip. For latency-sensitive applications,
TLS 0-RTT (see <xref section="2.3" sectionFormat="of" target="TLS"/>) can be used; that has the
advantage of allowing non-PFS data for the client's first flight and then
PFS for all other data. TLS 0-RTT does however have one relevant
limitation: it allows a TLS server to link distinct 0-RTT requests by
encoding identifying information in TLS session tickets. That makes
TLS 0-RTT unsuitable for use cases that require unlinkability between
requests, which Chunked OHTTP provides.</t>
      <t>This document proposes a solution that offers PFS to all data sent over
OHTTP apart from the client's first flight. This provides privacy and
security properties similar to TLS 0-RTT over HTTP CONNECT without losing
the performance nor request-correlation-prevention properties of OHTTP.
This mechanism is designed to be backwards compatible with unextended
OHTTP.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<t>This document uses <tt>SerializePublicKey()</tt>, <tt>DeserializePublicKey()</tt>,
<tt>GenerateKeyPair()</tt>, <tt>SetupBaseS()</tt>, <tt>SetupBaseR()</tt>, <tt>Export()</tt>, <tt>Seal()</tt>,
and <tt>Open()</tt> from <xref target="HPKE"/>.</t>
    </section>
    <section anchor="mechanism">
      <name>Mechanism</name>
      <t>This mechanism relies on the generation of two more ephemeral key pairs per
OHTTP request: one for the client (denoted <tt>skC, pkC</tt>) and one for the
gateway (not denoted since it only exists inside of <tt>SetupBaseS()</tt>).</t>
      <t>The client starts by generating a second ephemeral key pair, using the same KEM
it has selected for this request:</t>
      <artwork><![CDATA[
skC, pkC = GenerateKeyPair()
]]></artwork>
      <t>The client then adds the serialized public key
<tt>SerializePublicKey(pkC)</tt> to its Binary HTTP (<xref target="BHTTP"/>)
request headers using the "OHTTP-PFS" header. That header is a
Structured Header Field Item of type Byte Sequence as defined in
<xref section="3.3.5" sectionFormat="of" target="STRUCTURED"/>. For example:</t>
      <artwork><![CDATA[
ohttp-pfs: :dGhpcyBpcyBhIHB1YmxpYyBrZXk=:
]]></artwork>
      <t>The client then encrypts the Binary HTTP request following the procedure in
<xref section="4.3" sectionFormat="of" target="OHTTP"/>. The gateway follows the procedure in that same
section to recover the Binary HTTP request.</t>
      <t>The gateway then checks the request for the presence of the "ohttp-pfs"
header to determine whether this extension is in use. If it is, it uses
<tt>DeserializePublicKey()</tt> to parse the key then uses the HPKE receiver
context (<tt>rctxt</tt>) from the OHTTP request as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Export a secret, <tt>req_secret</tt>, from <tt>rctxt</tt>, using the string
"OHTTP PFS Request Derivation" as the <tt>exporter_context</tt> parameter to
<tt>context.Export</tt>; see <xref section="5.3" sectionFormat="of" target="HPKE"/>.  The length of this
secret is <tt>Nsecret</tt>, the length of the shared secret for the KEM
associated with <tt>context</tt>.</t>
        </li>
        <li>
          <t>Build <tt>info2</tt> by concatenating the ASCII-encoded string
"OHTTP PFS Response", a zero byte, the values of <tt>key_id</tt>, <tt>kem_id</tt>,
<tt>kdf_id</tt>, and <tt>aead_id</tt>, as one 8-bit integer and three 16-bit
integers, respectively, each in network byte order, and <tt>req_secret</tt>.</t>
        </li>
        <li>
          <t>Create a sending HPKE context by invoking <tt>SetupBaseS()</tt>
(<xref section="5.1.1" sectionFormat="of" target="HPKE"/>) with the public key of the client <tt>pkE</tt>
and <tt>info2</tt>.  This yields the context <tt>sctxt2</tt> and an encapsulation
key <tt>enc2</tt>.</t>
        </li>
        <li>
          <t>Encrypt <tt>response</tt> by invoking the <tt>Seal()</tt> method on <tt>sctxt2</tt>
(<xref section="5.2" sectionFormat="of" target="HPKE"/>) with empty associated data <tt>aad</tt>, yielding
ciphertext <tt>ct2</tt>.</t>
        </li>
        <li>
          <t>Concatenate <tt>enc2</tt> and <tt>ct2</tt>, yielding an Encapsulated Response,
<tt>enc_response</tt>.</t>
        </li>
      </ol>
      <t>In pseudocode, this procedure is as follows:</t>
      <artwork><![CDATA[
req_secret = rctxt.Export("OHTTP PFS Request Derivation", Nsecret)
info2 = concat(encode_str("OHTTP PFS Response"),
               encode(1, 0),
               encode(1, key_id),
               encode(2, kem_id),
               encode(2, kdf_id),
               encode(2, aead_id),
               req_secret)
enc2, sctxt2 = SetupBaseS(pkC, info2)
ct2 = sctxt2.Seal("", response)
enc_response = concat(enc2, ct2)
]]></artwork>
      <t>The client then reverses this process to extract the response. To
decapsulate an Encapsulated Response, <tt>enc_response</tt>, it uses the HPKE
sender context (<tt>sctxt</tt>) from the OHTTP request as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Parses <tt>enc_request</tt> into <tt>enc2</tt> and <tt>ct2</tt> (indicated using the function
<tt>parse()</tt> in pseudocode). Note that <tt>enc2</tt> is of fixed-length, so there is
no ambiguity in parsing this structure.</t>
        </li>
        <li>
          <t>Export a secret, <tt>req_secret</tt>, from <tt>sctxt</tt>, using the string
"OHTTP PFS Request Derivation" as the <tt>exporter_context</tt> parameter to
<tt>context.Export</tt>; see <xref section="5.3" sectionFormat="of" target="HPKE"/>.  The length of this
secret is <tt>Nsecret</tt>, the length of the shared secret for the KEM
associated with <tt>context</tt>.</t>
        </li>
        <li>
          <t>Build <tt>info2</tt> by concatenating the ASCII-encoded string
"OHTTP PFS Response", a zero byte, the values of <tt>key_id</tt>, <tt>kem_id</tt>,
<tt>kdf_id</tt>, and <tt>aead_id</tt>, as one 8-bit integer and three 16-bit
integers, respectively, each in network byte order, and <tt>req_secret</tt>.</t>
        </li>
        <li>
          <t>Create a receiving HPKE context, <tt>rctxt2</tt>, by invoking <tt>SetupBaseR()</tt>
(<xref section="5.1.1" sectionFormat="of" target="HPKE"/>) with <tt>skE</tt>, <tt>enc2</tt>, and <tt>info2</tt>.</t>
        </li>
        <li>
          <t>Decrypt <tt>ct2</tt> by invoking the <tt>Open()</tt> method on <tt>rctxt2</tt>
(<xref section="5.2" sectionFormat="of" target="HPKE"/>), with an empty associated data <tt>aad</tt>,
yielding <tt>response</tt> or an error on failure.</t>
        </li>
      </ol>
      <t>In pseudocode, this procedure is as follows:</t>
      <artwork><![CDATA[
enc2, ct2 = parse(enc_response)
req_secret = sctxt.Export("OHTTP PFS Request Derivation", Nsecret)
info2 = concat(encode_str("OHTTP PFS Response"),
               encode(1, 0),
               encode(1, key_id),
               encode(2, kem_id),
               encode(2, kdf_id),
               encode(2, aead_id),
               req_secret)
rctxt2 = SetupBaseR(enc2, skE, info2)
response, error = rctxt2.Open("", ct2)
]]></artwork>
    </section>
    <section anchor="media-type">
      <name>Media Type</name>
      <t>This mechanism uses a media type to differentiate the response from OHTTP
responses without this extension. The "message/ohttp-res-pfs" is used to
indicate that this extension is in use for the response.</t>
      <t>Gateways <bcp14>MAY</bcp14> respond with "message/ohttp-res" responses and use the response
encoding described in <xref section="4.2" sectionFormat="of" target="OHTTP"/> if it does not PFS to be useful
for the response. This allows saving computational resources, for example, if
the response is a generic response with an error status code where no part of
the response is tied to information in the request.</t>
      <t>If chunked OHTTP <xref target="CHUNKED"/> is in use, the response media type for this
extension is "message/ohttp-chunked-res-pfs".</t>
    </section>
    <section anchor="chunked">
      <name>Chunked OHTTP</name>
      <t>Chunked OHTTP (<xref target="CHUNKED"/>) is different in that the client can send more data
after its first flight.</t>
      <t>For the reponse, all chunks are encrypted by the gateway using the <tt>sctxt2</tt>
context and decrypted by the client using the <tt>rctxt2</tt> context, and using the
AAD construction described in <xref target="CHUNKED"/>.</t>
      <t>For the request, there is a distinction between the first flight and
subsequent chunks. The first chunks are encrypted using <tt>sctxt</tt> as described
in <xref target="CHUNKED"/>. The client keeps using <tt>sctxt</tt> to send subsequent chunks
until is receives the first chunk from the gateway. Once the client receives
that, it creates <tt>rctxt2</tt> (see <xref target="mechanism"/>), and performs the following
steps to switch to it for sending:</t>
      <ol spacing="normal" type="1"><li>
          <t>Encrypt an empty chunk, the encrypted last first flight chunk <tt>elff_chunk</tt>
with <tt>sctxt</tt> using empty associated data <tt>aad</tt>. Send this chunk with a
variable-length integer length prefix.</t>
        </li>
        <li>
          <t>Use that as the associated data <tt>aad</tt> to encrypt the first PFS chunk
<tt>sealed_pfs_chunk1</tt> using <tt>sctxt2</tt>. Send that chunk with a
variable-length integer length prefix.</t>
        </li>
        <li>
          <t>Encrypt all subsequent non-final chunks with an empty AAD and a
variable-length integer length prefix, using <tt>sctxt2</tt>.</t>
        </li>
        <li>
          <t>Encrypt the final chunk with the AAD set to the ASCII-encoded
string "final" and prefixed with a zero length, using <tt>sctxt2</tt>.</t>
        </li>
      </ol>
      <t>In pseudocode, this procedure is as follows:</t>
      <artwork><![CDATA[
elff_chunk = sctxt.Seal("", "")
elff_chunk_len = varint_encode(len(elff_chunk))
send(concat(elff_chunk_len, elff_chunk))
sealed_pfs_chunk1 = sctxt2.Seal(elff_chunk, pfs_chunk1)
sealed_pfs_chunk1_len = varint_encode(len(sealed_pfs_chunk1))
send(concat(sealed_pfs_chunk1_len, sealed_pfs_chunk1))
sealed_pfs_chunk2 = sctxt2.Seal("", pfs_chunk2)
sealed_pfs_chunk_len = varint_encode(len(sealed_pfs_chunk))
send(concat(sealed_pfs_chunk_len, sealed_pfs_chunk2))
...
sealed_final_chunk = sctxt2.Seal("final", chunk)
send(concat(varint_encode(0), sealed_final_chunk))
]]></artwork>
      <t>The gateway needs to handle this transition. It initially handles chunks using
the procedure from <xref target="CHUNKED"/>. When the gateway decrypts a chunk with a
zero-length plaintext, this means that the client is transitioning to the PFS
context (zero-length plaintext non-final chunks are explicitly disallowed in
chunked OHTTP without PFS, see <xref section="6" sectionFormat="of" target="CHUNKED"/>).</t>
      <t>When the gateway decrypts its first zero-length plaintext using the <tt>rctxt</tt>
context, it acts on the ciphertext <tt>elff_chunk</tt> as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>Save <tt>elff_chunk</tt> until the next chunk is received.</t>
        </li>
        <li>
          <t>Wait for and parse the next variable-length integer length-prefixed
chunk, <tt>sealed_pfs_chunk1</tt>.</t>
        </li>
        <li>
          <t>Decrypt <tt>sealed_pfs_chunk1</tt> using <tt>rctxt2</tt> with the associated data <tt>aad</tt>
set to <tt>elff_chunk</tt>.</t>
        </li>
        <li>
          <t>Keep decrypting variable-length integer length-prefixed chunks with the
associated data <tt>aad</tt> empty.</t>
        </li>
        <li>
          <t>When encoutering a variable-length integer length-prefix set to zero,
decrypt the final chunk using the associated data <tt>aad</tt> set to the
ASCII-encoded string "final".</t>
        </li>
      </ol>
    </section>
    <section anchor="sec">
      <name>Security Considerations</name>
      <t>The security considerations described in <xref section="6" sectionFormat="of" target="OHTTP"/> and
<xref section="7" sectionFormat="of" target="CHUNKED"/> apply to this document as well.</t>
      <t>As mentioned in <xref section="7.2" sectionFormat="of" target="CHUNKED"/>, interactivity can cause the
gateway to learn the round trip to the client. The PFS mechanism can
increase that risk if the client sends its last first flight chunk
(see <xref target="chunked"/>) immediately when it receives the gateway's first flight.
To avoid this, clients <bcp14>MUST NOT</bcp14> send their last first flight chunk until
they have more application data to send to the gateway.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <section anchor="ohttp-pfs-http-header-field">
        <name>OHTTP-PFS HTTP Header Field</name>
        <t>This document requests IANA to register the following entry in the
"Hypertext Transfer Protocol (HTTP) Field Name Registry" maintained at
&lt;<eref target="https://www.iana.org/assignments/http-fields"/>&gt;:</t>
        <dl spacing="compact">
          <dt>Field Name:</dt>
          <dd>
            <t>OHTTP-PFS</t>
          </dd>
          <dt>Template:</dt>
          <dd>
            <t>None</t>
          </dd>
          <dt>Status:</dt>
          <dd>
            <t>provisional (permanent if this document is approved)</t>
          </dd>
          <dt>Reference:</dt>
          <dd>
            <t>This document</t>
          </dd>
          <dt>Comments:</dt>
          <dd>
            <t>None</t>
          </dd>
        </dl>
      </section>
      <section anchor="media-types">
        <name>Media Types</name>
        <t>This document requests IANA to register the "message/ohttp-res-pfs" and
"message/ohttp-chunked-res-pfs" media types in the "Media Types Registry"
maintained at
&lt;<eref target="https://www.iana.org/assignments/media-types/media-types.xhtml"/>&gt;.</t>
        <t>The subtype names are "ohttp-res-pfs" and "ohttp-chunked-res-pfs",
respectively. The other fields have the following values:</t>
        <dl spacing="compact">
          <dt>Type name:</dt>
          <dd>
            <t>message</t>
          </dd>
          <dt>Required parameters:</dt>
          <dd>
            <t>N/A</t>
          </dd>
          <dt>Optional parameters:</dt>
          <dd>
            <t>N/A</t>
          </dd>
          <dt>Encoding considerations:</dt>
          <dd>
            <t>"binary"</t>
          </dd>
          <dt>Security considerations:</dt>
          <dd>
            <t>see <xref target="sec"/></t>
          </dd>
          <dt>Interoperability considerations:</dt>
          <dd>
            <t>N/A</t>
          </dd>
          <dt>Published specification:</dt>
          <dd>
            <t>This document</t>
          </dd>
          <dt>Applications that use this media type:</dt>
          <dd>
            <t>Oblivious HTTP and applications that use Oblivious HTTP use this media type to
identify encapsulated binary HTTP responses when using the PFS extension.</t>
          </dd>
          <dt>Fragment identifier considerations:</dt>
          <dd>
            <t>N/A</t>
          </dd>
          <dt>Additional information:</dt>
          <dd>
            <dl spacing="compact">
              <dt>Magic number(s):</dt>
              <dd>N/A</dd>
              <dt>Deprecated alias names for this type:</dt>
              <dd>N/A</dd>
              <dt>File extension(s):</dt>
              <dd>N/A</dd>
              <dt>Macintosh file type code(s):</dt>
              <dd>N/A</dd>
            </dl>
          </dd>
          <dt>Person and email address to contact for further information:</dt>
          <dd>
            <t>see Authors' Addresses section</t>
          </dd>
          <dt>Intended usage:</dt>
          <dd>
            <t>COMMON</t>
          </dd>
          <dt>Restrictions on usage:</dt>
          <dd>
            <t>N/A</t>
          </dd>
          <dt>Author:</dt>
          <dd>
            <t>see Authors' Addresses section</t>
          </dd>
          <dt>Change controller:</dt>
          <dd>
            <t>IETF</t>
          </dd>
        </dl>
      </section>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="OHTTP">
          <front>
            <title>Oblivious HTTP</title>
            <author fullname="M. Thomson" initials="M." surname="Thomson"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="January" year="2024"/>
            <abstract>
              <t>This document describes Oblivious HTTP, a protocol for forwarding encrypted HTTP messages. Oblivious HTTP allows a client to make multiple requests to an origin server without that server being able to link those requests to the client or to identify the requests as having come from the same client, while placing only limited trust in the nodes used to forward the messages.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9458"/>
          <seriesInfo name="DOI" value="10.17487/RFC9458"/>
        </reference>
        <reference anchor="CHUNKED">
          <front>
            <title>Chunked Oblivious HTTP Messages</title>
            <author fullname="Tommy Pauly" initials="T." surname="Pauly">
              <organization>Apple</organization>
            </author>
            <author fullname="Martin Thomson" initials="M." surname="Thomson">
              <organization>Mozilla</organization>
            </author>
            <date day="18" month="February" year="2026"/>
            <abstract>
              <t>   This document defines a variant of the Oblivious HTTP message format
   that allows chunks of requests and responses to be encrypted and
   decrypted before the entire request or response is processed.  This
   allows incremental processing of Oblivious HTTP messages, which is
   particularly useful for handling large messages or systems that
   process messages slowly.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-ohai-chunked-ohttp-08"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="HPKE">
          <front>
            <title>Hybrid Public Key Encryption</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="K. Bhargavan" initials="K." surname="Bhargavan"/>
            <author fullname="B. Lipp" initials="B." surname="Lipp"/>
            <author fullname="C. Wood" initials="C." surname="Wood"/>
            <date month="February" year="2022"/>
            <abstract>
              <t>This document describes a scheme for hybrid public key encryption (HPKE). This scheme provides a variant of public key encryption of arbitrary-sized plaintexts for a recipient public key. It also includes three authenticated variants, including one that authenticates possession of a pre-shared key and two optional ones that authenticate possession of a key encapsulation mechanism (KEM) private key. HPKE works for any combination of an asymmetric KEM, key derivation function (KDF), and authenticated encryption with additional data (AEAD) encryption function. Some authenticated variants may not be supported by all KEMs. We provide instantiations of the scheme using widely used and efficient primitives, such as Elliptic Curve Diffie-Hellman (ECDH) key agreement, HMAC-based key derivation function (HKDF), and SHA2.</t>
              <t>This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9180"/>
          <seriesInfo name="DOI" value="10.17487/RFC9180"/>
        </reference>
        <reference anchor="BHTTP">
          <front>
            <title>Binary Representation of HTTP Messages</title>
            <author fullname="M. Thomson" initials="M." surname="Thomson"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="August" year="2022"/>
            <abstract>
              <t>This document defines a binary format for representing HTTP messages.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9292"/>
          <seriesInfo name="DOI" value="10.17487/RFC9292"/>
        </reference>
        <reference anchor="STRUCTURED">
          <front>
            <title>Structured Field Values for HTTP</title>
            <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
            <author fullname="P-H. Kamp" surname="P-H. Kamp"/>
            <date month="September" year="2024"/>
            <abstract>
              <t>This document describes a set of data types and associated algorithms that are intended to make it easier and safer to define and handle HTTP header and trailer fields, known as "Structured Fields", "Structured Headers", or "Structured Trailers". It is intended for use by specifications of new HTTP fields.</t>
              <t>This document obsoletes RFC 8941.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9651"/>
          <seriesInfo name="DOI" value="10.17487/RFC9651"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="TLS">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="HTTP">
          <front>
            <title>HTTP Semantics</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2022"/>
            <abstract>
              <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of the protocol that are shared by all versions. In this definition are core protocol elements, extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes.</t>
              <t>This document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="97"/>
          <seriesInfo name="RFC" value="9110"/>
          <seriesInfo name="DOI" value="10.17487/RFC9110"/>
        </reference>
      </references>
    </references>
    <?line 420?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thank you to Martin Thomson for
<eref target="https://mailarchive.ietf.org/arch/msg/ohai/Vrh25BxK4wmIDJxeRYrYj6U1-g0/">asking me</eref>
to write this draft, and to Chris Wood for
<eref target="https://mailarchive.ietf.org/arch/msg/ohai/bLD_klUzBwVHUPeXI4a5NRIaoT8/">supporting it</eref>
 more than two years before it was written.</t>
      <t>Thanks to Martin Thomson for reviewing this document.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
