<?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.29 (Ruby 3.4.1) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-mahy-mls-private-external-00" category="info" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.30.2 -->
  <front>
    <title abbrev="MLS Private External Messages">Private External Message extensions for Messaging Layer Security (MLS)</title>
    <seriesInfo name="Internet-Draft" value="draft-mahy-mls-private-external-00"/>
    <author fullname="Rohan Mahy">
      <organization/>
      <address>
        <email>rohan.ietf@gmail.com</email>
      </address>
    </author>
    <author fullname="Mojtaba Chenani">
      <organization>Ephemera</organization>
      <address>
        <email>chenani@outlook.com</email>
      </address>
    </author>
    <date year="2025" month="October" day="20"/>
    <area>Security</area>
    <workgroup>Messaging Layer Security</workgroup>
    <keyword>private external proposal</keyword>
    <keyword>private external commit</keyword>
    <keyword>private external join</keyword>
    <keyword>private GroupContext</keyword>
    <keyword>private ratchet tree</keyword>
    <keyword>external proposal privacy</keyword>
    <keyword>external commit privacy</keyword>
    <keyword>external join privacy</keyword>
    <keyword>GroupContext privacy</keyword>
    <keyword>ratchet tree privacy</keyword>
    <abstract>
      <?line 46?>

<t>MLS groups that use private handshakes lose member privacy when sending external proposals. This document addresses this shortcoming by encrypting external proposals using an HPKE public key derived from the epoch secret. It also provides a mechanism to share this key and protect it from tampering by a malicious intermediary.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://rohanmahy.github.io/mls-private-external/draft-mahy-mls-private-external.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-mahy-mls-private-external/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Messaging Layer Security Working Group mailing list (<eref target="mailto:mls@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/mls/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/mls/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/rohanmahy/mls-private-external"/>.</t>
    </note>
  </front>
  <middle>
    <?line 50?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>The MLS protocol <xref target="RFC9420"/> was designed to support both a model where the Distribution Service (DS) sees the contents of MLS handshake messages and often assumes a policy enforcement role, and a model where the DS is merely responsible for forwarding handshake messages and possibly enforcing ordering of messages.
In the first model clients send every handshake as a PublicMessage (or a SemiPrivateMessage <xref target="I-D.mahy-mls-semiprivatemessage"/>), whereas in the second model the clients send in-group handshakes as a PrivateMessage.
As of this writing there are non-trivial commercial deployments using both the PublicMessage model (ex: Cisco, Amazon, Ring Central, Wire) and the PrivateMessage model (ex: Ephemera, Germ).</t>
      <t>In the PrivateMessage model, group members enjoy substantially more privacy from the DS.
In the PublicMessage model, the DS usually can provide (authorized) non-members with enough information that they can join a group via an external commit.
Even in the PublicMessage model, some (usually large) groups use external proposals to join.
In the PrivateMessage model, (authorized) non-members can also join using external proposals (or rarely using external commits if the GroupInfo is shared by an existing member), however the joiner is currently forced to send the proposal (or commit) as a PublicMessage and therefore reveal potentially private information such as their credential and capabilities to the DS.</t>
      <t>This extension allows groups using PrivateMessage to maintain the privacy of external handshake messages by encrypting them to a public key derived from the group's epoch secret.
It also provides a way to convey that public key safely to prevent active attacks.</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?>

</section>
    <section anchor="mechanism">
      <name>Mechanism</name>
      <section anchor="external-encryption-key-derivation">
        <name>External Encryption Key Derivation</name>
        <t>Groups using this extension derive a dedicated HPKE <xref target="RFC9180"/> key pair from the epoch secret for encrypting external messages. This key pair is derived independently from the ratchet tree structure.</t>
        <t>The external encryption key pair is derived as follows:</t>
        <artwork><![CDATA[
external_encryption_secret =
    ExpandWithLabel(epoch_secret, "external encryption", "", KDF.Nh)

(external_encryption_private_key, external_encryption_public_key) =
    DeriveKeyPair(external_encryption_secret)
]]></artwork>
        <t>Where:</t>
        <ul spacing="normal">
          <li>
            <t><tt>epoch_secret</tt> is the epoch secret from <xref target="RFC9420"/></t>
          </li>
          <li>
            <t><tt>ExpandWithLabel</tt> is from <xref target="RFC9420"/></t>
          </li>
          <li>
            <t><tt>DeriveKeyPair</tt> is from <xref target="RFC9180"/></t>
          </li>
          <li>
            <t><tt>KDF.Nh</tt> is the output size of the hash function for the cipher suite</t>
          </li>
        </ul>
        <t>All group members in the current epoch can derive the same key pair from their shared epoch secret. The public key is made available to external senders via the <tt>ExternalEncryptionInfo</tt> structure (<xref target="ext-info"/>).</t>
      </section>
      <section anchor="ext-info">
        <name>Additional information shared in every commit</name>
        <t>Groups participating in this mechanism include a <tt>root_private_signature_key</tt> component (see <xref section="4.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>) in the GroupContext of type <tt>RootPrivateSignature</tt>, containing a unique random private signature key corresponding to the group's cipher suite.
Whenever a commit removes a member from a group, this component <bcp14>MUST</bcp14> be replaced with a new unique random private signature key.</t>
        <t>Members sending a commit need to calculate the future <tt>epoch_secret</tt>, <tt>external_encryption_secret</tt>, and <tt>external_encryption_public_key</tt> for the new epoch that would result if the commit is accepted.
The commit sender includes one additional Additional Authentication Data (AAD) component (see <xref section="4.9" sectionFormat="of" target="I-D.ietf-mls-extensions"/>) of type <tt>ExternalEncryptionInfo</tt> in every commit (including commits sent in a <tt>PrivateExternalMessage</tt>).
The <tt>ExternalEncryptionInfo</tt> includes the <tt>external_encryption_public_key</tt> for the future epoch.</t>
        <ul empty="true">
          <li>
            <t>Note: SafeSignWithLabel is not used, because there are two different component IDs represented.</t>
          </li>
        </ul>
        <sourcecode type="tls"><![CDATA[
struct {
    opaque root_private_signature_key<V>;
} RootPrivateSignature;

struct {
    ProtocolVersion version = mls10;
    opaque group_id<V>;
    uint64 epoch;
    CipherSuite ciphersuite;
    HPKEPublicKey external_encryption_public_key;
    SignaturePublicKey root_public_signature_key;
} ExternalEncryptionInfoTBS;

struct {
    CipherSuite ciphersuite;
    HPKEPublicKey external_encryption_public_key;
    SignaturePublicKey root_public_signature_key;
    /* SignWithLabel(root_private_signature_key, */
    /*    "ExternalEncryptionInfoTBS", ExternalEncryptionInfoTBS) */
    opaque external_encryption_signature<V>;
} ExternalEncryptionInfo;
]]></sourcecode>
      </section>
      <section anchor="sending-an-external-proposal-or-external-commit-to-the-group">
        <name>Sending an external proposal or external commit to the group</name>
        <t>A non-member client that wishes to send a message to the group, first constructs a <tt>PublicMessage</tt> called <tt>external_message_plaintext</tt>.
The <tt>PrivateExternalMessage</tt> wire format wraps that <tt>external_message_plaintext</tt> by encrypting it to the <tt>external_encryption_public_key</tt>.</t>
        <sourcecode type="tls"><![CDATA[
/*  PublicMessage.content.sender.sender_type != member  */
PublicMessage external_message_plaintext;

encrypted_public_message = EncryptWithLabel(external_encryption_public_key,
    "PrivateExternalMessageContent", PrivateExternalMessageContext,
    external_message_plaintext)

struct {
    /* PublicMessage (the plaintext) is pretty self contained */
} PrivateExternalMessageContext;

struct {
    opaque group_id<V>;
    uint64 epoch;
    ContentType content_type;
    opaque authenticated_data<V>;
    HPKECiphertext encrypted_public_message<V>;
} PrivateExternalMessage;

PrivateExternalMessage.authenticated_data =
   external_message_plaintext.content.authenticated_data

struct {
    ProtocolVersion version = mls10;
    WireFormat wire_format;
    select (MLSMessage.wire_format) {
        case mls_public_message:
            PublicMessage public_message;
        case mls_private_message:
            PrivateMessage private_message;
        ...
        case mls_private_external_message;
            PrivateExternalMessage private_external_message
    };
} MLSMessage;
]]></sourcecode>
      </section>
      <section anchor="decryption-and-verification-by-members">
        <name>Decryption and verification by members</name>
        <t>Members receiving a <tt>PrivateExternalMessage</tt> check that the <tt>group_id</tt> matches a known group and that the epoch is the current epoch.</t>
        <t>To decrypt the message, members first derive the external encryption key pair from their current epoch secret:</t>
        <sourcecode type="tls"><![CDATA[
/* Derive the external encryption key pair from epoch_secret */
external_encryption_secret =
    ExpandWithLabel(epoch_secret, "external encryption", "", KDF.Nh)

(external_encryption_private_key, external_encryption_public_key) =
    DeriveKeyPair(external_encryption_secret)

/* Decrypt the external message */
external_message_plaintext = DecryptWithLabel(
    external_encryption_private_key,
    "PrivateExternalMessageContent", PrivateExternalMessageContext,
    encrypted_public_message.kem_output,
    encrypted_public_message.ciphertext)
]]></sourcecode>
        <t>They then verify the following values in the <tt>PrivateExternalMessage</tt> match their corresponding field in the <tt>external_message_plaintext.content</tt>:</t>
        <ul spacing="normal">
          <li>
            <t><tt>group_id</tt>,</t>
          </li>
          <li>
            <t><tt>epoch</tt>,</t>
          </li>
          <li>
            <t><tt>content_type</tt>, and</t>
          </li>
          <li>
            <t><tt>authenticated_data</tt></t>
          </li>
        </ul>
        <t>Finally, they process the <tt>external_message_plaintext</tt> as if it were a regular <tt>PublicMessage</tt>.</t>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>An established MLS group which only exchanges handshakes using MLS PrivateMessage enjoys a high level of privacy for its members.
The GroupContext and the ratchet tree, including the contents of the credentials in MLS leaf nodes is not visible to outsiders nor to the DS.
However, during the process of joining, private information is often leaked to the DS.
This mechanism focuses on improving the privacy for the external joining mechanisms.</t>
      <t>There are three mechanisms for potential new members to join an MLS group: an existing member gets a KeyPackage (KP) for the new member and commits an Add proposal with the KP; the joiner sends an external proposal asking to join the group that needs to be committed by an existing member; or the joiner fetches the GroupInfo of the group (usually from the DS) and sends an external commit.
In the base MLS protocol <xref target="RFC9420"/>, an external join or external commit needs to be sent as an MLS PublicMessage, which greatly reduces the privacy of the group.</t>
      <section anchor="security-of-external-proposals">
        <name>Security of External Proposals</name>
        <t>External Add proposals in <xref target="RFC9420"/> are sent using an MLS PublicMessage, which is integrity protected but reveals the public signature key, MLS capabilities, MLS credential to the DS, and KeyPackageRef (used to correlate Welcome messages).
If a public key representing the entire target MLS group is available, the external proposer can encrypt this information to all group members without revealing it to the DS.
The external proposer needs a way to get this public key and not the key of an active attacker, and the DS and members need a reasonable authorization and rate limiting mechanisms to prevent from being overwhelmed by such encrypted requests.</t>
        <t>The <tt>ExternalEncryptionInfo</tt> defined in <xref target="ext-info"/> contains a per-group, per-epoch signature key shared by all members of the group
The <tt>ExternalEncryptionInfo</tt> could be posted in transparency ledger, shared as gossip, or additionally signed by a specific member.
The specific mechanism can be tailored to a specific application as needed.</t>
        <t>Application protocols above the MLS layer would also need to provide authorization. For example, in the MIMI protocol <xref target="I-D.ietf-mimi-protocol"/> this could be a join code. Other techniques such as using single or limited use pseudonymous tokens, privacy pass <xref target="RFC9576"/>, or anonymous credit tokens <xref target="I-D.schlesinger-cfrg-act"/> are all reasonable options.
The privacy of some of these techniques could also be reinforced by using Oblivious HTTP <xref target="RFC9458"/>.</t>
      </section>
      <section anchor="security-of-external-commits">
        <name>Security of External Commits</name>
        <t>TODO</t>
      </section>
      <section anchor="security-of-keypackages-and-welcomes">
        <name>Security of KeyPackages and Welcomes</name>
        <t>In the classical usage of MLS, a member of a group fetches a KeyPackage, commits an Add proposal containing that KeyPackage, the sends a Welcome to the new member.
Both the returned KeyPackage and the query for it could reveal a lot of private information.
In order to forward a Welcome message to the correct recipient, the DS needs to be able to associate the <tt>KeyPackageRef</tt> with some resource that eventually delivers to the appropriate client.</t>
        <t>TODO add more.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>TODO IANA</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC9420" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9420.xml">
          <front>
            <title>The Messaging Layer Security (MLS) Protocol</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="B. Beurdouche" initials="B." surname="Beurdouche"/>
            <author fullname="R. Robert" initials="R." surname="Robert"/>
            <author fullname="J. Millican" initials="J." surname="Millican"/>
            <author fullname="E. Omara" initials="E." surname="Omara"/>
            <author fullname="K. Cohn-Gordon" initials="K." surname="Cohn-Gordon"/>
            <date month="July" year="2023"/>
            <abstract>
              <t>Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that messages are only accessible to the communicating endpoints, and not to any servers involved in delivering messages. Establishing keys to provide such protections is challenging for group chat settings, in which more than two clients need to agree on a key but may not be online at the same time. In this document, we specify a key establishment protocol that provides efficient asynchronous group key establishment with forward secrecy (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9420"/>
          <seriesInfo name="DOI" value="10.17487/RFC9420"/>
        </reference>
        <reference anchor="RFC2119" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
          <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" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
          <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="RFC9180">
          <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="I-D.ietf-mls-extensions">
          <front>
            <title>The Messaging Layer Security (MLS) Extensions</title>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="21" month="July" year="2025"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol is an asynchronous group
   authenticated key exchange protocol.  MLS provides a number of
   capabilities to applications, as well as several extension points
   internal to the protocol.  This document provides a consolidated
   application API, guidance for how the protocol's extension points
   should be used, and a few concrete examples of both core protocol
   extensions and uses of the application API.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mls-extensions-08"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="I-D.mahy-mls-semiprivatemessage">
          <front>
            <title>Semi-Private Messages in the Messaging Layer Security (MLS) Protocol</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="16" month="October" year="2025"/>
            <abstract>
              <t>   This document defines a SemiPrivateMessage for the Messaging Layer
   Security (MLS) protocol.  It allows members to share otherwise
   private commits and proposals with a designated list of external
   receivers rather than send these handshakes in a PublicMessage.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mls-semiprivatemessage-06"/>
        </reference>
        <reference anchor="I-D.ietf-mimi-protocol">
          <front>
            <title>More Instant Messaging Interoperability (MIMI) using HTTPS and MLS</title>
            <author fullname="Richard Barnes" initials="R." surname="Barnes">
              <organization>Cisco</organization>
            </author>
            <author fullname="Matthew Hodgson" initials="M." surname="Hodgson">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <author fullname="Travis Ralston" initials="T." surname="Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="7" month="July" year="2025"/>
            <abstract>
              <t>   This document specifies the More Instant Messaging Interoperability
   (MIMI) transport protocol, which allows users of different messaging
   providers to interoperate in group chats (rooms), including to send
   and receive messages, share room policy, and add participants to and
   remove participants from rooms.  MIMI describes messages between
   providers, leaving most aspects of the provider-internal client-
   server communication up to the provider.  MIMI integrates the
   Messaging Layer Security (MLS) protocol to provide end-to-end
   security assurances, including authentication of protocol
   participants, confidentiality of messages exchanged within a room,
   and agreement on the state of the room.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-protocol-04"/>
        </reference>
        <reference anchor="RFC9576">
          <front>
            <title>The Privacy Pass Architecture</title>
            <author fullname="A. Davidson" initials="A." surname="Davidson"/>
            <author fullname="J. Iyengar" initials="J." surname="Iyengar"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="June" year="2024"/>
            <abstract>
              <t>This document specifies the Privacy Pass architecture and requirements for its constituent protocols used for authorization based on privacy-preserving authentication mechanisms. It describes the conceptual model of Privacy Pass and its protocols, its security and privacy goals, practical deployment models, and recommendations for each deployment model, to help ensure that the desired security and privacy goals are fulfilled.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9576"/>
          <seriesInfo name="DOI" value="10.17487/RFC9576"/>
        </reference>
        <reference anchor="I-D.schlesinger-cfrg-act">
          <front>
            <title>Anonymous Credit Tokens</title>
            <author fullname="Samuel Schlesinger" initials="S." surname="Schlesinger">
              <organization>Google</organization>
            </author>
            <author fullname="Jonathan Katz" initials="J." surname="Katz">
              <organization>Google</organization>
            </author>
            <date day="18" month="August" year="2025"/>
            <abstract>
              <t>   This document specifies Anonymous Credit Tokens (ACT), a privacy-
   preserving authentication protocol that enables numerical credit
   systems without tracking individual clients.  Based on keyed-
   verification anonymous credentials and privately verifiable BBS-style
   signatures, the protocol allows issuers to grant tokens containing
   credits that clients can later spend anonymously with that issuer.

   The protocol's key features include: (1) unlinkable transactions -
   the issuer cannot correlate credit issuance with spending, or link
   multiple spends by the same client, (2) partial spending - clients
   can spend a portion of their credits and receive anonymous change,
   and (3) double-spend prevention through cryptographic nullifiers that
   preserve privacy while ensuring each token is used only once.

   Anonymous Credit Tokens are designed for modern web services
   requiring rate limiting, usage-based billing, or resource allocation
   while respecting user privacy.  Example applications include rate
   limiting and API credits.

   This document is a product of the Crypto Forum Research Group (CFRG)
   in the IRTF.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-schlesinger-cfrg-act-00"/>
        </reference>
        <reference anchor="RFC9458">
          <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>
      </references>
    </references>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA91a627bRhb+z6eYuj/WKiS56aY3pzfFchojceyN3QaLxSIa
kSOJNcXhkkM5auA+yz7LPtl+58yFpEw57WKBBbZAW3k4M+d+n9FoFJnUZOpY
HFyW6UYaJU7fGVXmMhPnqqrkUgmFhbxKdV6JhS7dcpovxUu5VaW4UnFdpmYr
Ds9fXg0OIjmfl2qDC/Gn2HdpdRDFWF/qcnss0nyhoyjRcS7XwCQp5cKM1nK1
Ha2zalTYK0bKXTH69NOoqufrtCKczLbAkbPT62dCfCxkVmlATvNEFQr/yc3B
UByoJDW6TGVGf5xNnuJ/oOPg7PX1s4Mor9dzVR5HCWAcRzGoBLF1dSxMWasI
dPw5kqWSuNUTehDd6vJmWeq6ICr3sOMgulFbbEyOIzESjgjhicCCLnQls96P
sV6vU9P76Red5u0PPxIaJ+ADdrTXS2nilTKgQilavwfY7oy3nY8WcO8nAtz+
0AbcXm8DDusbldfgrhAf5poQVqQHb8Bk2sCAaH0t0wzr0IkfUmUWY10uaVmW
8QrLK2OK6vjoiHbRUrpRY7/tiBaO5qW+rdQRzh/RuWVqVvUcJ0u9kjmp21Gf
utHWDAuVaQEJR8b2lnGqew8ffUCXxyuzBoRI1malS9IUQBNiUWeZtYXXBEic
4zx/UJYHDJ6p+2FJK2PI7f7Zc/2LkXMpTlYql3nKX8EM/PxVGpjOsTgtVmqt
Stm+O7a7f9C1ybS+4aujXJdrnNlAhhFZa/PXaDQScl6ZUsYmisjkWcSVMCtp
RF2poJFAOalW8kZVItNYXysyPK8i4hZwBWwvIZnf09ZqLK5XaSXgJOo1zFrI
JCmhQ4oAYb0C+wxQpcPzrVB5XG4L038VsKIP4OvzyxenoqjnWRoLWKtIFJBR
iViUeo17YXaFjlfAKi6VGYszww6GbtqkCUBLEBGDrrTCdg0k4CksPnQb6KWt
RsVGwKjspXJdAIjFEsclQKe6ruADgeYankqW27Fl6zpNkkxF0cfiLDelTuqY
pBZF10CMGE1361hn4v37j14/O/n68Wef3t2JWwkuqSpd5iCEkKqLArwRc21W
BFEnKiNmM6ZKTFPILp3XdDWssNyksRKH06sBqGbmKjgF4JabSugFww2CBPXW
mTOpeoFdQlYVBESsKTRoI1FAXWLFQit1poa8uQeRKwG+QRtVthUQbQFPnM4z
xTEH/97KklVjD3SIlrZ7eLQTvteyGnj7vePoLGdwi7SsjEMizlKmj7RPqI0q
ty0okmi5ZB3xAfEQGEkwa5268OY/vH///dloOg7mXmGLU3+HwN3dYGiJliRz
RgXqpQHY4sIMb+OT5iO2qLb9WJw6sMfRhAXE2ncLV0qEG+YuKWWu8xHkvEmd
k1dgEX4iTGZ6u2Zo1ipYTQiJLskWuUP17licpFWsh2Kylr/qfChe06kT3FDK
bCjepKUasED4ji57Wpd4zzMUP0LtB9B4J5e+I0PrU5zHqCDiX/QWig23I3MD
OiD2tS5DuGnsd3oVBN5Dz9ArXl3VfEksc2/c4tD65PRXlQyYfR76LTw+UND1
ciWCL9S5dXi40F7D4VI6xMF2cjc7YXYcnSIuei3oxa/Sa2Di0UNcW4K7zsGS
b+1xbjB5gj1+mKF7qSPc2ckxAVYneqCQCZSSbXVnj6UNyr1g8By9z8AmwV4a
RxJ2fcQNuB46akHDLlb6lqyPzxF4/MQhJAYl1AuQ2JFYp6achoVshhCyoAd9
Jus0slQL0hPkp4rI0eTXrP74KNWWaFXD+Ut2giluB+p2O98Wy0LO0wyGppjp
Xt0ijlMhZwYzM6QdjdCI4h2Z4DRib26kUwWvxjDnwNYet9eNczjIQUg+GNAY
jT9V3cAW9QS2W7ml2+CZNriHdbt1byUXJHpDR8BLiscxJQRCGiPjG7hZRK0T
OpsbLhyIY1O1SPOU/7ZBjG6iDLlCPvjT1TVl5/R/8eqCf78+/ctPZ69Pp/T7
6vnk5cvwI3I7rp5f/PRy2vxqTp5cnJ+fvpraw1gVnaXo4Hzy1wMbiQ4uLq/P
Ll5NXh5YS+wkGSULZ65seAatBsyUVQQexYiaityzeHpy+a9/PnrswvBnjx59
jTBs//jq0ZePKSYjt7HQdJ5t3Z/kKiJZFEqWdAv0hHQqNZDEkLQOKc1tLkhn
wc1P/kac+fux+GYeF48ef+cWiODOoudZZ5F5dn/l3mHLxJ6lHjCBm531HU53
8Z38tfO353tr8ZvvM1i9GD366vvvIlKhc59e4Y+PmyLy1Kk9zOsFdGiq2J44
OfqxbWema4rWGqDcCfIsKj8TmwG6/OnRV5Q/kVIWEvbemwRyNtKXXYYEw+ap
4RZSJ2eErao0a8WoTsGEZAxpXs0yJxMJ96uG5L67JdXm7GmQk//222+RP/i2
OfjWkfAtp/un7woo5BsEs5dyrrJDptJtoZr5PmAyJfz7Yvps/Go1iKLDPhjO
j74FkkPRu4G9CH0fOExYfAqCvARRvZdarAZMWPSGTIIqDzFr4zwjdtwXF3G5
nR/TsR3S+WTvxg5m97axvtA2y5GAACqnojaiQnC1GRnVPtUKlVnOGTzrEOd5
KbKgEmEmNUjzJ3AA3TzHhQMXAB1hFKCdInPyiFLvvs7ip4u13QqGVKrlxinh
lsh15IaKZkq24e2C5CnIEhqUvRCombe/xvwosM8apRWH79/j+IiCKDLdMVvt
JEnY6ePGTnC1+IFGm3G71sP7j8MFwZgLWRqUSYVkk/Neuim90jzOaiJDzEqt
TdBBKoIk4UXaNiMIKCqIk4eobSDFK2Xl8Xj8BQnqI8rdqajm3L3peoESL4pO
04Nkuy3Al9cA6kL6lQc5G3LdhJDOtaao8/QfNRl7nkBEPtsIGLI4Yl3awocL
HZdT+IjdVpYxGUHOuZL0jCvVWm9cTcqFNeuCy0CHlmUNBzh4zCkTKjJJSRVn
tVLk6vb3oArJnjsl9SV7QCRXNkeLZRbX1Dmx9VbNZ7smO8Tfe819ZiNm747G
icyCNRHqVts5W7nVdZZQIVlnxiejDkNwQsaxKhAAxuxl3bpVeK9OKKcQi2Sj
vS1FniB7ptQmtro8lUaKw8lkOnhIyb7+kJIFhdpnaLvGcmhRJfb7tLsi0Fx6
zJxK+stctjkbWJofAOLIZ5v/vdx38mUBQDu+E6+QXB+LKySKZBPB2RLzc82d
oWQIDYwl1TFNoWputUjSxUKxy2u4eTatSFkhT/xFcqNgIExWRdb7iPe2v1VI
1t29buCbn797Et2JPpN9EnXvunT9lZ+h5iTBjfv/twKie/TpkzZAtrK3acLX
03qNjPGLx5YfduWEDfiK7NcZM9uy/Uh5iK1YKKF5mOn2REC7OWaptvs6RBPF
/eK+fnq1S/b/FE86cfSJ6KjM4X5pDsUnR/4M/jnYSyTylr3fBv4SJ8tel+Sh
Ov3pv+yJzVAQ9K68V8x7Ou+UQu503NvOHqlAqyR33SDn1NJqZctNroClTzs7
54euuUWzDBZsxd6gXQ/PyDtnqu1d3U1vEQ9Sjm8z5yf2uBHgUnJzbk14ldK3
fB+6cadkbej+kJtpmTtJukPL2PUnx9Z9u/+9ZU/60bc+GpKMuy2B/XjCIhwa
KvFYeEZ/64uPVub8IO5DVq2Dfi6eWNShnQ98f2fsHfsRHuyYMHi007HktkLY
Tk6YilmDSl5lC5+pQB/ApbuHcdl1F3/AAVpir0kwTmYspY4jlU1kBfMTBNZw
I/ke65w4/donImeh/UQA+/4P4/uAbXmyn+tB8e4f/U8iCbVOnzlzws+31rTs
N0iJpgg0YfX4tvYMHBj6J5Y0WsmqHaYchw2MT0c5ujuf9FzlXG//Xd1e1s7e
5rbxeLz/5l0mP+kDsSMxse8wn70jHWjY1XjmqQqFNKWXEEW68Hkc3JOrvZr8
tlSxSjc2w93rC1HAxzehAyxm3hpmqK+ouicPfJNTP8dWeLYd6XbbpNUVj51i
j5oASIcsxvzZkTgMNaJ19a2C8MGOQas+7FaVNuU+7rjZ6R+5tJ3Xkxf5v+w/
WK400tjt/nQIv+cvYO7ucEN117HvoeO/F0H2uMzxjVq/tW2LD2yMg/913Zjr
FbeHVW4taWuLAW5Fkc1sZFar0MnYaz9sJV4xO1XwIlVZEs5/2BnPbGcoGOAw
9Insz3bgsRUmrd734LMoepbmNBqwnVrK3mIA/RAeM2rFodxEbnPLNQ0cyBJl
cLmbgXGLPLydOaFpJ6xYuvb4BHljZSQOIOFLRJiri9tVCk5xG1m9owYITQJa
o0Hb+Gw9vQnpDg3NyA+t0uVKZKgjMyo4w8gMSSnVj86v2Nyv0+7wQ712v3Io
mgp0d1TMf4eZCesAoZUpuUB6SwWmKwU3qR30IheEDjIb6EPZnqo8t6OhoUjq
0gPzEgEsmhZhedg7xkkrN5sG6Bvbm/DXXncbSQsd1xUX/iJd8zAkgGq41DF8
B7i5o7KNW1/Nrqip23zkC8LYiVsW3pG7uR1VDEHaxz1zMrFUnNCzv4pvOLt7
cTnotEHcTh5Tub4ALpokSVODcL+H9r+4fNIeuFH2XPWXLbK6cX0pRjTUGzaS
UdunctMSC9TsG/U9Eboz5FsoGyO780KnQhZEmIG2Rrt2znwfYT9ddQPQOSUb
e99LDDtHmbCe8qxNHHdYZOUF1bHqobPPZamk4XcMSR07ylpTvUDX2BWLzgvg
U5hxXPpZaxSFtbYE2aA6Lz9I4Ri58L5lL36pfXCyZKjujQpJqzZuNupQtq3i
TutvyLe2p59upRmPBgOzHbxGU1+rBUnS9QfJz3N/8I3KYhp0+xnKALJbdAeZ
ofXjLZJ+koHRSNy0/CP19nw3e9i1Vcs5qqhJ5LkP48yL1hhf8yiu24kna9GB
Od3a1fqRPjhWa8IslRBlcC26iD/kA40bh0IDaADfHqaS1/O+d3rFPz1a3Gql
CCMrnXP/3o/1ZUhwS+Jwlq5T0/VT7eEtG9Vc8VsZeNnblcrW1nh5BB6yAUBC
jVYZ5+T29xATGvXa7n57IuALTX4epMqRa1fQT5eGdvrhrecCWRaIbtvPw1jE
3AKGyUIcxmJjSplXBa7NYYmZSpbEXQcHNr2kV0QFPw9tGr+wY/ecit9sVYWK
qWRwCFnhtxZ9MCEtm5OGppkurcq3DsuiyHzZIa0kuas5aa17hwV2zbXLxDmE
8pNJ2+Dmub1vufu3Kx0tGItn7NHkusg4YNt7zs7P2h7x+6YvDV0Z+S+QmZsc
OFZK6yNjBPCxuKC+rYDzWPHIoAovJqwHov9AJwGd9Q848nvAStWJzrdrevZm
9I3Kq2FwjoVEQAc25NU+//IL8s8ki9zvJy/DpkfHPNpVvMoUAYMexYtyOYL9
OH9IitMyD83a4bKblkPmdzZWsagb3RAUN0zmaUmau0coc//w5QK2vOEnfM+v
ry897o8//+ru7gHvfmLDMszoYnpxb1vjMe3LCecgq/BKKs7AJ6hJBiQoA7Av
84bN8If8iPNhPrq2U4bh3rygNbTisN4+Yx+rcbgNPts5wSbrGEdP/RMy1Ex1
SXbTylW8JwN3S591Oi67VzlSZNqE1LSby3FQ53d9BNi9Cmxhs9MO5RATk9tG
3UJd1PDiqx3Q/eATLNVx6gdWs07YmtmEifUEgUjXUALLIPagNjdJFFTB5XJ0
BWwcbC35StvFHVuBk3PhF2tcBJxNXk3uFQC8jb5E9jHoHKhE/wZiSSvNry8A
AA==

-->

</rfc>
