<?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-01" 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-01"/>
    <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="09"/>
    <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</text>
                <text fill="black" font-family="sans-serif" font-size="13" x="178" y="422.0889">Key Bundle</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=[VP0zQyCm48Pt_OeZGvSsb7RC4F1N88G6rwQR5zMwfWBdf9uaG_vzPP6IDWxTX9xdFRqdAzdhNbj97XRrKqTG31h9Bq0wo8ITuGsRUAv89IE_OUpb4Q557f6JK_nrik0_3MillHuHwkUEhWFbrT2emAvi4wlcx5VXZH35SbskeC6lWCvVnZVO6rPEbCjrCM4xw5vwd0lPSfsleDusy1gGJntL-yStXxmjHPwoDn6PECl41Q1uY9y2q0Ph3NjK48LHzmZRqiLxk0U57p8C_WS890LJVgeUdsulVaTtCpkMg5Rp0bNADkW34zJXFQxNqGvFa0TIGufb__4iyOfwFbaFB-YSFAJRpTGeDZoZkD0PmgWb7DDPqm4icr4hP2U-0G00]-->
  </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         │                     │                │    
         │                   │ <─────────────────────────────────────────────────────────────────────                │    
         │                   │                      │                         │                     │                │    
         │   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 receipt 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 paramaters to use for quering 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 paramaeters.
  map<PirScheme, PirParams> pir_schemes = 6;

  // The shard hash key to identify subdatabase cointaining 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 PatitionBundaries 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;
}

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

message PatitionBundaries {
  // 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 paramaters 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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
ss9P7VnS8Ol+mNLsr3AbeDz1fwHnHw9chW0AAA==

-->

</rfc>
