<?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.1 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-party-mimi-user-private-discovery-02" category="info" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.18.1 -->
  <front>
    <title abbrev="E2EE Messaging Private User Discovery">Interoperable Private Identity Discovery for E2EE Messaging</title>
    <seriesInfo name="Internet-Draft" value="draft-party-mimi-user-private-discovery-02"/>
    <author fullname="Giles Hogben">
      <organization>Google</organization>
      <address>
        <email>gih@google.com</email>
      </address>
    </author>
    <author fullname="Femi Olumofin">
      <organization>Google</organization>
      <address>
        <email>fgolu@google.com</email>
      </address>
    </author>
    <date year="2023" month="October" day="10"/>
    <area>ART</area>
    <workgroup>More Instant Messaging Interoperability (mimi)</workgroup>
    <keyword>interoperable E2EE messaging</keyword>
    <keyword>private user discovery</keyword>
    <abstract>
      <?line 52?>

<t>This document specifies how users can find each other privately when using end-to-end encrypted messaging services. Users can retrieve the key materials and message delivery endpoints of other users without revealing their social graphs to the key material service hosts. Users can search for phone numbers or user IDs, either individually or in batches, using private information retrieval (PIR). Our specification is based on a state-of-the-art lattice-based homomorphic PIR scheme, which provides a reasonable tradeoff between privacy and cost in a keyword-based sparse PIR setting.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://datatracker.ietf.org/doc/giles-interop-user-private-discovery/"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-party-mimi-user-private-discovery/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        mimi Working Group mailing list (<eref target="mailto:mimi@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/mimi/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/mimi/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/femigolu/giles-interop-user-private-discovery"/>.</t>
    </note>
  </front>
  <middle>
    <?line 57?>

<section anchor="terminology">
      <name>Terminology</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>Glossary of terms:</t>
      <ul spacing="normal">
        <li>
          <t>Authoritative Name Server: Final holder of the IP addresses for a specific domain or set of domains.</t>
        </li>
        <li>
          <t>Client: A software application running on a user's device or computer.</t>
        </li>
        <li>
          <t>Database: A collection of records all of equal sizes (i.e., padded as appropriate).</t>
        </li>
        <li>
          <t>Dense PIR: A type of PIR scheme that is used to retrieve information from a database using the index or position of each record as key. This is equivalent to the standard PIR schemes from the literature.</t>
        </li>
        <li>
          <t>DNS: See Domain Name Service.</t>
        </li>
        <li>
          <t>​​Domain Name Service: A system that accepts domain names and returns their IP addresses.</t>
        </li>
        <li>
          <t>FHE: See Fully Homomorphic Encryption.</t>
        </li>
        <li>
          <t>Fully Homomorphic Encryption: A type of encryption that allows arithmetic operations to be performed on encrypted data without decrypting it first.</t>
        </li>
        <li>
          <t>KDS Resolver: A service that helps clients find and download the public keys of other users.</t>
        </li>
        <li>
          <t>KDS: See Key Distribution Server.</t>
        </li>
        <li>
          <t>Key Distribution Server: A server holding the public key material that enables a user to securely communicate with other users.</t>
        </li>
        <li>
          <t>Name Server: Stores DNS records that map a domain name to an IP address.</t>
        </li>
        <li>
          <t>Partition: A smaller division of a shard that is used to facilitate recursion with PIR.</t>
        </li>
        <li>
          <t>PIR: See Private Information Retrieval</t>
        </li>
        <li>
          <t>Preferred Service: A messaging service that a user has chosen as the default.</t>
        </li>
        <li>
          <t>Private Information Retrieval: A cryptographic technique that allows a client to query a database server without the server being able to learn anything about the query or the record retrieved.</t>
        </li>
        <li>
          <t>Public Key Bundle: Cryptographic key and other metadata that are used to encrypt and decrypt messages.</t>
        </li>
        <li>
          <t>Public Key PIR: A type of PIR scheme that uses a small amount of client storage to gain communication and computation efficiencies over multiple queries.</t>
        </li>
        <li>
          <t>Resolver: A service that helps clients find the IP address for a domain through recursive queries over Name Servers hierarchy.</t>
        </li>
        <li>
          <t>Shard: A subset of a large database that is divided into smaller, more manageable pieces.</t>
        </li>
        <li>
          <t>Sparse PIR: A type of PIR scheme that is used to retrieve information from a database of key-value pairs. This is the same as Keyword PIR in the literature.</t>
        </li>
        <li>
          <t>Transform: A process of converting the partitions in a shard into a format that is suitable for homomorphic encryption computations.</t>
        </li>
      </ul>
    </section>
    <section anchor="introduction">
      <name>Introduction</name>
      <t>Outline of design for message delivery bridge and key distribution server discovery mechanisms for interoperable E2EE messaging clients. A DNS-like resolver service stores UserID &lt;-&gt; service pairs that map to key distribution and message delivery endpoints (e.g. Platform1 Bridges).  Each service is responsible for an "authoritative name server" that covers its own users and this can be replicated/cached by other providers and retrieved by sender clients using a privacy preserving protocol to prevent social graph leakage.</t>
      <section anchor="functional-requirements">
        <name>Functional Requirements</name>
        <t>For a given messaging service identity handle (phone number or alphanumeric UserID):</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Endpoint discovery</strong>: discover receiver service IDs to retrieve public key material and send message payload e.g. <eref target="matrix.org/send/">Platform1.org/send/</eref>, <eref target="matrix.org/kds">Platform1.org/kds</eref></t>
          </li>
          <li>
            <t><strong>Default service discovery</strong>: Discover optional default receiver service ID user preference for a given PN/UserID (e.g. default:Platform1.org)</t>
          </li>
          <li>
            <t><strong>Global uniqueness</strong>: Fully-qualified service identifiers should be globally unique</t>
          </li>
          <li>
            <t><strong>Key verification (P1)</strong>: Provide an independently trusted party to assert and verify the association between a public key and a UserID</t>
          </li>
        </ol>
      </section>
      <section anchor="privacy-requirements">
        <name>Privacy Requirements</name>
        <ol spacing="normal" type="1"><li>
            <t><strong>Social graph</strong>: Resolver or discovery services should not learn the PN/UserID a client is querying for (i.e. who is sending a message to who)</t>
          </li>
          <li>
            <t><strong>Querying user identity</strong>: A resolver service should not default to sharing the querying user identity with other resolver services when it requires their help for discovery</t>
          </li>
          <li>
            <t><strong>Metadata</strong>: Resolver service should not learn the exact timing of when a message is sent</t>
          </li>
        </ol>
      </section>
      <section anchor="other-non-functional-requirements">
        <name>Other Non-functional Requirements</name>
        <ol spacing="normal" type="1"><li>
            <t>No single entity should be financially responsible for resolving all identity queries (e.g. even within a geographical region)</t>
          </li>
          <li>
            <t>Costs for each participating entity of storing and querying key records should be proportional to their number of participating users</t>
          </li>
          <li>
            <t>Performance should support each client querying each of their contacts at least once every 24 hours</t>
          </li>
        </ol>
      </section>
      <section anchor="non-requirements">
        <name>Non-requirements</name>
        <ol spacing="normal" type="1"><li>
            <t><strong>Hiding service reachability</strong>: This is the link between a UserID and a service. All major E2EE messaging services already publish unACL'd reachability information without opt-out i.e. +16501234567, reachable on Messages, Whatsapp, Telegram (not including name or any other info). Therefore this should not be a goal (and would not be feasible to implement).</t>
          </li>
          <li>
            <t><strong>Hiding the value of UserIDs or public keys</strong>: e.g. the existence of the PN, +16501234567</t>
          </li>
          <li>
            <t><strong>Hiding the association between a public key and a UserID</strong>: e.g. PN +16501234567 has pubkey x</t>
          </li>
          <li>
            <t><strong>Contact lookup by name</strong> (or anything except username)</t>
          </li>
        </ol>
      </section>
    </section>
    <section anchor="proposed-solution">
      <name>Proposed solution</name>
      <section anchor="key-distribution">
        <name>Key distribution</name>
        <artset>
          <artwork type="svg"><svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="616px" preserveAspectRatio="none" version="1.1" viewBox="0 0 617 616" width="617px">
              <defs/>
              <g>
                <line x1="34" x2="34" y1="54.0293" y2="563.0156" stroke="black" stroke-width="0.5"/>
                <line x1="160.5" x2="160.5" y1="54.0293" y2="563.0156" stroke="black" stroke-width="0.5"/>
                <line x1="296.5" x2="296.5" y1="54.0293" y2="563.0156" stroke="black" stroke-width="0.5"/>
                <line x1="424.5" x2="424.5" y1="54.0293" y2="563.0156" stroke="black" stroke-width="0.5"/>
                <line x1="523.5" x2="523.5" y1="54.0293" y2="563.0156" stroke="black" stroke-width="0.5"/>
                <line x1="584.5" x2="584.5" y1="54.0293" y2="563.0156" stroke="black" stroke-width="0.5"/>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="58" x="5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="25.5" y="26.0752">P1</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="17" y="43.0898">Client</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="58" x="5" y="562.0156" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="25.5" y="583.0908">P1</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="17" y="600.1055">Client</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="89" x="116.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="152.5" y="26.0752">P1</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="128.5" y="43.0898">Front End</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="89" x="116.5" y="562.0156" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="152.5" y="583.0908">P1</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="128.5" y="600.1055">Front End</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="109" x="242.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="288.5" y="26.0752">P1</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="254.5" y="43.0898">Name Server</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="109" x="242.5" y="562.0156" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="288.5" y="583.0908">P1</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="254.5" y="600.1055">Name Server</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="127" x="361.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="368.5" y="26.0752">Authoritative P2</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="380" y="43.0898">Name Server</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="127" x="361.5" y="562.0156" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="368.5" y="583.0908">Authoritative P2</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="380" y="600.1055">Name Server</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="50" x="498.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="515" y="26.0752">P2</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="510.5" y="43.0898">KDS</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="50" x="498.5" y="562.0156" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="515" y="583.0908">P2</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="510.5" y="600.1055">KDS</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="53" x="558.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="576.5" y="26.0752">P2</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="565.5" y="43.0898">Client</text>
                <rect fill="white" height="48.0293" rx="2.5" ry="2.5" width="53" x="558.5" y="562.0156" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="576.5" y="583.0908">P2</text>
                <text fill="black" font-family="sans-serif" font-size="14" x="565.5" y="600.1055">Client</text>
                <polygon fill="black" points="413,97.6279,423,101.6279,413,105.6279,417,101.6279" stroke="black" stroke-width="1.0"/>
                <line x1="297" x2="419" y1="101.6279" y2="101.6279" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="304" y="81.0991">Request P2</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="304" y="96.8984">Name Records</text>
                <polygon fill="black" points="308,143.2266,298,147.2266,308,151.2266,304,147.2266" stroke="black" stroke-width="1.0"/>
                <line x1="302" x2="424" y1="147.2266" y2="147.2266" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="314" y="126.6978">Replicate P2</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="314" y="142.4971">Name Records</text>
                <polygon fill="black" points="149,188.8252,159,192.8252,149,196.8252,153,192.8252" stroke="black" stroke-width="1.0"/>
                <line x1="34" x2="155" y1="192.8252" y2="192.8252" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="41" y="172.2964">PIR Query</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="41" y="188.0957">PN/UserID</text>
                <polygon fill="black" points="285,234.4238,295,238.4238,285,242.4238,289,238.4238" stroke="black" stroke-width="1.0"/>
                <line x1="161" x2="291" y1="238.4238" y2="238.4238" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="168" y="217.895">PIR Query</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="168" y="233.6943">PN/UserID</text>
                <path d="M114,251.4238 L114,292.4238 L344,292.4238 L344,261.4238 L334,251.4238 L114,251.4238 " fill="white" stroke="black" stroke-width="0.5"/>
                <path d="M334,251.4238 L334,261.4238 L344,261.4238 L334,251.4238 " fill="white" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="151.5" y="269.4937">Supported service IDs</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="156.5" y="285.293">+ default service</text>
                <polygon fill="black" points="172,331.6211,162,335.6211,172,339.6211,168,335.6211" stroke="black" stroke-width="1.0"/>
                <line x1="166" x2="296" y1="335.6211" y2="335.6211" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="178" y="315.0923">Service IDs</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="178" y="330.8916">&amp; default service</text>
                <polygon fill="black" points="511.5,377.2197,521.5,381.2197,511.5,385.2197,515.5,381.2197" stroke="black" stroke-width="1.0"/>
                <line x1="161" x2="517.5" y1="381.2197" y2="381.2197" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="168" y="360.6909">Query</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="168" y="376.4902">PN/UserID</text>
                <polygon fill="black" points="172,422.8184,162,426.8184,172,430.8184,168,426.8184" stroke="black" stroke-width="1.0"/>
                <line x1="166" x2="522.5" y1="426.8184" y2="426.8184" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="178" y="406.2896">Return Public Key Bundle</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="178" y="422.0889">(Signed by provider or 3P CA)</text>
                <polygon fill="black" points="45,468.417,35,472.417,45,476.417,41,472.417" stroke="black" stroke-width="1.0"/>
                <line x1="39" x2="160" y1="472.417" y2="472.417" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="51" y="451.8882">Return Public</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="51" y="467.6875">Key Bundle</text>
                <line x1="34" x2="76" y1="502.2163" y2="502.2163" stroke="black" stroke-width="1.0"/>
                <line x1="76" x2="76" y1="502.2163" y2="515.2163" stroke="black" stroke-width="1.0"/>
                <line x1="35" x2="76" y1="515.2163" y2="515.2163" stroke="black" stroke-width="1.0"/>
                <polygon fill="black" points="45,511.2163,35,515.2163,45,519.2163,41,515.2163" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="41" y="497.4868">Encrypt Message</text>
                <polygon fill="black" points="573,541.0156,583,545.0156,573,549.0156,577,545.0156" stroke="black" stroke-width="1.0"/>
                <line x1="34" x2="579" y1="545.0156" y2="545.0156" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="41" y="540.2861">Send Encrypted Message via messaging providers</text>
                <!--SRC=[RP1DIyD048Rl-HL33w9e4VNMGo5VXL8iCS5RBjli61VIsNK_0ldtJaArslIsxFEyC- -k4TQhHXb17XR5KqsGTWh9Bq0uY2Cpmnkh-PoJd8paYh4NHuGAROzsSjB_JXpyfxRA2wzwXEAvfij0TZ6K5TXbrSJoEVjJU1D5wNAThQ34hu3EdyUNs6WhNPGjr-c8JQSQuN4knCjrie9YMy9RG3lKLEmVtntQRHObK_Og8ispD3y0qWV-580g6AEjHmaizAf1s6QEx-4U97w8qFaV42596FDZTLvTdVsQRcOsbyXNymBvb2tH1qjGX0C_3tOuG198TbZJRQLQuZQ70OpLlP9SLLjuAI2DxyQXyKMwfdDy_1JcEJLsC1vUqJdHJhURiI_tFo5US8BGAm77wQoe_Ttfecy0]-->
  </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[     ┌───────┐          ┌──────────┐          ┌────────────┐          ┌────────────────┐          ┌────┐          ┌──────┐
     │P1     │          │P1        │          │P1          │          │Authoritative P2│          │P2  │          │P2    │
     │ Client│          │ Front End│          │ Name Server│          │Name Server     │          │ KDS│          │Client│
     └───┬───┘          └────┬─────┘          └─────┬──────┘          └───────┬────────┘          └─┬──┘          └──┬───┘
         │                   │                      │       Request P2        │                     │                │    
         │                   │                      │       Name Records      │                     │                │    
         │                   │                      │ ────────────────────────>                     │                │    
         │                   │                      │                         │                     │                │    
         │                   │                      │       Replicate P2      │                     │                │    
         │                   │                      │       Name Records      │                     │                │    
         │                   │                      │ <────────────────────────                     │                │    
         │                   │                      │                         │                     │                │    
         │     PIR Query     │                      │                         │                     │                │    
         │     PN/UserID     │                      │                         │                     │                │    
         │───────────────────>                      │                         │                     │                │    
         │                   │                      │                         │                     │                │    
         │                   │       PIR Query      │                         │                     │                │    
         │                   │       PN/UserID      │                         │                     │                │    
         │                   │ ─────────────────────>                         │                     │                │    
         │                   │                      │                         │                     │                │    
         │             ╔═════╧══════════════════════╧═══════╗                 │                     │                │    
         │             ║Supported service IDs              ░║                 │                     │                │    
         │             ║ + default service                  ║                 │                     │                │    
         │             ╚═════╤══════════════════════╤═══════╝                 │                     │                │    
         │                   │   Service IDs        │                         │                     │                │    
         │                   │   & default service  │                         │                     │                │    
         │                   │ <─────────────────────                         │                     │                │    
         │                   │                      │                         │                     │                │    
         │                   │                      │        Query            │                     │                │    
         │                   │                      │        PN/UserID        │                     │                │    
         │                   │ ─────────────────────────────────────────────────────────────────────>                │    
         │                   │                      │                         │                     │                │    
         │                   │                     Return Public Key Bundle   │                     │                │    
         │                   │                     (Signed by provider or 3P CA)                    │                │    
         │                   │ <─────────────────────────────────────────────────────────────────────                │    
         │                   │                      │                         │                     │                │    
         │   Return Public   │                      │                         │                     │                │    
         │   Key Bundle      │                      │                         │                     │                │    
         │<───────────────────                      │                         │                     │                │    
         │                   │                      │                         │                     │                │    
         ────┐                                      │                         │                     │                │    
             │ Encrypt Message                      │                         │                     │                │    
         <───┘                                      │                         │                     │                │    
         │                   │                      │                         │                     │                │    
         │                   │          Send Encrypted Message via messaging providers              │                │    
         │───────────────────────────────────────────────────────────────────────────────────────────────────────────>    
     ┌───┴───┐          ┌────┴─────┐          ┌─────┴──────┐          ┌───────┴────────┐          ┌─┴──┐          ┌──┴───┐
     │P1     │          │P1        │          │P1          │          │Authoritative P2│          │P2  │          │P2    │
     │ Client│          │ Front End│          │ Name Server│          │Name Server     │          │ KDS│          │Client│
     └───────┘          └──────────┘          └────────────┘          └────────────────┘          └────┘          └──────┘
]]></artwork>
        </artset>
        <t>Taking Platform1 client sending to a Platform2 user as an example:</t>
        <ol spacing="normal" type="1"><li>
            <t>Platform1 name server replicates authoritative Platform2 NS records. There will need to be a shared list of participating services and name server endpoints.</t>
          </li>
          <li>
            <t>Platform1 client sends key bundle request to Platform1 front end (PIR encrypted PN/UserID)</t>
          </li>
          <li>
            <t>Platform1 FE gets supported key distribution service IDs, version number + default service=Platform2 via PIR protocol from its own name server.</t>
          </li>
          <li>
            <t>Platform1 FE queries Platform2 KDS to retrieve public keys.</t>
          </li>
        </ol>
        <ul spacing="normal">
          <li>
            <t>4.1 Platform1 Client first sends (query and session key) encrypted with Platform2 public key to Platform1 FE.</t>
          </li>
          <li>
            <t>4.2 Platform1 FE sends encrypted query to Platform2 KDS</t>
          </li>
          <li>
            <t>4.3 Platform2 KDS decrypts query and session key, encrypts response with session key</t>
          </li>
          <li>
            <t>4.4 Platform2 KDS sends encrypted response to Platform1 FE</t>
          </li>
          <li>
            <t>4.5 Platform1 FE forwards to Platform1 client</t>
          </li>
        </ul>
        <ol spacing="normal" type="1" start="5"><li>
            <t>Platform 1 Client and Platform 2 Client exchange messages through their respective messaging providers.</t>
          </li>
        </ol>
        <t>This provides E2EE interop while only disclosing to gateway service which services a phone number is registered to. In all other respects, gateway services learn no more information than in the non-interop case.</t>
      </section>
      <section anchor="resolver-registration">
        <name>Resolver registration</name>
        <t>Each service is responsible for registering user enrollments with the resolver.</t>
      </section>
      <section anchor="preferred-service-integrity">
        <name>Preferred service integrity</name>
        <t>While the preferred service is public, the user should control its value/integrity. As well as ensuring user control, it also prevents spoofing attacks where an attacker A could create an account on a new service that B does not have an account on, and then set it to B's preferred service (see cross-service identity spoofing below). Therefore to prevent anyone but the user modifying the default service value, records must be signed with the user's private key and verified by the sender against their public key. For multiple key pairs across different services, the last key pair to sign the default service bit must be used to change the default.</t>
        <artset>
          <artwork type="svg"><svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="225px" preserveAspectRatio="none" version="1.1" viewBox="0 0 604 225" width="604px">
              <defs/>
              <g>
                <line x1="31" x2="31" y1="37.0146" y2="189.2119" stroke="black" stroke-width="0.5"/>
                <line x1="283.5" x2="283.5" y1="37.0146" y2="189.2119" stroke="black" stroke-width="0.5"/>
                <line x1="561.5" x2="561.5" y1="37.0146" y2="189.2119" stroke="black" stroke-width="0.5"/>
                <rect fill="white" height="31.0146" rx="2.5" ry="2.5" width="53" x="5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="12" y="26.0752">Client</text>
                <rect fill="white" height="31.0146" rx="2.5" ry="2.5" width="53" x="5" y="188.2119" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="12" y="209.2871">Client</text>
                <rect fill="white" height="31.0146" rx="2.5" ry="2.5" width="84" x="241.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="248.5" y="26.0752">Service UI</text>
                <rect fill="white" height="31.0146" rx="2.5" ry="2.5" width="84" x="241.5" y="188.2119" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="248.5" y="209.2871">Service UI</text>
                <rect fill="white" height="31.0146" rx="2.5" ry="2.5" width="74" x="524.5" y="5" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="531.5" y="26.0752">Resolver</text>
                <rect fill="white" height="31.0146" rx="2.5" ry="2.5" width="74" x="524.5" y="188.2119" stroke="black" stroke-width="0.5"/>
                <text fill="black" font-family="sans-serif" font-size="14" x="531.5" y="209.2871">Resolver</text>
                <polygon fill="black" points="549.5,64.814,559.5,68.814,549.5,72.814,553.5,68.814" stroke="black" stroke-width="1.0"/>
                <line x1="283.5" x2="555.5" y1="68.814" y2="68.814" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="290.5" y="64.0845">Register Preferred Service + Signature</text>
                <polygon fill="black" points="549.5,94.6133,559.5,98.6133,549.5,102.6133,553.5,98.6133" stroke="black" stroke-width="1.0"/>
                <line x1="31.5" x2="555.5" y1="98.6133" y2="98.6133" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="38.5" y="93.8838">Query PN/UserID</text>
                <polygon fill="black" points="42.5,124.4126,32.5,128.4126,42.5,132.4126,38.5,128.4126" stroke="black" stroke-width="1.0"/>
                <line x1="36.5" x2="560.5" y1="128.4126" y2="128.4126" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="48.5" y="123.6831">Return supported service IDs + default service preference + signature</text>
                <line x1="31.5" x2="73.5" y1="158.2119" y2="158.2119" stroke="black" stroke-width="1.0"/>
                <line x1="73.5" x2="73.5" y1="158.2119" y2="171.2119" stroke="black" stroke-width="1.0"/>
                <line x1="32.5" x2="73.5" y1="171.2119" y2="171.2119" stroke="black" stroke-width="1.0"/>
                <polygon fill="black" points="42.5,167.2119,32.5,171.2119,42.5,175.2119,38.5,171.2119" stroke="black" stroke-width="1.0"/>
                <text fill="black" font-family="sans-serif" font-size="13" x="38.5" y="153.4824">Verify default service pref signature</text>
                <!--SRC=[ROqn2uCm48Nt_8h3jKZt3eB6nQLenUv1Jmb837U9uB_lAMsnqEdWU- - -vmq5srjlN00zMvHZ67BbJpnfaLRR8tHLigV5J_f0NkOLQK-qKaMQwPl0oN8GM1EEI8G3V2GNQEtaJ8Y4AZ_AJKJQeBvVEqQgIgNJBDyLKd70qVk5WWZuBQXA5ic0eubp-59_3A4x5lYy8AudaXstlp-dxWi0]-->
  </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[     ┌──────┐                                 ┌──────────┐                             ┌────────┐
     │Client│                                 │Service UI│                             │Resolver│
     └──┬───┘                                 └────┬─────┘                             └───┬────┘
        │                                          │ Register Preferred Service + Signature│     
        │                                          │ ──────────────────────────────────────>     
        │                                          │                                       │     
        │                                  Query PN/UserID                                 │     
        │ ─────────────────────────────────────────────────────────────────────────────────>     
        │                                          │                                       │     
        │       Return supported service IDs + default service preference + signature      │     
        │ <─────────────────────────────────────────────────────────────────────────────────     
        │                                          │                                       │     
        │────┐                                                                             │     
        │    │ Verify default service pref signature                                       │     
        │<───┘                                                                             │     
     ┌──┴───┐                                 ┌────┴─────┐                             ┌───┴────┐
     │Client│                                 │Service UI│                             │Resolver│
     └──────┘                                 └──────────┘                             └────────┘
]]></artwork>
        </artset>
      </section>
      <section anchor="cross-service-identity-spoofing">
        <name>Cross-service identity spoofing</name>
        <t>Today, a messaging service may support one or more ways of identifying a user including email address, phone number, or service specific user name.</t>
        <t>Messaging interoperability introduces a new problem that traditionally has been resolvable at the service level: cross-service identity spoofing, where a user on a given E2EE may or may not be addressable at the same ID on another service due to a lack of global uniqueness constraints across providers.</t>
        <t>As a result, a user may be registered at multiple services with the same handles, e.g. if Bob's email is <eref target="mailto:bob@example.com">bob@example.com</eref> and his phone number is 555-111-2222 and he is registered with Signal and iMessage, he would be addressable at <eref target="mailto:bob@example.com">bob@example.com</eref>:iMessage, 555-111-2222:iMessage, and 555-111-2222:Signal. In this case, the same userId on iMessage and Signal is acceptable as the phone number can map to only one individual who proves their identity by validating ownership of the SIM card.</t>
        <t>On services where a user can log in with a username <em>alone</em>, however e.g. Threema and FooService, the challenge becomes:</t>
        <ul spacing="normal">
          <li>
            <t>Alice messages Bob at Bob's preferred service (bob@Threema)</t>
          </li>
          <li>
            <t>Eve messages Alice impersonating Bob using bob@FooService</t>
          </li>
          <li>
            <t>Alice needs some indicator or UI to know that bob@Threema isn't bob@FooSercice and that when bob@FooService messages, it should not be assumed that bob@FooService is bob@Threema.</t>
          </li>
        </ul>
        <t>Options for solving this are:
1. Storing the supported services for a contact in Contacts and if a recipient receives a message from an unknown sender, to treat it as spam or otherwise untrusted from the start.
2. Requiring the fully qualified username for services that rely on usernames only - e.g. bob@threema.com vs bob.</t>
      </section>
    </section>
    <section anchor="privacy-of-resolver-lookup-queries">
      <name>Privacy of resolver lookup queries</name>
      <t>Resolver lookup queries leak the user's social graph - i.e. who is communicating with whom, since the IP address of the querying client can be tied to user identity, especially when operating over a mobile data network. Therefore we propose to use Private Information Retrieval (PIR) to perform the resolver queries. We have evaluated multiple alternative schemes. The proposed solution is based on the Public Key PIR framework by Patel et al<xref target="PIRFramework"/> with sharded databases. This framework is applicable with any standard PIR scheme such as the open source implementation <eref target="https://github.com/google/private-retrieval">here</eref>. Cost estimates suggest this is feasible even for very large resolver databases (10 billion records).</t>
      <section anchor="proposed-protocols">
        <name>Proposed protocols</name>
        <t>A private information retrieval protocol enables a client holding an index (or keyword) to retrieve the database record corresponding to that index from a remote server. PIR schemes have communication complexities sublinear in the database size and they provide access privacy for clients which precludes the server from being able to learn any information about either the query index or the record retrieved. A standard single-server PIR scheme provides clients with algorithms to generate a query and decrypt a response from the server. It also provides an algorithm for the server to compute a response.</t>
        <t>The Public Key PIR framework <xref target="PIRFramework"/> can be wrapped around any standard lattice-based PIR scheme. This framework consists of server database setup, client key initialization, client query generation, server response computation, and client response decryption sub-protocols. All operations are over a set of integers with a plaintext modulus. The appendix provides the protocol messages in protocol buffer format.</t>
        <section anchor="server-database-setup">
          <name>Server database setup</name>
          <ul spacing="normal">
            <li>
              <t><strong>Sharding</strong>: If the database is over 2<sup>20</sup> records, sub-divide it into  shards of ~1 million unique records each, which is a good balance for privacy and costs. Performing PIR over the databases gives stronger privacy but is more costly. Similarly, running PIR queries over the shards is less costly but gives weaker privacy.
              </t>
              <ul spacing="normal">
                <li>
                  <t>Sample a hash key <strong>K<sub>s</sub></strong> for sharding.</t>
                </li>
                <li>
                  <t>Using <strong>K<sub>s</sub></strong>, shard the large database of <strong>r</strong> records into <strong>⌈r/2<sup>20</sup>⌉</strong> shards based on the hash prefix of the record's unique identifier.</t>
                </li>
                <li>
                  <t><strong>N.B.</strong> The hash key will be provided to clients to determine the shard to query.</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Set partitioning boundaries for each shard D</strong>: Given a <strong>n</strong> key-value pairs shard <strong>D = {(k<sub>1</sub>,v<sub>1</sub>),...,(k<sub>n</sub>,v<sub>n</sub>)}</strong>, then
              </t>
              <ul spacing="normal">
                <li>
                  <t>Compute the number of database partitions as <strong>b = n/d<sub>1</sub></strong>. Where <strong>d<sub>1</sub></strong> is the desired size for each partition. A value of 128 for <strong>d<sub>1</sub></strong> works well.</t>
                </li>
                <li>
                  <t>Sample a partitioning boundary hash key <strong>K<sub>1 </sub></strong> to generate a target partition for each shard key.</t>
                </li>
                <li>
                  <t>Compute the hash <strong>F<sub>1</sub>(K<sub>1</sub>,k<sub>i</sub>)</strong> for each record identifier <strong>k<sub>i</sub></strong>.</t>
                </li>
                <li>
                  <t>Sort the hash values alphanumerically and then divide the list into <strong>b</strong> partitions <strong>P<sub>1</sub>,...,P<sub>b</sub></strong>.</t>
                </li>
                <li>
                  <t>Store the b partition boundaries beginning hash values <strong>B<sub>0</sub>, ..., B<sub>b</sub></strong>. Note that <strong>B<sub>0</sub> = 0</strong>, and <strong>B<sub>b</sub> = |U|-1</strong> where U is the rage for <strong>F<sub>1</sub>(K<sub>1</sub>,k<sub>i</sub>)</strong>.</t>
                </li>
                <li>
                  <t><strong>N.B.</strong> The partition boundaries will be provided to clients and can be stored efficiently (e.g., ~11KB for <strong>n</strong> = 2<sup><strong>20</strong></sup>, <strong>d<sub>1</sub></strong> = 128, <strong>|U|</strong> = 2<sup><strong>64</strong></sup>).</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Transform each shard</strong>: Sample two hash keys <strong>K<sub>2</sub></strong> and <strong>K<sub>r</sub></strong> where <strong>K<sub>2</sub></strong> will be used to generate a row vector within each partition, and <strong>K<sub>r</sub></strong> is used to generate a representation for the transformed database as <strong>F(K<sub>r</sub>,k<sub>i</sub>)||v</strong>.</t>
            </li>
            <li>
              <t><strong>N.B.</strong> <strong>F(K,k)</strong> is the output value from hashing <strong>k</strong> with key <strong>K</strong> and <strong>||</strong> is a concatenation.</t>
            </li>
            <li>
              <t>For each partition <strong>P<sub>i</sub></strong>
              </t>
              <ul spacing="normal">
                <li>
                  <t>Construct a <strong>|P<sub>i</sub>| x d<sub>1</sub></strong> Platform1 <strong>M<sub>i</sub></strong> by appending a random row vector from the bit vector derived from <strong>(F<sub>2</sub>(K<sub>2</sub>,k||1),...,F<sub>2</sub>(K<sub>2</sub>,k||d<sub>1</sub>))</strong>.</t>
                </li>
                <li>
                  <t>Construct a <strong>|P<sub>i</sub>|</strong> vector <strong>y<sub>i</sub></strong> by appending <strong>F<sub>r</sub>(K<sub>r</sub>,k)||v</strong> for each <strong>(k,v)</strong> in <strong>P<sub>i</sub></strong>.</t>
                </li>
                <li>
                  <t>Solve for <strong>e<sub>i</sub></strong> that satisfies <strong>M<sub>i</sub>e<sub>i</sub> = y<sub>i</sub></strong>.</t>
                </li>
              </ul>
            </li>
            <li>
              <t>Construct the transformed <strong>d<sub>1</sub> x b</strong> Platform1 as <strong>E = [e<sub>1</sub> … e<sub>b</sub>]</strong>.</t>
            </li>
            <li>
              <t>The Platform1 <strong>E</strong> is the transformed Platform1 for shard <strong>D</strong>.</t>
            </li>
            <li>
              <t>The clients must download parameters <strong>(K<sub>1</sub>,K<sub>2</sub>,K<sub>r</sub>)</strong> to query each shard, plus <strong>K<sub>s</sub></strong> to inform the server of the target shard for a query.</t>
            </li>
          </ul>
          <t>This protocol is completed by the server without any client participation and before answering any client query. Note that a shard must be re-transformed after an update. Shard transform only takes a few minutes.</t>
        </section>
        <section anchor="client-key-initialization">
          <name>Client key initialization</name>
          <ul spacing="normal">
            <li>
              <t>The client generates a per-key unique identifier (<strong>UID</strong>),  <strong>private key</strong> and <strong>public key</strong> using a fully homomorphic encryption (FHE) scheme relying on hardness assumptions similar to Ring Learning with Errors problem.</t>
            </li>
            <li>
              <t>The client persists the <strong>UID</strong> and <strong>private key</strong> into its local key store, and uploads query-independent parameters <strong>UID</strong> and <strong>public key</strong> to the server. These later parameters will enable the server to perform cryptographic operations (i.e., FHE) efficiently.</t>
            </li>
            <li>
              <t>The server needs to maintain an up-to-date mapping of <strong>UID</strong> to <strong>public key</strong> for all clients.</t>
            </li>
            <li>
              <t>Each client completes this offline initialization protocol before running any query. It also needs to perform it periodically (e.g., weekly or monthly) to prevent server linkability of private queries to the user over an extended period.</t>
            </li>
            <li>
              <t>The client downloads query parameters from the server:
              </t>
              <ul spacing="normal">
                <li>
                  <t>Sharding hash key <strong>K<sub>s</sub></strong> to inform the server of the target shard for a query.</t>
                </li>
              </ul>
            </li>
            <li>
              <t>Sets of parameters (<strong>K<sub>1</sub>,K<sub>2</sub>,K<sub>r</sub>,B<sub>0</sub>, …, B<sub>b</sub></strong>) for each shard.</t>
            </li>
          </ul>
        </section>
        <section anchor="client-query-generation">
          <name>Client query generation</name>
          <ul spacing="normal">
            <li>
              <t>The client creates a query to retrieve the value corresponding to a database key <strong>k</strong> as follows:</t>
            </li>
            <li>
              <t>Select a standard PIR algorithm with server-supported implementation as the underlying PIR scheme.</t>
            </li>
            <li>
              <t>Compute <strong>d = F<sub>s</sub>(K<sub>s</sub>,k)</strong> to identify the shard to query.</t>
            </li>
            <li>
              <t>Compute <strong>j = F<sub>1</sub>(K<sub>1</sub>,k)</strong> to learn which partition contains the desired entry from the downloaded partition boundaries for the shard.</t>
            </li>
            <li>
              <t>Generate <strong>z</strong> vector <strong>v</strong> of length <strong>d<sub>1</sub> , … , d<sub>z</sub></strong> . Compute a <strong>d<sub>1</sub></strong>-length random bit vector <strong>v<sub>1</sub></strong> from <strong>(F<sub>2</sub>(K<sub>2</sub>,k||1),...,F<sub>2</sub>(K<sub>2</sub>,k||d<sub>1</sub>))</strong>. Compute <strong>v<sub>2</sub></strong> as a zero bit vector of <strong>d<sub>2</sub></strong> length with only the bit set at <strong>⌊j/⌈n/d<sub>1</sub>d<sub>2</sub>⌉⌋</strong>. Similarly compute <strong>v<sub>3</sub> , … , v<sub>z</sub></strong>.</t>
            </li>
            <li>
              <t>Finally use the underlying PIR scheme and the private key to encrypt the <strong>z</strong> vector <strong>v.</strong></t>
            </li>
            <li>
              <t>Send <strong>v, d</strong> and the <strong>UID</strong> to the server.</t>
            </li>
            <li>
              <t><strong>N.B.</strong> The dimension <strong>d<sub>z</sub></strong> is typically small; a size of 2 or 4 works well.</t>
            </li>
          </ul>
        </section>
        <section anchor="server-response-computation">
          <name>Server response computation</name>
          <ul spacing="normal">
            <li>
              <t>The server retrieves the public key for the client's <strong>UID</strong>, and computes the ciphertext of the value corresponding to the key of interest for the shard <strong>d</strong>, as follows.</t>
            </li>
            <li>
              <t>Take the transformed shard <strong>E</strong> as a <strong>d<sub>1 </sub>x ⌈n/d<sub>1</sub>⌉</strong> Platform1 <strong>E<sub>1</sub></strong>, use the underlying PIR response answering algorithm to compute <strong>v<sub>1</sub>.E<sub>1</sub></strong>, and rearrange the resulting <strong>⌈n/d<sub>1</sub>⌉</strong> vector as a <strong>d<sub>2 </sub>x ⌈n/d<sub>1</sub>d<sub>2</sub>⌉</strong> Platform1 <strong>E<sub>2</sub></strong>.</t>
            </li>
            <li>
              <t>Next, compute <strong>v<sub>2</sub>.E<sub>2</sub></strong>, and rearrange the resulting <strong>⌈n/d<sub>1</sub>d<sub>2</sub>⌉</strong> vector as a <strong>d<sub>3 </sub>x ⌈n/d<sub>1</sub>d<sub>2</sub>d<sub>3</sub>⌉</strong> Platform1 <strong>E<sub>3</sub></strong>.</t>
            </li>
            <li>
              <t>The server similarly repeats the computation for the remaining dimensions <strong>v<sub>3</sub> ,… , v<sub>z</sub></strong>.</t>
            </li>
            <li>
              <t>The end result is a ciphertext <strong>r</strong> of the database value corresponding to <strong>k</strong>. The server sends <strong>r</strong> back to the client.</t>
            </li>
          </ul>
        </section>
        <section anchor="client-response-decryption">
          <name>Client response decryption</name>
          <ul spacing="normal">
            <li>
              <t>The client uses the underlying PIR response decryption algorithm and <strong>private key</strong> to decrypt the response <strong>r</strong> as <strong>k<sub>r</sub>||v</strong>. If <strong>F<sub>r</sub>(K<sub>r</sub>,k) == k<sub>r</sub></strong> then returns <strong>v</strong> otherwise returns <strong>null</strong> (key not found).</t>
            </li>
          </ul>
        </section>
      </section>
      <section anchor="fhe-key-requirements">
        <name>FHE key requirements</name>
        <ul spacing="normal">
          <li>
            <t>At least 128-bit of security
            </t>
            <ul spacing="normal">
              <li>
                <t>ElGamal, NIST P-224r1 curve and a 4 bytes plaintext size for fast decryption.</t>
              </li>
              <li>
                <t>Gentry-Ramzan, used a 2048-bit modulus</t>
              </li>
              <li>
                <t>Damgård-Jurik, used 1160-bit primes</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="cost-estimates">
        <name>Cost estimates</name>
        <t>In these estimates, we propose using shards of size ~1 million of identifiers. For 1.28 TB (10 billion records), breaking this down into 10,000 shards each of size 1 million records gives a cost estimate for each query as below:</t>
        <table>
          <thead>
            <tr>
              <th align="left">Parameter</th>
              <th align="left">Cost estimate</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">PIR Public Key Size Per Device, including metadata (storage required)</td>
              <td align="left">14 MB</td>
            </tr>
            <tr>
              <td align="left">Upload Bandwidth Per Query</td>
              <td align="left">14 KB</td>
            </tr>
            <tr>
              <td align="left">Download Bandwidth Per Query</td>
              <td align="left">21 KB</td>
            </tr>
            <tr>
              <td align="left">Client Time Per Query</td>
              <td align="left">0.1s</td>
            </tr>
            <tr>
              <td align="left">Server Time Per Query (Single Thread)</td>
              <td align="left">0.8-1s</td>
            </tr>
          </tbody>
        </table>
        <t>Note on some assumptions for feasibility:</t>
        <ol spacing="normal" type="1"><li>
            <t>Resolver queries will be cached (vs requiring a roundtrip for every message) and asynchronous with message sending, therefore 1s latency is acceptable.</t>
          </li>
          <li>
            <t>It is acceptable for key changes to be communicated reactively on decrypt failure.</t>
          </li>
          <li>
            <t>Group messaging E2EE is bootstrapped using individual users' public keys and for V1, group state will be stored by the initiating user's service provider. Therefore no additional discovery mechanism is required.</t>
          </li>
        </ol>
      </section>
      <section anchor="notes">
        <name>Notes</name>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
      <section anchor="appendix">
        <name>Appendix</name>
        <t>The protocol messages are specified in protobuffer format in this appendix.</t>
        <sourcecode type="protobuf"><![CDATA[
syntax = "proto3";

package mimi.discovery.pir;

// PirParameterRequest represents a request from a client to a server to
// fetch database and cryptographic parameters for querying a database.

message PirParameterRequest {
  // The protocol version for PIR.
  uint32 protocol_version = 1;

  // Used to prevent replays; request fingerprint.
  string nonce = 2;

  // The unique identifier of the client.
  string uid = 3;

  // The PIR scheme that the client wants to use.
  PirScheme pir_scheme = 4;

  // The public key of the client.
  repeated bytes public_key = 5;
}

// PirParameterResponse represents a server's response to PirParameterRequest
// and it contains database and cryptographic parameters to use for querying the
// database using PIR.

message PirParameterResponse {
  // The protocol version for PIR.
  uint32 protocol_version = 1;

  // Used to prevent replays; request fingerprint.
  string nonce = 2;

  // The unique identifier of the client.
  string uid = 3;

  // Status of the request.
  PirStatus response_status = 4;

  // The PIR scheme negotiated from the client request.
  optional PirScheme pir_scheme = 5;

  // A map of server-supported PIR schemes to their parameters.
  map<PirScheme, PirParams> pir_schemes = 6;

  // The shard hash key to identify subdatabase containing a keyword.
  HashKey shard_key = 7;

  // parameters for sub databases
  repeated PirSubDbParameter sub_db_param = 8;
}

// PirSubDbParameter represents a subdatabase partitioning parameters

message PirSubDbParameter {
  // The hash key of the partition boundary.
  HashKey partion_boundary_hash_key = 1;

  // The hash key of the row vector.
  HashKey row_vector_hash_key = 2;

  // The hash key of the record representation.
  HashKey record_representation_hash_key = 3;

  // The beginning hash values for the partition
  // boundaries for a single shard.
  repeated PartitionBoundaries partition_boundaries = 4;

  // The size of the database.
  uint32 database_size = 5;

  // The size of the largest record.
  uint32 record_size = 6;
}

// PirRequest represents a sparse PIR request to a server for retrieving a
// database record.

message PirRequest {
  // The protocol version for PIR.
  uint32 protocol_version = 1;

  // Used to prevent replays; request fingerprint.
  string nonce = 2;

  // The unique identifier of the client.
  string uid = 3;

  // The PIR scheme that the client wants to use.
  optional PirScheme pir_scheme = 4;

  // The shard ID of the record to be retrieved.
  uint32 shard = 5;

  // The encrypted vector of the query.
  repeated bytes encrypted_vector = 6;
}

// PirResponse represents a PIR server's response to a PirRequest.

message PirResponse {
  // The protocol version for PIR.
  uint32 protocol_version = 1;

  // Used to prevent replays; request fingerprint.
  string nonce = 2;

  // The unique identifier of the client.
  string uid = 3;

  // Status of the request.
  PirStatus response_status = 4;

  // The encrypted response.
  repeated bytes encrypted_response = 5;
}

// PartitionBoundaries represents the beginning hash values for the partition
// boundaries for a single shard.

message PartitionBoundaries {
  // The hash values of the partition boundaries.
  repeated string boundary = 1;
}

// HashKey represents a cryptographic hash key.

message HashKey {
  // The hash key.
  repeated bytes hash_key = 1;
}

// PirParams represents the parameters of a PIR scheme instance.

message PirParams {
  // The number of levels of recursion used in the PIR scheme.
  optional int32 levels_of_recursion = 1;

  // The modulus used in the PIR scheme.
  repeated bytes modulus = 2;

  // The plaintext modulus used in the PIR scheme.
  repeated bytes plaintext_modulus = 3;

  // Other parameters used in the specific PIR scheme.
  repeated bytes other_params = 4;

  // Reserved values.
  reserved 5, 6, 7;
}

// PirScheme represents an indexed-based PIR scheme .

enum PirScheme {
  // Scheme not specified
  PIR_SCHEME_UNSPECIFIED = 0;

  // XPIR scheme based on the Ring Learning with Errors (Ring-LWE) problem.
  PIR_SCHEME_RLWE_XPIR = 1;

  // Add more PIR schemes that we might want to support.
}

// PirStatus represents the PIR server response codes.

enum PirStatus {
  // The PIR scheme selected by the client is supported.
  PIR_SCHEME_MATCHED = 0;

  // The PIR scheme selected by the client is not supported, but the server
  // suggests a list of supported schemes.
  PIR_SCHEME_SUGGESTED = 1;

  // There are problems with the request.
  PIR_REQUEST_FAILURE = 2;

  // The response was successfully computed from the request.
  PIR_RESPONSE_SUCCESS = 3;

  // The response computation failed.
  PIR_RESPONSE_FAILURE = 4;
}
]]></sourcecode>
      </section>
    </section>
  </middle>
  <back>
    <references anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="PIRFramework">
        <front>
          <title>Don't be Dense: Efficient Keyword PIR for Sparse Databases</title>
          <author fullname="Sarvar Patel">
            <organization/>
          </author>
          <author fullname="Joon Young Seo">
            <organization/>
          </author>
          <author fullname="Kevin Yeo">
            <organization/>
          </author>
          <date>n.d.</date>
        </front>
        <seriesInfo name="32nd USENIX Security Symposium, USENIX Security 2023" value=""/>
      </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>
    </references>
    <?line 550?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The technical description of the private information retrieval framework is based on Sarvar Patel, Joon Young Seo and Kevin Yeo's USENIX Security '23 paper titled <eref target="https://www.usenix.org/conference/usenixsecurity23/presentation/patel">"Don't be Dense: Efficient Keyword PIR for Sparse Databases
"</eref>.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
U3OMNHyy66czuyvcBp5M/Q9VA3mgoG0AAA==

-->

</rfc>
