<?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.23 (Ruby 3.3.6) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-yun-cfrg-arc-00" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.26.0 -->
  <front>
    <title abbrev="ARC">Anonymous Rate-Limited Credentials</title>
    <seriesInfo name="Internet-Draft" value="draft-yun-cfrg-arc-00"/>
    <author initials="C." surname="Yun" fullname="Cathie Yun">
      <organization>Apple, Inc.</organization>
      <address>
        <email>cathie@apple.com</email>
      </address>
    </author>
    <author initials="C. A." surname="Wood" fullname="Christopher A. Wood">
      <organization>Apple, Inc.</organization>
      <address>
        <email>caw@heapingbits.net</email>
      </address>
    </author>
    <date year="2025" month="February" day="05"/>
    <abstract>
      <?line 55?>

<t>This document specifies the Anonymous Rate-Limited Credential (ARC) protocol,
a specialization of keyed-verification anonymous credentials with support for
rate limiting. ARC credentials can be presented from client to server up to
some fixed number of times, where each presentation is cryptographically bound
to client secrets and application-specific public information, such that each
presentation is unlinkable from the others as well as the original credential
creation. ARC is useful in applications where a server needs to throttle or
rate-limit access from anonymous clients.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://chris-wood.github.io/draft-arc/draft-yun-cfrg-arc.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-yun-cfrg-arc/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Crypto Forum  mailing list (<eref target="mailto:cfrg@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/cfrg"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/cfrg/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/chris-wood/draft-arc"/>.</t>
    </note>
  </front>
  <middle>
    <?line 66?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>This document specifies the Anonymous Rate-Limited Credential (ARC) protocol,
a specialization of keyed-verification anonymous credentials with support for
rate limiting.</t>
      <t>ARC is privately verifiable (keyed-verification), yet differs from similar token-based
protocols in that each credential can be presented multiple times without violating
unlinkability of different presentations. Servers issue credentials to clients that
are cryptographically bound to client secrets and some public information.
Afterwards, clients can present this credential to the server up to some fixed
number of times, where each presentation provides proof that it was derived
from a valid (previously issued) credential and bound to some public information.
Each presentation is pairwise unlinkable, meaning the server cannot link any two
presentations to the same client credential, nor can the server link a presentation
to the preceding credential issuance flow. Notably, the maximum number of
presentations from a credential is fixed by the application.</t>
      <t>ARC is useful in settings where applications require a fixed number of zero-knowledge
proofs about client secrets that can also be cryptographically bound to some public
information. This capability lets servers use credentials in applications that need
throttled or rate-limited access from anonymous clients.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <section anchor="notation-and-terminology">
        <name>Notation and Terminology</name>
        <t>The following functions and notation are used throughout the document.</t>
        <ul spacing="normal">
          <li>
            <t>concat(x0, ..., xN): Concatenation of byte strings. For example,
concat(0x01, 0x0203, 0x040506) = 0x010203040506.</t>
          </li>
          <li>
            <t>bytes_to_int and int_to_bytes: Convert a byte string to and from a non-negative integer.
bytes_to_int and int_to_bytes are implemented as OS2IP and I2OSP as described in
<xref target="RFC8017"/>, respectively. Note that these functions operate on byte strings
in big-endian byte order.</t>
          </li>
          <li>
            <t>random_integer_uniform(M, N): Generate a random, uniformly distributed integer R
between M inclusive and N exclusive, i.e., M &lt;= R &lt; N.</t>
          </li>
          <li>
            <t>random_integer_uniform_excluding_set(M, N, S): Generate a random, uniformly
distributed integer R between M inclusive and N exclusive, i.e., M &lt;= R &lt; N,
such that R does not exist in the set of integers S.</t>
          </li>
        </ul>
        <t>All algorithms and procedures described in this document are laid out
in a Python-like pseudocode. Each function takes a set of inputs and parameters
and produces a set of output values. Parameters become constant values once the
protocol variant and the ciphersuite are fixed.</t>
        <t>The notation <tt>T U[N]</tt> refers to an array called U containing N items of type
T. The type <tt>opaque</tt> means one single byte of uninterpreted data. Items of
the array are zero-indexed and referred as <tt>U[j]</tt> such that 0 &lt;= j &lt; N.
The notation <tt>{T}</tt> refers to a set consisting of elements of type <tt>T</tt>.
For any object <tt>x</tt>, we write <tt>len(x)</tt> to denote its length in bytes.</t>
        <t>String values such as "CredentialRequest", "CredentialResponse", "Presentation", and "Tag"
are ASCII string literals.</t>
        <t>The following terms are used throughout this document.</t>
        <ul spacing="normal">
          <li>
            <t>Client: Protocol initiator. Creates a credential request, and uses the
corresponding server response to make a credential. The client can
make multiple presentations of this credential.</t>
          </li>
          <li>
            <t>Server: Computes a response to a credential request, with its
server private keys. Later the server can verify the client's presentations
with its private keys. Learns nothing about the client's secret attributes,
and cannot link a client's request/response and presentation steps.</t>
          </li>
        </ul>
        <!-- TODO(caw): define these terms:
- tag
- attribute
- requestContext
- presentationContext
- presentationLimit
- presentation
-->

</section>
    </section>
    <section anchor="preliminaries">
      <name>Preliminaries</name>
      <t>The construction in this document has one primary dependency:</t>
      <ul spacing="normal">
        <li>
          <t><tt>Group</tt>: A prime-order group implementing the API described below in <xref target="pog"/>.
See <xref target="ciphersuites"/> for specific instances of groups.</t>
        </li>
      </ul>
      <section anchor="pog">
        <name>Prime-Order Group</name>
        <t>In this document, we assume the construction of an additive, prime-order
group <tt>Group</tt> for performing all mathematical operations. In prime-order groups,
any element (other than the identity) can generate the other elements of the
group. Usually, one element is fixed and defined as the group generator.
In the ARC setting, there are two fixed generator elements (generatorG, generatorH).
Such groups are uniquely determined by the choice of the prime <tt>p</tt> that defines the
order of the group. (There may, however, exist different representations
of the group for a single <tt>p</tt>. <xref target="ciphersuites"/> lists specific groups which
indicate both order and representation.)</t>
        <t>The fundamental group operation is addition <tt>+</tt> with identity element
<tt>I</tt>. For any elements <tt>A</tt> and <tt>B</tt> of the group, <tt>A + B = B + A</tt> is
also a member of the group. Also, for any <tt>A</tt> in the group, there exists an element
<tt>-A</tt> such that <tt>A + (-A) = (-A) + A = I</tt>. Scalar multiplication by <tt>r</tt> is
equivalent to the repeated application of the group operation on an
element A with itself <tt>r-1</tt> times, this is denoted as <tt>r*A = A + ... + A</tt>.
For any element <tt>A</tt>, <tt>p*A=I</tt>. The case when the scalar multiplication is
performed on the group generator is denoted as <tt>ScalarMultGen(r)</tt>.
Given two elements A and B, the discrete logarithm problem is to find
an integer k such that B = k*A. Thus, k is the discrete logarithm of
B with respect to the base A.
The set of scalars corresponds to <tt>GF(p)</tt>, a prime field of order p, and are
represented as the set of integers defined by <tt>{0, 1, ..., p-1}</tt>.
This document uses types
<tt>Element</tt> and <tt>Scalar</tt> to denote elements of the group and its set of
scalars, respectively.</t>
        <t>We now detail a number of member functions that can be invoked on a
prime-order group.</t>
        <ul spacing="normal">
          <li>
            <t>Order(): Outputs the order of the group (i.e. <tt>p</tt>).</t>
          </li>
          <li>
            <t>Identity(): Outputs the identity element of the group (i.e. <tt>I</tt>).</t>
          </li>
          <li>
            <t>Generator(): Outputs the fixed generator of the group.</t>
          </li>
          <li>
            <t>HashToGroup(x, info): Deterministically maps
an array of bytes <tt>x</tt> with domain separation value <tt>info</tt> to an element of <tt>Group</tt>. The map must ensure that,
for any adversary receiving <tt>R = HashToGroup(x, info)</tt>, it is
computationally difficult to reverse the mapping.
Security properties of this function are described
in <xref target="I-D.irtf-cfrg-hash-to-curve"/>.</t>
          </li>
          <li>
            <t>HashToScalar(x, info): Deterministically maps
an array of bytes <tt>x</tt> with domain separation value <tt>info</tt> to an element in GF(p).
Security properties of this function are described in <xref section="10.5" sectionFormat="comma" target="I-D.irtf-cfrg-hash-to-curve"/>.</t>
          </li>
          <li>
            <t>RandomScalar(): Chooses at random a non-zero element in GF(p).</t>
          </li>
          <li>
            <t>ScalarInverse(s): Returns the inverse of input <tt>Scalar</tt> <tt>s</tt> on <tt>GF(p)</tt>.</t>
          </li>
          <li>
            <t>SerializeElement(A): Maps an <tt>Element</tt> <tt>A</tt>
to a canonical byte array <tt>buf</tt> of fixed length <tt>Ne</tt>.</t>
          </li>
          <li>
            <t>DeserializeElement(buf): Attempts to map a byte array <tt>buf</tt> to
an <tt>Element</tt> <tt>A</tt>, and fails if the input is not the valid canonical byte
representation of an element of the group. This function can raise a
DeserializeError if deserialization fails or <tt>A</tt> is the identity element of
the group; see <xref target="ciphersuites"/> for group-specific input validation steps.</t>
          </li>
          <li>
            <t>SerializeScalar(s): Maps a <tt>Scalar</tt> <tt>s</tt> to a canonical
byte array <tt>buf</tt> of fixed length <tt>Ns</tt>.</t>
          </li>
          <li>
            <t>DeserializeScalar(buf): Attempts to map a byte array <tt>buf</tt> to a <tt>Scalar</tt> <tt>s</tt>.
This function can raise a DeserializeError if deserialization fails; see
<xref target="ciphersuites"/> for group-specific input validation steps.</t>
          </li>
        </ul>
        <t>For each group, there exists two distinct generators, generatorG and
generatorH, generatorG = G.Generator() and generatorH = G.HashToGroup(G.SerializeElement(generatorG), "generatorH").
The group member functions GeneratorG() and GeneratorH() are shorthand
for returning generatorG and generatorH, respectively.</t>
        <t><xref target="ciphersuites"/> contains details for the implementation of this interface
for different prime-order groups instantiated over elliptic curves.</t>
      </section>
    </section>
    <section anchor="arc-protocol">
      <name>ARC Protocol</name>
      <t>The ARC protocol is a two-party protocol run between client and server
consisting of three distinct phases:</t>
      <ol spacing="normal" type="1"><li>
          <t>Key generation. In this phase, the server generates its private and public
keys to be used for the remaining phases. This phase is described in <xref target="setup"/>.</t>
        </li>
        <li>
          <t>Credential issuance. In this phase, the client and server interact to issue
the client a credential that is cryptographically bound to client secrets.
This phase is described in <xref target="issuance"/>.</t>
        </li>
        <li>
          <t>Presentation. In this phase, the client uses the credential to create a "presentation"
to the server, where the server learns nothing more than whether or not the
presentation is valid and corresponds to some previously issued credential,
without learning which credential it corresponds to. This phase is described
in <xref target="presentation"/>.</t>
        </li>
      </ol>
      <t>This protocol bears resemblance to anonymous token protocols, such as those built on
Blind RSA <xref target="BLIND-RSA"/> and Oblivious Pseudorandom Functions <xref target="OPRFS"/>
with one critical distinction: unlike anonymous tokens, an anonymous credential can be
used multiple times to create unlinkable presentations (up to the fixed presentation
limit). This means that a single issuance invocation can drive multiple presentation
invocations, whereas with anonymous tokens, each presentation invocation requires
exactly one issuance invocation. As a result, credentials are generally longer lived
than tokens. Applications configure the credential presentation limit after the
credential is issued such that client and server agree on the limit during presentation.
Servers are responsible for ensuring this limit is not exceeded. Clients that exceed
the agreed-upon presentation limit break the unlinkability guarantees provided by
the protocol.</t>
      <t>The rest of this section describes the three phases of the ARC protocol.</t>
      <section anchor="setup">
        <name>Key Generation</name>
        <t>In the key generation phase, the server generates its private and public
keys, denoted ServerPrivateKey and ServerPublicKey, as follows.</t>
        <artwork><![CDATA[
Input: None
Output:
- ServerPrivateKey:
  - x0: Scalar
  - x1: Scalar
  - x2: Scalar
  - x0Blinding: Scalar
- ServerPublicKey:
  - X0: Element
  - X1: Element
  - X2: Element

Parameters
- Group G

def SetupServer():
  x0 = G.RandomScalar()
  x1 = G.RandomScalar()
  x2 = G.RandomScalar()
  x0Blinding = G.RandomScalar()
  X0 = x0 * G.GeneratorG() + x0Blinding * G.GeneratorH()
  X1 = x1 * G.GeneratorH()
  X2 = x2 * G.GeneratorH()
  return ServerPrivateKey(x0, x1, x2, x0Blinding), ServerPublicKey(X0, X1, X2)
]]></artwork>
        <t>The server public keys can be serialized as follows:</t>
        <artwork><![CDATA[
struct {
  uint8 X0[Ne]; // G.SerializeElement(X0)
  uint8 X1[Ne]; // G.SerializeElement(X1)
  uint8 X2[Ne]; // G.SerializeElement(X2)
} ServerPublicKey;
]]></artwork>
        <t>The length of this encoded response structure is <tt>NserverPublicKey = 3*Ne</tt>.</t>
      </section>
      <section anchor="issuance">
        <name>Issuance</name>
        <t>The purpose of the issuance phase is for the client and server to cooperatively compute a credential
that is cryptographically bound to the client's secrets. Clients do not choose these secrets;
they are computed by the protocol.</t>
        <t>The issuance phase of the protocol requires clients to know the server public key a priori, as well as
an arbitrary, application-specific request context. It requires no other input. It consists of three
distinct steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>The client generates and sends a credential request to the server. This credential request contains a
proof that the request is valid with respect to the client's secrets and request context. See
<xref target="issuance-step1"/> for details about this step.</t>
          </li>
          <li>
            <t>The server validates the credential request. If valid, it computes a credential response with the server
private keys. The response includes a proof that the credential response is valid with respect to the
server keys. The server sends the response to the client. See <xref target="issuance-step2"/> for details about this
step.</t>
          </li>
          <li>
            <t>The client finalizes the credential by processing the server response. If valid, this step yields a
credential that can then be used in the presentation phase of the protocol. See <xref target="issuance-step3"/> for
details about this step.</t>
          </li>
        </ol>
        <t>Each of these steps are described in the following subsections.</t>
        <section anchor="issuance-step1">
          <name>Credential Request</name>
          <t>Given a request context, the process for creating a credential request is as follows:</t>
          <artwork><![CDATA[
(clientSecrets, request) = CredentialRequest(requestContext)

Inputs:
- requestContext: Data, context for the credential request

Outputs:
- request:
  - m1Enc: Element, first encrypted secret.
  - m2Enc: Element, second encrypted secret.
  - requestProof: ZKProof, a proof of correct generation of m1Enc and m2Enc.
- clientSecrets:
  - m1: Scalar, first secret.
  - m2: Scalar, second secret.
  - r1: Scalar, blinding factor for first secret.
  - r2: Scalar, blinding factor for second secret.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

def CredentialRequest(requestContext):
  m1 = G.RandomScalar()
  m2 = G.HashToScalar(requestContext, "requestContext")
  r1 = G.RandomScalar()
  r2 = G.RandomScalar()
  m1Enc = m1 * generatorG + r1 * generatorH
  m2Enc = m2 * generatorG + r2 * generatorH
  requestProof = MakeCredentialRequestProof(m1, m2, r1, r2, m1Enc, m2Enc)
  request = (m1Enc, m2Enc, requestProof)
  clientSecrets = (m1, m2, r1, r2)
  return (clientSecrets, request)
]]></artwork>
          <t>See <xref target="request-proof"/> for more details on the generation of the credential request proof.</t>
          <t>The resulting request can be serialized as follows.</t>
          <artwork><![CDATA[
struct {
  uint8 m1Enc[Ne];
  uint8 m2Enc[Ne];
  uint8 challenge[Ns];
  uint8 response0[Ns];
  uint8 response1[Ns];
  uint8 response2[Ns];
  uint8 response3[Ns];
} CredentialRequest;
]]></artwork>
          <t>The length of this encoded request structure is <tt>Nrequest = 2*Ne + 5*Ns</tt>.</t>
        </section>
        <section anchor="issuance-step2">
          <name>Credential Response</name>
          <t>Given a credential request and server public and private keys, the process
for creating a credential response is as follows.</t>
          <sourcecode type="psuedocode"><![CDATA[
response = CredentialResponse(serverPrivateKey, serverPublicKey, request)

Inputs:
- serverPrivateKey:
  - x0: Scalar (private), server private key 0.
  - x1: Scalar (private), server private key 1.
  - x2: Scalar (private), server private key 2.
  - x0Blinding: Scalar (private), blinding value for x0.
- serverPublicKey:
  - X0: Element, server public key 0.
  - X1: Element, server public key 1.
  - X2: Element, server public key 2.
- request:
  - m1Enc: Element, first encrypted secret.
  - m2Enc: Element, second encrypted secret.
  - requestProof: ZKProof, a proof of correct generation of m1Enc and m2Enc.

Outputs:
- U: Element, a randomized generator for the response, `b*G`.
- encUPrime: Element, encrypted UPrime.
- X0Aux: Element, auxiliary point for X0.
- X1Aux: Element, auxiliary point for X1.
- X2Aux: Element, auxiliary point for X2.
- HAux: Element, auxiliary point for generatorH.
- responseProof: ZKProof, a proof of correct generation of
  U, encUPrime, server public keys, and auxiliary points.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

Exceptions:
- VerifyError, raised when response verification fails

def CredentialResponse(serverPrivateKeys, serverPublicKey, request):
  if VerifyCredentialRequestProof(request) == false:
    raise VerifyError

  b = G.RandomScalar()
  U = b * generatorG
  encUPrime = b * (serverPublicKey.X0 +
        serverPrivateKeys.x1 * request.m1Enc +
        serverPrivateKeys.x2 * request.m2Enc)
  X0Aux = b * serverPrivateKeys.x0Blinding * generatorH
  X1Aux = b * serverPublicKey.X1
  X2Aux = b * serverPublicKey.X2
  HAux = b * generatorH

  responseProof = MakeCredentialResponseProof(serverPrivateKey,
    serverPublicKey, request, b, U, encUPrime, X0Aux, X1Aux, X2Aux, HAux)
  return (U, encUPrime, X0Aux, X1Aux, X2Aux, HAux, responseProof)
]]></sourcecode>
          <t>The resulting response can be serialized as follows. See <xref target="response-proof"/> for more details on the generation of the credential response proof.</t>
          <artwork><![CDATA[
struct {
  uint8 U[Ne];
  uint8 encUPrime[Ne];
  uint8 X0Aux[Ne];
  uint8 X1Aux[Ne];
  uint8 X2Aux[Ne];
  uint8 HAux[Ne];
  uint8 challenge[Ns];
  uint8 response0[Ns];
  uint8 response1[Ns];
  uint8 response2[Ns];
  uint8 response3[Ns];
  uint8 response4[Ns];
  uint8 response5[Ns];
  uint8 response6[Ns];
}
]]></artwork>
          <t>The length of this encoded response structure is <tt>Nresponse = 6*Ne + 8*Ns</tt>.</t>
        </section>
        <section anchor="issuance-step3">
          <name>Finalize Credential</name>
          <t>Given a credential request and response, server public keys, and the client
secrets produced when creating a credential request, the process for
finalizing the issuance flow and creating a credential is as follows.</t>
          <artwork><![CDATA[
credential = FinalizeCredential(clientSecrets, serverPublicKey, request, response)

Inputs:
- clientSecrets:
  - m1: Scalar, first secret.
  - m2: Scalar, second secret.
  - r1: Scalar, blinding factor for first secret.
  - r2: Scalar, blinding factor for second secret.
- serverPublicKey: ServerPublicKey, shared with the client out-of-band
- request:
  - m1Enc: Element, first encrypted secret.
  - m2Enc: Element, second encrypted secret.
  - requestProof: ZKProof, a proof of correct generation of m1Enc and m2Enc.
- response:
  - U: Element, a randomized generator for the response. `b*G`.
  - encUPrime: Element, encrypted UPrime.
  - X0Aux: Element, auxiliary point for X0.
  - X1Aux: Element, auxiliary point for X1.
  - X2Aux: Element, auxiliary point for X2.
  - HAux: Element, auxiliary point for generatorH.
  - responseProof: ZKProof, a proof of correct generation of U, encUPrime, server public keys, and auxiliary points.

Outputs:
- credential:
  - m1: Scalar, client's first secret.
  - U: Element, a randomized generator for the response. `b*G`.
  - UPrime: Element, the MAC over the server's private keys and the client's secret secrets.
  - X1: Element, server public key 1.

Exceptions:
- VerifyError, raised when response verification fails

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

def FinalizeCredential(clientSecrets, serverPublicKey, request, response):
  if VerifyCredentialResponseProof(serverPublicKey, response, request) == false:
    raise VerifyError
  UPrime = response.encUPrime - response.X0Aux - clientSecrets.r1 * response.X1Aux - clientSecrets.r2 * response.X2Aux
  return (clientSecrets.m1, response.U, UPrime, serverPublicKey.X1)
]]></artwork>
        </section>
      </section>
      <section anchor="presentation">
        <name>Presentation</name>
        <t>The purpose of the presentation phase is for the client to create a "presentation" to the server
which can be verified using the server private key. This phase is non-interactive, i.e., there is
no state stored between client and server in order to produce and then verify a presentation.
Client and server agree upon a fixed limit of presentations in order to create and verify
presentations; presentations will not verify correctly if the client and server use different
limits.</t>
        <t>This phase consists of three steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>The client creates a presentation state for a given presentation context and presentation limit.
This state is used to produce a fixed amount of presentations.</t>
          </li>
          <li>
            <t>The client creates a presentation from the presentation state and sends it to the server.
The presentation is cryptographically bound to the state's presentation context, and
contains proof that the presentation is valid with respect to the presentation context.
Moreover, the presentation contains proof that the nonce (an integer) associated with this
presentation is within the presentation limit.</t>
          </li>
          <li>
            <t>The server verifies the presentation with respect to the presentation context and presentation
limit.</t>
          </li>
        </ol>
        <t>Details for each each of these steps are in the following subsections.</t>
        <section anchor="presentation-state">
          <name>Presentation State</name>
          <t>Presentation state is used to track the number of presentations for a given credential.
This state is important for ARC's unlinkability goals: reuse of state can break
unlinkability properties of credential presentations. State is initialized
with a credential, presentation context, and presentation limit. It is then mutated
after each presentation construction (as described in <xref target="presentation-construction"/>).</t>
          <artwork><![CDATA[
state = MakePresentationState(credential, presentationContext, presentationLimit)

Inputs:
- credential:
  - m1: Scalar, client's first secret.
  - U: Element, a randomized generator for the response `b*G`.
  - UPrime: Element, the MAC over the server's private keys and the client's secrets.
  - X1: Element, server public key 1.
- presentationContext: Data (public), used for presentation tag computation.
- presentationLimit: Integer, the fixed presentation limit.

Outputs:
- credential
- presentationContext: Data (public), used for presentation tag computation.
- presentationNonceSet: {Integer}, the set of nonces that have been used for this presentation
- presentationLimit: Integer, the fixed presentation limit.

def MakePresentationState(credential, presentationContext, presentationLimit):
  nonce = random_integer_uniform(0, presentationLimit)
  return PresentationState(credential, presentationContext, [nonce], presentationLimit)
]]></artwork>
        </section>
        <section anchor="presentation-construction">
          <name>Presentation Construction</name>
          <t>Creating a presentation requires a credential, presentation context, and presentation limit.
This process is necessarily stateful on the client since the number of times a credential
is used for a given presentation context cannot exceed the presentation limit; doing so
would break presentation unlinkability, as two presentations created with the same nonce
can be directly compared for equality (via the "tag"). As a result, the process for creating
a presentation accepts as input a presentation state and then outputs an updated presentation
state.</t>
          <artwork><![CDATA[
newState, nonce, presentation = Present(state)

Inputs:
state: input PresentationState
  - credential
  - presentationContext: Data (public), used for presentation tag computation.
  - presentationNonceSet: {Integer}, the set of nonces that have been used for this presentation
  - presentationLimit: Integer, the fixed presentation limit.

Outputs:
- newState: updated PresentationState
- nonce: Integer, the nonce associated with this presentation.
- presentation:
  - U: Element, re-randomized from the U in the response.
  - UPrimeCommit: Element, a public key to the issued UPrime.
  - m1Commit: Element, a public key to the client secret (m1).
  - tag: Element, the tag element used for enforcing the presentation limit.
  - presentationProof: ZKProof, a proof of correct generation of the presentation.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

Exceptions:
- LimitExceededError, raised when the presentation count meets or exceeds the presentation limit for the given presentation context

def Present(state):
  if len(state.presentationNonceSet) >= state.presentationLimit:
    raise LimitExceededError

  a = G.RandomScalar()
  r = G.RandomScalar()
  z = G.RandomScalar()

  U = a * state.credential.U
  UPrime = a * state.credential.UPrime
  UPrimeCommit = UPrime + r * generatorG
  m1Commit = state.credential.m1 * U + z * generatorH

  # This step mutates the state by keeping track of
  # what nonces have already been spent.
  nonce = random_integer_uniform_excluding_set(0,
    state.presentationLimit, state.presentationNonceSet)
  state.presentationNonceSet.add(nonce)

  generatorT = G.HashToGroup(presentationContext, "Tag")
  tag = (credential.m1 + nonce)^(-1) * generatorT
  V = z * credential.X1 - r * generatorG
  m1Tag = state.credential.m1 * tag

  presentationProof = MakePresentationProof(U, UPrimeCommit, m1Commit, tag, generatorT, credential, V, r, z, nonce, m1Tag)

  presentation = (U, UPrimeCommit, m1Commit, tag, presentationProof)

  return state, nonce, presentation
]]></artwork>
          <t>[[OPEN ISSUE: should the tag also fold in the presentation limit?]]</t>
          <t>The resulting presentation can be serialized as follows. See <xref target="presentation-proof"/>
for more details on the generation of the presentation proof.</t>
          <artwork><![CDATA[
struct {
  uint8 U[Ne];
  uint8 UPrimeCommit[Ne];
  uint8 m1Commit[Ne];
  uint8 tag[Ne];
  uint8 challenge[Ns];
  uint8 response0[Ns];
  uint8 response1[Ns];
  uint8 response2[Ns];
  uint8 response3[Ns];
  uint8 response4[Ns];
}
]]></artwork>
          <t>The length of this structure is <tt>Npresentation = 4*Ne + 6*Ns</tt>.</t>
        </section>
        <section anchor="presentation-verification">
          <name>Presentation Verification</name>
          <t>The server processes the presentation by verifying the presentation proof against server-computed
values, and performing a check that the presentation conforms to the presentation limit.</t>
          <artwork><![CDATA[
validity = VerifyPresentation(serverPrivateKey, serverPublicKey, requestContext, presentationContext, nonce, presentation, presentationLimit)

Inputs:
- serverPrivateKey:
  - x0: Scalar (private), server private key 0.
  - x1: Scalar (private), server private key 1.
  - x2: Scalar (private), server private key 2.
  - x0Blinding: Scalar (private), blinding value for x0.
- serverPublicKey:
  - X0: Element, server public key 0.
  - X1: Element, server public key 1.
  - X2: Element, server public key 2.
- requestContext: Data, context for the credential request.
- presentationContext: Data (public), used for presentation tag computation.
- nonce: Integer, the nonce associated with this presentation.
- presentation:
  - U: Element, re-randomized from the U in the response.
  - UPrimeCommit: Element, a public key to the issued UPrime.
  - m1Commit: Element, a public key to the client secret (m1).
  - nonce: Integer, the nonce associated with this presentation.
  - tag: Element, the tag element used for enforcing the presentation limit.
  - presentationProof: ZKProof, a proof of correct generation of the presentation.
- presentationLimit: Integer, the fixed presentation limit.

Outputs:
- validity: Boolean, True if the presentation is valid, False otherwise.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

Exceptions:
- InvalidNonceError, raised when the nonce associated with the presentation is invalid

def VerifyPresentation(serverPrivateKey, serverPublicKey, requestContext, presentationContext, nonce, presentation, presentationLimit):
  if nonce < 0 or nonce > presentationLimit:
    raise InvalidNonceError

  generatorT = G.HashToGroup(presentationContext, "Tag")
  m1Tag = generatorT - (nonce * presentation.tag)

  validity = VerifyPresentationProof(serverPrivateKey, serverPublicKey, requestContext, presentationContext, presentation, m1Tag)
  # Implementation-specific step: perform double-spending check on tag.
  # Implementation-specific step: store tag for future double-spending check.
  return validity
]]></artwork>
          <t>Implementation-specific steps: the server must perform a check that the tag (presentation.tag) has
not previously been seen, to prevent double spending. It then stores the tag for use in future double
spending checks. To reduce the overhead of performing double spend checks, the server can store and
look up the tags corresponding to the associated requestContext and presentationContext values.</t>
        </section>
      </section>
    </section>
    <section anchor="zero-knowledge-proofs">
      <name>Zero-Knowledge Proofs</name>
      <t>This section describes a Schnorr proof compiler that is used for the construction of other proofs needed throughout
the ARC protocol. <xref target="compiler"/> describes the compiler, and the remaining sections describe how it is used for
the purposes of producing ARC proofs.</t>
      <section anchor="compiler">
        <name>Schnorr Compiler</name>
        <t>The compiler specified in this section automates the Fiat-Shamir transform that is often used to
transform interactive zero-knowledge proofs into non-interactive proofs such that they can be used
to non-interactively prove various statements of importance in higher-level protocols, such as ARC.
The compiler consists of a prover and verifier role. The prover constructs a transcript for the
proof and then applies the Fiat-Shamir heuristic to generate the resulting challenge and response
values. The verifier reconstructs the same transcript to verify the proof.</t>
        <t>The prover and verifier roles are specified below in <xref target="prover"/> and <xref target="verifier"/>, respectively.</t>
        <section anchor="prover">
          <name>Prover</name>
          <t>The prover role consists of four functions:</t>
          <ul spacing="normal">
            <li>
              <t>AppendScalar: This function adds a scalar representation to the transcript.</t>
            </li>
            <li>
              <t>AppendElement: This function adds an element representation to the transcript.</t>
            </li>
            <li>
              <t>Constrain: This function applies an explicit constraint to the proof, where the constraint is expressed as equality between some element and a linear combination of scalar and element representations. An example constraint might be <tt>Z = aX + bY</tt>, for scalars <tt>a</tt>, <tt>b</tt>, and elements
<tt>X</tt>, <tt>Y</tt>, <tt>Z</tt>.</t>
            </li>
            <li>
              <t>Prove: This function applies the Fiat-Shamir heuristic to the protocol transcript and set of
constraints to produce a zero-knowledge proof that can be verified.</t>
            </li>
          </ul>
          <t>These functions are defined in the following sub-sections.</t>
          <t>In addition, the prover role consists of the following state:</t>
          <ul spacing="normal">
            <li>
              <t>label: Data, a value representing the context in which the proof will be used</t>
            </li>
            <li>
              <t>scalars: [Integer], An ordered set of representation of scalar variables to use in the proof. Each scalar has a label associated with it, stored in a list called <tt>scalar_labels</tt>.</t>
            </li>
            <li>
              <t>elements: [Integer], An ordered set of representation of element variables to use in the proof. Each element has a label associated with it, stored in a list called <tt>element_labels</tt>.</t>
            </li>
            <li>
              <t>constraints: a set of constraints, where each constraint consists of a constraint element and a linear combination of variables.</t>
            </li>
          </ul>
          <section anchor="appendscalar">
            <name>AppendScalar</name>
            <artwork><![CDATA[
AppendScalar(label, assignment)

Inputs:
- label: Data, Scalar variable label
- assignment: Scalar variable

Outputs:
- Integer: Integer representation of the new scalar variable

def AppendScalar(label, assignment):
  state.scalars.append(assignment)
  state.scalar_labels.append(label)
  return len(state.scalars) - 1
]]></artwork>
          </section>
          <section anchor="appendelement">
            <name>AppendElement</name>
            <artwork><![CDATA[
AppendElement(label, assignment)

Inputs:
- label: Data, Element variable label
- assignment: Element variable

Outputs:
- Integer: Integer representation of the new element variable

def AppendElement(label, assignment):
  state.elements.append(assignment)
  state.element_labels.append(label)
  return len(state.elements) - 1
]]></artwork>
          </section>
          <section anchor="constrain">
            <name>Constrain</name>
            <artwork><![CDATA[
Constrain(result, linearCombination)

Inputs:
- result: Integer, representation of constraint element
- assignment: linear combination of scalar and element variable (representations)

def Constrain(label, linearCombination):
  state.constraints.append((result, linearCombination))
]]></artwork>
          </section>
          <section anchor="prove">
            <name>Prove</name>
            <t>The Prove function is defined below.</t>
            <artwork><![CDATA[
Prove()

Outputs:
- ZKProof, a proof consisting of a challenge Scalar and then fixed number of response Scalar values

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

Exceptions:
- InvalidVariableAllocationError, raised when the prover was incorrectly configured

def Prove():
  blindings = [G.RandomScalar() for i in range(len(state.scalars))]

  blinded_elements = []
  for (constraint_point, linear_combination) in state.constraints:
    if constraint_point.index > len(state.elements):
      raise InvalidVariableAllocationError

    for (scalar_var, element_var) in linear_combination:
      if scalar_var.index > len(state.scalars):
        raise InvalidVariableAllocationError
      if element_var.index > len(state.elements):
        raise InvalidVariableAllocationError

    scalar_index = linear_combination[0][0]
    element_index = linear_combination[0][1]
    blinded_element = blindings[scalar_index] * state.elements[element_index]

    for i, pair in enumerate(linear_combination):
      if i > 0:
        scalar_index = pair[0]
        element_index = pair[1]
        blinded_element += blindings[scalar_index] * state.elements[element_index]

        blinded_elements.append(blinded_element)

  # Obtain a scalar challenge
  challenge = ComposeChallenge(state.label, state.elements, blinded_elements)

  # Compute response scalars from the challenge, scalars, and blindings.
  responses = []
  for (index, scalar) in enumerate(state.scalars):
    blinding = blindings[index]
    responses.append(blinding - challenge * scalar)

  return ZKProof(challenge, responses)
]]></artwork>
            <t>The function ComposeChallenge is defined below.</t>
            <artwork><![CDATA[
ComposeChallenge(label, elements, blinded_elements)

Inputs:
- label: Data, the proof label
- elements: [Element], ordered list of elements
- blinded_elements: [Element], ordered list of blinded elements

Outputs:
- challenge, Scalar

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

def ComposeChallenge(label, elements, blinded_elements):
  challenge_input = Data() # Empty Data

  for element in elements:
    serialized_element = G.SerializeElement(element)
    challenge_input += I2OSP(len(serialized_element), 2) + serialized_element

  for blinded_element in blinded_elements:
    serialized_blinded_element = G.SerializeElement(blinded_element)
    challenge_input += I2OSP(len(serialized_blinded_element), 2) + serialized_blinded_element

  return G.HashToScalar(challenge_input, label)
]]></artwork>
          </section>
        </section>
        <section anchor="verifier">
          <name>Verifier</name>
          <t>The verifier role consists of four functions:</t>
          <ul spacing="normal">
            <li>
              <t>AppendScalar: This function adds a scalar representation to the transcript.</t>
            </li>
            <li>
              <t>AppendElement: This function adds an element representation to the transcript.</t>
            </li>
            <li>
              <t>Constrain: This function applies an explicit constraint to the proof, where the constraint is expressed as equality between some element and a linear combination of scalar and element representations. An example constraint might be <tt>Z = aX + bY</tt>, for scalars <tt>a</tt>, <tt>b</tt>, and elements
<tt>X</tt>, <tt>Y</tt>, <tt>Z</tt>.</t>
            </li>
            <li>
              <t>Verify: This function applies the Fiat-Shamir heuristic to verify the zero-knowledge proof.</t>
            </li>
          </ul>
          <t>AppendScalar and Verify are defined in the following sub-sections. AppendElement and Constrain matches the functionality used in the prover role.</t>
          <section anchor="appendscalar-1">
            <name>AppendScalar</name>
            <artwork><![CDATA[
AppendScalar(label)

Inputs:
- label: Data, Scalar variable label

Outputs:
- Integer: Integer representation of the new scalar variable

def AppendScalar(label):
  state.scalar_labels.append(label)
  return len(state.scalar_labels) - 1
]]></artwork>
          </section>
          <section anchor="verify">
            <name>Verify</name>
            <artwork><![CDATA[
Verify(proof)

Inputs:
- ZKProof, a proof consisting of a challenge Scalar and then fixed number of response Scalar values

Outputs:
- Boolean, True if the proof is valid, False otherwise.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

Exceptions:
- InvalidVariableAllocationError, raised when the prover was incorrectly configured

def Verify(proof):
  if len(state.elements) != len(state.element_labels):
    raise InvalidVariableAllocationError

  blinded_elements = []
  for (constraint_element, linear_combination) in state.constraints:
    if constraint_element > len(state.elements):
      raise InvalidVariableAllocationError
    for (_, element_var) in linear_combination:
      if element_var > len(state.elements):
        raise InvalidVariableAllocationError

    challenge_element = proof.challenge * state.elements[constraint_element]
    for i, pair in enumerate(linear_combination):
      challenge_element += proof.responses[pair[0]] * state.elements[pair[1]]

    blinded_elements.append(challenge_element)

  challenge = ComposeChallenge(state.label, self.elements, blinded_elements)
  return challenge == proof.challenge
]]></artwork>
          </section>
        </section>
      </section>
      <section anchor="request-proof">
        <name>CredentialRequest Proof</name>
        <t>The request proof is a proof of knowledge of (m1, m2, r1, r2) used to generate the encrypted request. Statements to prove:</t>
        <artwork><![CDATA[
1. m1Enc = m1 * generatorG + r1 * generatorH
2. m2Enc = m2 * generatorG + r2 * generatorH
]]></artwork>
        <section anchor="credentialrequest-proof-creation">
          <name>CredentialRequest Proof Creation</name>
          <artwork><![CDATA[
requestProof = MakeCredentialRequestProof(m1, m2, r1, r2, m1Enc, m2Enc)

Inputs:
- m1: Scalar, first secret.
- m2: Scalar, second secret.
- r1: Scalar, blinding factor for first secret.
- r2: Scalar, blinding factor for second secret.
- m1Enc: Element, first encrypted secret.
- m2Enc: Element, second encrypted secret.

Outputs:
- proof: ZKProof
  - challenge: Scalar, the challenge used in the proof of valid encryption.
  - response0: Scalar, the response corresponding to m1.
  - response1: Scalar, the response corresponding to m2.
  - response2: Scalar, the response corresponding to r1.
  - response3: Scalar, the response corresponding to r2.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()
- contextString: public input

def MakeCredentialRequestProof(m1, m2, r1, r2, m1Enc, m2Enc):
  prover = Prover(contextString + "CredentialRequest")

  m1Var = prover.AppendScalar("m1", m1)
  m2Var = prover.AppendScalar("m2", m2)
  r1Var = prover.AppendScalar("r1", r1)
  r2Var = prover.AppendScalar("r2", r2)

  genGVar = prover.AppendElement("genG", generatorG)
  genHVar = prover.AppendElement("genH", generatorH)
  m1EncVar = prover.AppendElement("m1Enc", m1Enc)
  m2EncVar = prover.AppendElement("m2Enc", m2Enc)

  # 1. m1Enc = m1 * generatorG + r1 * generatorH
  prover.Constrain(m1EncVar, [(m1Var, genGVar), (r1Var, genHVar)])

  # 2. m2Enc = m2 * generatorG + r2 * generatorH
  prover.Constrain(m2EncVar, [(m2Var, genGVar), (r2Var, genHVar)])

  return prover.Prove()
]]></artwork>
        </section>
        <section anchor="credentialrequest-proof-verification">
          <name>CredentialRequest Proof Verification</name>
          <artwork><![CDATA[
validity = VerifyCredentialRequestProof(request)

Inputs:
- request:
  - m1Enc: Element, first encrypted secret.
  - m2Enc: Element, second encrypted secret.
  - requestProof: ZKProof, a proof of correct generation of m1Enc and m2Enc.
    - challenge: Scalar, the challenge used in the proof of valid encryption.
    - response0: Scalar, the response corresponding to m1.
    - response1: Scalar, the response corresponding to m2.
    - response2: Scalar, the response corresponding to r1.
    - response3: Scalar, the response corresponding to r2.

Outputs:
- validity: Boolean, True if the proof verifies correctly, False otherwise.

Parameters:
- G: group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()
- contextString: public input

def VerifyCredentialRequestProof(request):
  verifier = Verifier(contextString + "CredentialRequest")

  m1Var = verifier.AppendScalar("m1")
  m2Var = verifier.AppendScalar("m2")
  r1Var = verifier.AppendScalar("r1")
  r2Var = verifier.AppendScalar("r2")

  genGVar = verifier.AppendElement("genG", generatorG)
  genHVar = verifier.AppendElement("genH", generatorH)
  m1EncVar = verifier.AppendElement("m1Enc", request.m1Enc)
  m2EncVar = verifier.AppendElement("m2Enc", request.m2Enc)

  # 1. m1Enc = m1 * generatorG + r1 * generatorH
  verifier.Constrain(m1EncVar, [(m1Var, genGVar), (r1Var, genHVar)])

  # 2. m2Enc = m2 * generatorG + r2 * generatorH
  verifier.Constrain(m2EncVar, [(m2Var, genGVar), (r2Var, genHVar)])

  return verifier.Verify(request.proof)
]]></artwork>
        </section>
      </section>
      <section anchor="response-proof">
        <name>CredentialResponse Proof</name>
        <t>The response proof is a proof of knowledge of (x0, x1, x2, x0Blinding, b) used in the server's CredentialResponse for the client's CredentialRequest. Statements to prove:</t>
        <artwork><![CDATA[
1. X0 = x0 * generatorG + x0Blinding * generatorH
2. X1 = x1 * generatorH
3. X2 = x2 * generatorH
4. X0Aux = b * x0Blinding * generatorH
  4a. HAux = b * generatorH
  4b: X0Aux = x0Blinding * HAux (= b * x0Blinding * generatorH)
5. X1Aux = b * x1 * generatorH
  5a. X1Aux = b * X1 (X1 = x1 * generatorH)
  5b. X1Aux = t1 * generatorH (t1 = b * x1)
6. X2Aux = b * x2 * generatorH
  6a. X2Aux = b * X2 (X2 = x2 * generatorH)
  6b. X2Aux = t2 * generatorH (t2 = b * x2)
7. U = b * generatorG
8. encUPrime = b * (X0 + x1 * Enc(m1) + x2 * Enc(m2))
]]></artwork>
        <section anchor="credentialresponse-proof-creation">
          <name>CredentialResponse Proof Creation</name>
          <artwork><![CDATA[
responseProof = MakeCredentialResponseProof(serverPrivateKey, serverPublicKey, request, b, U, encUPrime, X0Aux, X1Aux, X2Aux, HAux)

Inputs:
- serverPrivateKey:
  - x0: Scalar (private), server private key 0.
  - x1: Scalar (private), server private key 1.
  - x2: Scalar (private), server private key 2.
  - x0Blinding: Scalar (private), blinding value for x0.
- serverPublicKey:
  - X0: Element, server public key 0.
  - X1: Element, server public key 1.
  - X2: Element, server public key 2.
- request:
  - m1Enc: Element, first encrypted secret.
  - m2Enc: Element, second encrypted secret.
  - requestProof: ZKProof, a proof of correct generation of m1Enc and m2Enc.
- encUPrime: Element, encrypted UPrime.
- X0Aux: Element, auxiliary point for X0.
- X1Aux: Element, auxiliary point for X1.
- X2Aux: Element, auxiliary point for X2.
- HAux: Element, auxiliary point for generatorH.

Outputs:
- proof: ZKProof
  - challenge: Scalar, the challenge used in the proof of valid response.
  - response0: Scalar, the response corresponding to x0.
  - response1: Scalar, the response corresponding to x1.
  - response2: Scalar, the response corresponding to x2.
  - response3: Scalar, the response corresponding to x0Blinding.
  - response4: Scalar, the response corresponding to b.
  - response5: Scalar, the response corresponding to t1.
  - response6: Scalar, the response corresponding to t2.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()
- contextString: public input

def MakeCredentialResponseProof(serverPrivateKey, serverPublicKey, request, b, U, encUPrime, X0Aux, X1Aux, X2Aux, HAux):
  prover = Prover(contextString + "CredentialResponse")

  x0Var = prover.AppendScalar("x0", serverPrivateKey.x0)
  x1Var = prover.AppendScalar("x1", serverPrivateKey.x1)
  x2Var = prover.AppendScalar("x2", serverPrivateKey.x2)
  x0BlindingVar = prover.AppendScalar("x0Blinding", serverPrivateKey.x0Blinding)
  bVar = prover.AppendScalar("b", b)
  t1Var = prover.AppendScalar("t1", b * serverPrivateKey.x1)
  t2Var = prover.AppendScalar("t2", b * serverPrivateKey.x2)

  genGVar = prover.AppendElement("genG", generatorG)
  genHVar = prover.AppendElement("genH", generatorH)
  m1EncVar = prover.AppendElement("m1Enc", request.m1Enc)
  m2EncVar = prover.AppendElement("m2Enc", request.m2Enc)
  UVar = prover.AppendElement("U", U)
  encUPrimeVar = prover.AppendElement("encUPrime", encUPrime)
  X0Var = prover.AppendElement("X0", serverPublicKey.X0)
  X1Var = prover.AppendElement("X1", serverPublicKey.X1)
  X2Var = prover.AppendElement("X2", serverPublicKey.X2)
  X0AuxVar = prover.AppendElement("X0Aux", X0Aux)
  X1AuxVar = prover.AppendElement("X1Aux", X1Aux)
  X2AuxVar = prover.AppendElement("X2Aux", X2Aux)
  HAuxVar = prover.AppendElement("HAux", HAux)

  # 1. X0 = x0 * generatorG + x0Blinding * generatorH
  prover.Constrain(X0Var, [(x0Var, genGVar), (x0BlindingVar, genHVar)])
  # 2. 2. X1 = x1 * generatorH
  prover.Constrain(X1Var, [(x1Var, genHVar)])
  # 3. X2 = x2 * generatorH
  prover.Constrain(X2Var, [(x2Var, genHVar)])

  # 4. X0Aux = b * x0Blinding * generatorH
  # 4a. HAux = b * generatorH
  prover.Constrain(HAuxVar, [(bVar, genHVar)])
  # 4b: X0Aux = x0Blinding * HAux (= b * x0Blinding * generatorH)
  prover.Constrain(X0AuxVar, [(x0BlindingVar, HAuxVar)])

  #5. X1Aux = b * x1 * generatorH
  # 5a. X1Aux = b * X1 (X1 = x1 * generatorH)
  prover.Constrain(X1AuxVar, [(t1Var, genHVar)])
  # 5b. X1Aux = t1 * generatorH (t1 = b * x1)
  prover.Constrain(X1AuxVar, [(bVar, X1Var)])

  # 6. X2Aux = b * x2 * generatorH
  # 6a. X2Aux = b * X2 (X2 = x2 * generatorH)
  prover.Constrain(X2AuxVar, [(bVar, X2Var)])
  # 6b. X2Aux = t2 * H (t2 = b * x2)
  prover.Constrain(X2AuxVar, [(t2Var, genHVar)])

  # 7. U = b * generatorG
  prover.Constrain(UVar, [(bVar, genGVar)])
  # 8. encUPrime = b * (X0 + x1 * Enc(m1) + x2 * Enc(m2))
  # simplified: encUPrime = b * X0 + t1 * m1Enc + t2 * m2Enc, since t1 = b * x1 and t2 = b * x2
  prover.Constrain(encUPrimeVar, [(bVar, X0Var), (t1Var, m1EncVar), (t2Var, m2EncVar)])

  return prover.Prove()
]]></artwork>
        </section>
        <section anchor="credentialresponse-proof-verification">
          <name>CredentialResponse Proof Verification</name>
          <artwork><![CDATA[
validity = VerifyCredentialResponseProof(serverPublicKey, response, request)

Inputs:
- serverPublicKey:
  - X0: Element, server public key 0.
  - X1: Element, server public key 1.
  - X2: Element, server public key 2.
- response:
  - U: Element, a randomized generator for the response. `b*G`.
  - encUPrime: Element, encrypted UPrime.
  - X0Aux: Element, auxiliary point for X0.
  - X1Aux: Element, auxiliary point for X1.
  - X2Aux: Element, auxiliary point for X2.
  - HAux: Element, auxiliary point for generatorH.
  - responseProof: ZKProof, a proof of correct generation of U, encUPrime, server public keys, and auxiliary points.
    - challenge: Scalar, the challenge used in the proof of valid response.
    - response0: Scalar, the response corresponding to x0.
    - response1: Scalar, the response corresponding to x1.
    - response2: Scalar, the response corresponding to x2.
    - response3: Scalar, the response corresponding to x0Blinding.
    - response4: Scalar, the response corresponding to b.
    - response5: Scalar, the response corresponding to t1.
    - response6: Scalar, the response corresponding to t2.
- request:
  - m1Enc: Element, first encrypted secret.
  - m2Enc: Element, second encrypted secret.
  - requestProof: ZKProof, a proof of correct generation of m1Enc and m2Enc.

Outputs:
- validity: Boolean, True if the proof verifies correctly, False otherwise.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()

def VerifyCredentialResponseProof(serverPublicKey, response, request):
  verifier = Verifier(contextString + "CredentialResponse")

  x0Var = verifier.AppendScalar("x0")
  x1Var = verifier.AppendScalar("x1")
  x2Var = verifier.AppendScalar("x2")
  x0BlindingVar = verifier.AppendScalar("x0Blinding")
  bVar = verifier.AppendScalar("b", b)
  t1Var = verifier.AppendScalar("t1")
  t2Var = verifier.AppendScalar("t2")

  genGVar = verifier.AppendElement("genG", generatorG)
  genHVar = verifier.AppendElement("genH", generatorH)
  m1EncVar = verifier.AppendElement("m1Enc", request.m1Enc)
  m2EncVar = verifier.AppendElement("m2Enc", request.m2Enc)
  UVar = verifier.AppendElement("U", response.U)
  encUPrimeVar = verifier.AppendElement("encUPrime", response.encUPrime)
  X0Var = verifier.AppendElement("X0", serverPublicKey.X0)
  X1Var = verifier.AppendElement("X1", serverPublicKey.X1)
  X2Var = verifier.AppendElement("X2", serverPublicKey.X2)
  X0AuxVar = verifier.AppendElement("X0Aux", response.X0Aux)
  X1AuxVar = verifier.AppendElement("X1Aux", response.X1Aux)
  X2AuxVar = verifier.AppendElement("X2Aux", response.X2Aux)
  HAuxVar = verifier.AppendElement("HAux", response.HAux)

  # 1. X0 = x0 * generatorG + x0Blinding * generatorH
  verifier.Constrain(X0Var, [(x0Var, genGVar), (x0BlindingVar, genHVar)])
  # 2. 2. X1 = x1 * generatorH
  verifier.Constrain(X1Var, [(x1Var, genHVar)])
  # 3. X2 = x2 * generatorH
  verifier.Constrain(X2Var, [(x2Var, genHVar)])

  # 4. X0Aux = b * x0Blinding * generatorH
  # 4a. HAux = b * generatorH
  verifier.Constrain(HAuxVar, [(bVar, genHVar)])
  # 4b: X0Aux = x0Blinding * HAux (= b * x0Blinding * generatorH)
  verifier.Constrain(X0AuxVar, [(x0BlindingVar, HAuxVar)])

  #5. X1Aux = b * x1 * generatorH
  # 5a. X1Aux = b * X1 (X1 = x1 * generatorH)
  verifier.Constrain(X1AuxVar, [(t1Var, genHVar)])
  # 5b. X1Aux = t1 * generatorH (t1 = b * x1)
  verifier.Constrain(X1AuxVar, [(bVar, X1Var)])

  # 6. X2Aux = b * x2 * generatorH
  # 6a. X2Aux = b * X2 (X2 = x2 * generatorH)
  verifier.Constrain(X2AuxVar, [(bVar, X2Var)])
  # 6b. X2Aux = t2 * H (t2 = b * x2)
  verifier.Constrain(X2AuxVar, [(t2Var, genHVar)])

  # 7. U = b * generatorG
  verifier.Constrain(UVar, [(bVar, genGVar)])
  # 8. encUPrime = b * (X0 + x1 * Enc(m1) + x2 * Enc(m2))
  # simplified: encUPrime = b * X0 + t1 * m1Enc + t2 * m2Enc, since t1 = b * x1 and t2 = b * x2
  verifier.Constrain(encUPrimeVar, [(bVar, X0Var), (t1Var, m1EncVar), (t2Var, m2EncVar)])

  return verifier.Verify(response.proof)
]]></artwork>
        </section>
      </section>
      <section anchor="presentation-proof">
        <name>Presentation Proof</name>
        <t>The presentation proof is a proof of knowledge of (m1, r, z) used in the presentation, and a proof that the nonce used to make the tag is in the range of [0, presentationLimit).</t>
        <t>Statements to prove:</t>
        <artwork><![CDATA[
1. m1Commit = m1 * U + z * generatorH
2. V = z * X1 - r * generatorG
3. G.HashToGroup(presentationContext, "Tag") = m1 * tag + nonce * tag
4. m1Tag = m1 * tag
]]></artwork>
        <section anchor="presentation-proof-creation">
          <name>Presentation Proof Creation</name>
          <artwork><![CDATA[
presentationProof = MakePresentationProof(U, UPrimeCommit, m1Commit, tag, generatorT, credential, V, r, z, nonce, m1Tag)

Inputs:
- U: Element, re-randomized from the U in the response.
- UPrimeCommit: Element, a public key to the MACGGM output UPrime.
- m1Commit: Element, a public key to the client secret (m1).
- tag: Element, the tag element used for enforcing the presentation limit.
- generatorT: Element, used for presentation tag computation.
- credential:
  - m1: Scalar, client's first secret.
  - U: Element, a randomized generator for the response. `b*G`.
  - UPrime: Element, the MAC over the server's private keys and the client's secrets.
  - X1: Element, server public key 1.
- V: Element, a proof helper element.
- r: Scalar (private), a randomly generated element used in presentation.
- z: Scalar (private), a randomly generated element used in presentation.
- nonce: Int, the nonce associated with the presentation.
- m1Tag: Element, helper element for the proof.

Outputs:
- proof: ZKProof
  - challenge: Scalar, the challenge used in the proof of valid presentation.
  - response0: Scalar, the response corresponding to m1.
  - response1: Scalar, the response corresponding to z.
  - response2: Scalar, the response corresponding to -r.
  - response3: Scalar, the response corresponding to nonce.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()
- contextString: public input

def MakePresentationProof(U, UPrimeCommit, m1Commit, tag, generatorT, presentationContext, credential, V, r, z, nonce, m1Tag)
  prover = Prover(contextString + "PresentationProof")

  m1Var = prover.AppendScalar("m1", credential.m1)
  zVar = prover.AppendScalar("z", z)
  rNegVar = prover.AppendScalar("-r", -r)
  nonceVar = prover.AppendScalar("nonce", nonce)

  genGVar = prover.AppendElement("genG", generatorG)
  genHVar = prover.AppendElement("genH", generatorH)
  UVar = prover.AppendElement("U", U)
  _ = prover.AppendElement("UPrimeCommit", UPrimeCommit)
  m1CommitVar = prover.AppendElement("m1Commit", m1Commit)
  VVar = prover.AppendElement("V", V)
  X1Var = prover.AppendElement("X1", credential.X1)
  tagVar = prover.AppendElement("tag", tag)
  genTVar = prover.AppendElement("genT", generatorT)
  m1TagVar = prover.AppendElement("m1Tag", m1Tag)

  # 1. m1Commit = m1 * U + z * generatorH
  prover.Constrain(m1CommitVar, [(m1Var, UVar), (zVar, genHVar)])
  # 2. V = z * X1 - r * generatorG
  prover.Constrain(VVar, [(zVar, X1Var), (rNegVar, genGVar)])
  # 3. G.HashToGroup(presentationContext, "Tag") = m1 * tag + nonce * tag
  prover.Constrain(genTVar, [(m1Var, tagVar), (nonceVar, tagVar)])
  # 4. m1Tag = m1 * tag
  prover.Constrain(m1TagVar, [(m1Var, tagVar)])

  return prover.Prove()
]]></artwork>
        </section>
        <section anchor="presentation-proof-verification">
          <name>Presentation Proof Verification</name>
          <artwork><![CDATA[
validity = VerifyPresentationProof(serverPrivateKey, serverPublicKey, requestContext, presentationContext, presentation, m1Tag)

Inputs:
- serverPrivateKey:
  - x0: Scalar (private), server private key 0.
  - x1: Scalar (private), server private key 1.
  - x2: Scalar (private), server private key 2.
  - x0Blinding: Scalar (private), blinding value for x0.
- serverPublicKey:
  - X0: Element, server public key 0.
  - X1: Element, server public key 1.
  - X2: Element, server public key 2.
- requestContext: Data, context for the credential request.
- presentationContext: Data (public), used for presentation tag computation.
- presentation:
  - U: Element, re-randomized from the U in the response.
  - UPrimeCommit: Element, a public key to the issued UPrime.
  - m1Commit: Element, a public key to the client secret (m1).
  - tag: Element, the tag element used for enforcing the presentation limit.
  - presentationProof: ZKProof, a proof of correct generation of the presentation.
    - challenge: Scalar, the challenge used in the proof of valid presentation.
    - response0: Scalar, the response corresponding to m1.
    - response1: Scalar, the response corresponding to z.
    - response2: Scalar, the response corresponding to -r.
    - response3: Scalar, the response corresponding to nonce.
- m1Tag: Element, helper to validate the presentation proof.

Outputs:
- validity: Boolean, True if the proof verifies correctly, False otherwise.

Parameters:
- G: Group
- generatorG: Element, equivalent to G.GeneratorG()
- generatorH: Element, equivalent to G.GeneratorH()
- contextString: public input

def VerifyPresentationProof(serverPrivateKey, serverPublicKey, requestContext, presentationContext, presentation, m1Tag):
  m2 = G.HashToScalar(requestContext, "requestContext")
  V = serverPrivateKey.x0 * presentation.U + serverPrivateKey.x1 * presentation.m1Commit + serverPrivateKey.x2 * m2 * presentation.U - presentation.UPrimeCommit
  generatorT = G.HashToGroup(presentationContext, "Tag")

  verifier = Verifier(contextString + "PresentationProof")

  m1Var = verifier.AppendScalar("m1")
  zVar = verifier.AppendScalar("z")
  rNegVar = verifier.AppendScalar("-r")
  nonceVar = verifier.AppendScalar("nonce")

  genGVar = verifier.AppendElement("genG", generatorG)
  genHVar = verifier.AppendElement("genH", generatorH)
  UVar = verifier.AppendElement("U", presentation.U)
  _ = verifier.AppendElement("UPrimeCommit", presentation.UPrimeCommit)
  m1CommitVar = verifier.AppendElement("m1Commit", presentation.m1Commit)
  VVar = verifier.AppendElement("V", presentation.V)
  X1Var = verifier.AppendElement("X1", serverPublicKey.X1)
  tagVar = prover.AppendElement("tag", presentation.tag)
  genTVar = verifier.AppendElement("genT", generatorT)
  m1TagVar = prover.AppendElement("m1Tag", m1Tag)

  # 1. m1Commit = m1 * U + z * generatorH
  verifier.Constrain(m1CommitVar, [(m1Var, UVar), (zVar, genHVar)])
  # 2. V = z * X1 - r * generatorG
  verifier.Constrain(VVar, [(zVar, X1Var), (rNegVar, genGVar)])
  # 3. G.HashToGroup(presentationContext, "Tag") = m1 * tag + nonceVar * tag
  verifier.Constrain(genTVar, [(m1Var, tagVar), (nonceVar, tagVar)])
  # 4. m1Tag = m1 * tag
  prover.Constrain(m1TagVar, [(m1Var, tagVar)])

  return verifier.Verify(presentation.proof)
]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="ciphersuites">
      <name>Ciphersuites</name>
      <t>A ciphersuite (also referred to as 'suite' in this document) for the protocol
wraps the functionality required for the protocol to take place. The
ciphersuite should be available to both the client and server, and agreement
on the specific instantiation is assumed throughout.</t>
      <t>A ciphersuite contains an instantiation of the following functionality:</t>
      <ul spacing="normal">
        <li>
          <t><tt>Group</tt>: A prime-order Group exposing the API detailed in <xref target="pog"/>, with the
generator element defined in the corresponding reference for each group. Each
group also specifies HashToGroup, HashToScalar, and serialization functionalities.
For HashToGroup, the domain separation tag (DST) is constructed in accordance
with the recommendations in <xref section="3.1" sectionFormat="comma" target="I-D.irtf-cfrg-hash-to-curve"/>.
For HashToScalar, each group specifies an integer order that is used in
reducing integer values to a member of the corresponding scalar field.</t>
        </li>
      </ul>
      <t>This section includes an initial set of ciphersuites with supported groups.
It also includes implementation details for each ciphersuite, focusing on input validation.</t>
      <section anchor="arcp-384">
        <name>ARC(P-384)</name>
        <t>This ciphersuite uses P-384 <xref target="NISTCurves"/> for the Group.
The value of the ciphersuite identifier is "P384". The value of
contextString is "ARCV1-P384".</t>
        <ul spacing="normal">
          <li>
            <t>Group: P-384 (secp384r1) <xref target="NISTCurves"/>
            </t>
            <ul spacing="normal">
              <li>
                <t>Order(): Return 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973.</t>
              </li>
              <li>
                <t>Identity(): As defined in <xref target="NISTCurves"/>.</t>
              </li>
              <li>
                <t>Generator(): As defined in <xref target="NISTCurves"/>.</t>
              </li>
              <li>
                <t>RandomScalar(): Implemented by returning a uniformly random Scalar in the range
[0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for implementation guidance.</t>
              </li>
              <li>
                <t>HashToGroup(x, info): Use hash_to_curve with suite P384_XMD:SHA-384_SSWU_RO_
<xref target="I-D.irtf-cfrg-hash-to-curve"/>, input <tt>x</tt>, and DST =
"HashToGroup-" || contextString || info.</t>
              </li>
              <li>
                <t>HashToScalar(x, info): Use hash_to_field from <xref target="I-D.irtf-cfrg-hash-to-curve"/>
using L = 72, <tt>expand_message_xmd</tt> with SHA-384, input <tt>x</tt> and
DST = "HashToScalar-" || contextString || info, and
prime modulus equal to <tt>Group.Order()</tt>.</t>
              </li>
              <li>
                <t>ScalarInverse(s): Returns the multiplicative inverse of input Scalar <tt>s</tt> mod <tt>Group.Order()</tt>.</t>
              </li>
              <li>
                <t>SerializeElement(A): Implemented using the compressed Elliptic-Curve-Point-to-Octet-String
method according to <xref target="SEC1"/>; Ne = 49.</t>
              </li>
              <li>
                <t>DeserializeElement(buf): Implemented by attempting to deserialize a 49-byte array  to
a public key using the compressed Octet-String-to-Elliptic-Curve-Point method according to <xref target="SEC1"/>,
and then performs partial public-key validation as defined in section 5.6.2.3.4 of
<xref target="KEYAGREEMENT"/>. This includes checking that the
coordinates of the resulting point are in the correct range, that the point is on
the curve, and that the point is not the point at infinity. Additionally, this function
validates that the resulting element is not the group identity element.
If these checks fail, deserialization returns an InputValidationError error.</t>
              </li>
              <li>
                <t>SerializeScalar(s): Implemented using the Field-Element-to-Octet-String conversion
according to <xref target="SEC1"/>; Ns = 48.</t>
              </li>
              <li>
                <t>DeserializeScalar(buf): Implemented by attempting to deserialize a Scalar from a 48-byte
string using Octet-String-to-Field-Element from <xref target="SEC1"/>. This function can fail if the
input does not represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="random-scalar">
        <name>Random Scalar Generation</name>
        <t>Two popular algorithms for generating a random integer uniformly distributed in
the range [0, G.Order() -1] are as follows:</t>
        <section anchor="rejection-sampling">
          <name>Rejection Sampling</name>
          <t>Generate a random byte array with <tt>Ns</tt> bytes, and attempt to map to a Scalar
by calling <tt>DeserializeScalar</tt> in constant time. If it succeeds, return the
result. If it fails, try again with another random byte array, until the
procedure succeeds. Failure to implement <tt>DeserializeScalar</tt> in constant time
can leak information about the underlying corresponding Scalar.</t>
          <t>As an optimization, if the group order is very close to a power of
2, it is acceptable to omit the rejection test completely.  In
particular, if the group order is p, and there is an integer b
such that |p - 2<sup>b</sup>| is less than 2<sup>(b/2)</sup>, then
<tt>RandomScalar</tt> can simply return a uniformly random integer of at
most b bits.</t>
        </section>
        <section anchor="random-number-generation-using-extra-random-bits">
          <name>Random Number Generation Using Extra Random Bits</name>
          <t>Generate a random byte array with <tt>L = ceil(((3 * ceil(log2(G.Order()))) / 2) / 8)</tt>
bytes, and interpret it as an integer; reduce the integer modulo <tt>G.Order()</tt> and return the
result. See <xref section="5" sectionFormat="comma" target="I-D.irtf-cfrg-hash-to-curve"/> for the underlying derivation of <tt>L</tt>.</t>
        </section>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>For arguments about correctness, unforgeability, anonymity, and blind issuance of the ARC protocol, see the
"Formal Security Definitions for Keyed-Verification Anonymous Credentials" in <xref target="KVAC"/>.</t>
      <t>This section elaborates on unlinkability properties for ARC and other implementation details
necessary for these properties to hold.</t>
      <section anchor="credential-issuance-unlinkability">
        <name>Credential Issuance Unlinkability</name>
        <t>Client credential requests are constructed such that the server cannot distinguish between any two credential requests from the same client and two requests from different clients. We refer to this property as issuance unlinkability. This property is achieved by the way the credential requests are constructed. In particular, each credential request consists of two Pedersen commitments with fresh blinding factors, which are used to commit to a freshly generated client secret and request context. The resulting request is therefore perfetly hiding, and independent from other requests from the same client. More details about this unlinkability property can be found in <xref target="KVAC"/> and <xref target="REVISITING_KVAC"/>.</t>
      </section>
      <section anchor="pres-unlinkability">
        <name>Presentation Unlinkability</name>
        <t>Client credential presentations are constructed so that all presentations are indistinguishable, even if coming from the same user. We refer to this property as presentation unlinkability. This property is achieved by the way the credential presentations are constructed. The presentation elements <tt>[U, UPrimeCommit, m1Commit]</tt> are indistinguishable from all other presentations made from credentials issued with the same server keys, as detailed in <xref target="KVAC"/>.</t>
        <t>The indistinguishability set for these presentation elements is <tt>sum_{i=0}^c(p_i)</tt>, where <tt>c</tt> is the number of credentials issued with the same server keys, and <tt>p_i</tt> is the number of presentations made for each of those credentials.</t>
        <t>The presentation elements <tt>[tag, nonce, presentationContext, presentationProof]</tt> are indistinguishable from all presentations made from credentials issued with the same server keys for that presentationContext, with the exception of presentations with the same nonce (since those presentations can be ascertained as being generated from different credentials, as long as the presentation tag is unique).</t>
        <t>The indistinguishability set for those presentation elements is <tt>sum_{i=0}^c(p_i[presentationContext]) - k[presentationContext]</tt>, where <tt>c</tt> is the number of credentials issued with the same server keys, <tt>p_i[presentationContext]</tt> is the number of presentations made for each of those credentials with the same presentationContext, and <tt>k</tt> is the number of presentations with the same nonce for that presentationContext. As long as the nonces are generated randomly from the range defined by the presentation limit, <tt>k[presentationContext]</tt> should be roughly equal to <tt>sum_{i=0}^c(p_i[presentationContext]) / n</tt>, where <tt>n</tt> is the presentation limit. Therefore, the indistinguishability set can be represented as <tt>sum_{i=0}^c(p_i[presentationContext])(1 - 1/n)</tt>, where a larger presentation limit results in a larger indistinguishability set and therefore stronger unlinkability properties.</t>
        <t>[[OPEN ISSUE: hide the nonce and replace the tag proof with a range proof built from something like Bulletproofs.]]</t>
      </section>
      <section anchor="timing-leaks">
        <name>Timing Leaks</name>
        <t>To ensure no information is leaked during protocol execution, all operations that use secret data MUST run in constant time. This includes all prime-order group operations and proof-specific operations that operate on secret data, including proof generation and verification.</t>
      </section>
    </section>
    <section anchor="alternatives-considered">
      <name>Alternatives considered</name>
      <t>ARC uses the MACGGM algebraic MAC as its underlying primitive, as detailed in <xref target="KVAC"/> and <xref target="REVISITING_KVAC"/>. This offers the benefit of having a lower credential size than MACDDH, which is an alternative algebraic MAC detailed in <xref target="KVAC"/>.</t>
      <t>The BBS anonymous credential scheme, as detailed in <xref target="BBS"/> and its variants, is efficient and publicly verifiable, but requires pairings for verification. This is problematic for adoption because pairings are not supported as widely in software and hardware as non-pairing elliptic curves.</t>
      <t>It is possible to construct a keyed-verification variant of BBS which doesn't use pairings, as discussed in <xref target="BBDT17"/> and <xref target="REVISITING_KVAC"/>. However these keyed-verification BBS variants require more analysis, proofs of security properties, and review to be considered mature enough for safe deployment.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
    <section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>This section contains test vectors for the ARC ciphersuites specified in this document.</t>
      <section anchor="arcv1-p384">
        <name>ARCV1-P384</name>
        <artwork><![CDATA[
// ServerKey
x0 = 504650f53df8f16f6861633388936ea23338fa65ec36e0290022b48eb562889
d89dbfa691d1cde91517fa222ed7ad364
x1 = 803d955f0e073a04aa5d92b3fb739f56f9db001266677f62c095021db018cd8
cbb55941d4073698ce45c405d1348b7b1
x2 = a097e722ed2427de86966910acba9f5c350e8040f828bf6ceca27405420cdf3
d63cb3aef005f40ba51943c8026877963
xb = 3a349db178a923aa7dff7d2d15d89756fd293126bb49a6d793cd77d7db960f5
692fec3b7ec07602c60cd32aee595dffd
X0 = 02caa111a43a5909de4af5cb836897334e5a34857ffc3565223cad95a20f1f3
2303eb8f7594b286238f243eca1a79c60b8
X1 = 03ef0f59c9b0cc51c9e603dfcaa9a3e3719e186252b64f9ce1ebec352c5b605
b805af308a9bd697df7c97b0f1147108c3a
X2 = 028a9547a39d925bdd054706aa5ff7616c28aca94c92041c678970c52ee6572
2f2c54d4f6cecba66abd721ecbcdb2b8a04

// CredentialRequest
m1 = 5a32aaf031be0555089356d299ce24b0eedfe7939e2382934ab5b0f76aae441
24955d2c5ebf9b41d88786259c34692d2
m2 = ae93d3ea7e5856d5d951a0ae87f8845d767df2e97dd669c8025715e604cb1c4
3569792b6864f592fed3abe29b9ebc950
r1 = df2c61be3c0b37bc73dc89fc386c96b3008035081690bfde3b1e68b91443c22
cc791d244340fe957d5aa44d7313740df
r2 = 10fcb00134739cc403f27a79588ca05ad59c5e6ff560cc597c2b8ca25256c72
0bceca2ab03921492c5e9e4ad3b558002
m1_enc = 030a5167977e0c038a98fce96e127fc228aa58526f71a920044b74b2f22
dd5839f0e1cf871e6419a1f522e94510ccf2d92
m2_enc = 03a0fea0d3e83ee67b36cb86d8380d4b8420a75e23eb5dcb560a79e74d1
36cf3c382bff7576f7e50c2cd3d247b56dbf56d
proof = 6e2a6a8906c53eedc0620b8f635871aa2550acc551f0a61c05d7519cf605
5e28ebb737c44a7ba12376e8d4b21f79a0e91326907d2e24bdd176e575938fb5bf79
e4370e8031f3ba8143efa71622daea5338da386ab16ef76f72f6743b529dd603cb5a
3273dfdf24ec13c5b99c2a63a3e8640fd48530940f8faa7b623c882610bc29fbf74d
5c4a704db897798413c6db335357aef367aec11dba86cb07c30e5b46468ea788ccb4
3dcb8f39656328894b9c10465fb34cbb16304d1aa023353a85ef9afac0b123b5fc73
f1f8b7fc84e86e3981bb88e1557d7331bfac74ef986eb54902246a90ba5462ffd2b4
716030b7dd2b

// CredentialResponse
b = b8b2e8c2103ad6f1970e873420d82a21e699140babbe599f7dd8f6e3e8f615e5
f201d1c2b0bc2f821f19e80a0a0e1e7b
U = 02be890d43908e52ed43ae7bc7098f3a7694617fe44a88c33c6fa4eb9e942c0b
2bb9d2fd56a44e1d6094fc7b9e8b949055
enc_U_prime = 027f43377c69a2ad931cc21a9cc4d6ea85f84d517d197db721c931
276a9ed543a78055ddeb9cac6be3af34c212bca5f403
X0_aux = 02890d3f4287e7878ce88b2bc1cc818b2c40fee0f93187af43acb479259
979cef1c39d609ea69cc7d6ba1e2a55d107653f
X1_aux = 0345f2be0dd21d49437a82b221f7a9f074b352e8698fe6ffa08aecad480
e96e93a25b6dacd4531fc961e78cfb5503f0e69
X2_aux = 020f31991b9a40be69bc06ef30c250d9353a824f4da88cc43e63bf92bc8
ac8bca7e26bffed33a32cc124fd1fb6c73f8b77
H_aux = 03c7714830e1d72604e52fec595c7a399fe0f3276766f84425fd1f98764a
c76dab631c6dfd05e0200c4ffe6d6967304882
proof = 6e9e4447f3f25c407deb3ab2db763a66e38f14de53367c7bd278af37a130
ff5bd036e6967235f7d992c76cb3ec708569382040ab8d01958366ce5dc3e5de6f4c
9702ecc483518ae51785eb2157d1bcbadc4ead4897a8bbee36104468e9824c31804c
5f610bcbc752c2fa2e72a86f6ef82097712775dbfb8e83db2f6e19c09000b36a0250
56788238280c09a3c63c0705b6b17d42d50f2cf069b58a2a97cd1b51eeb92c117455
107881658393aef153156bcb2975aa33188f833c270dfd6588b9c559d3d48ecbfb84
ef558e0cf510bd06cd479710b20e488f4cf5e73e736958affe74e53cf755a7a4b6c1
08a4ef43de1204c6c83746d463c58683b448a188aa0bd2e0cb5f9bc920b5bb40a4e9
720bf8fa832614e9b53b1edcbc43496e459dec881e0aa5e1876e71e1125ebfae3e0d
e69d8fa45953e748adc562ea1e56d7f1eac95063ecd440c360294cc9cb8b4c27235a
8bf212631c466e9c0200f15498559ff4f7ac82dfdbe161dd06ae97dfd208d4b986e2
9a6f8e8b8f191b1ca70e95eb8068

// Credential
m1 = 5a32aaf031be0555089356d299ce24b0eedfe7939e2382934ab5b0f76aae441
24955d2c5ebf9b41d88786259c34692d2
U = 02be890d43908e52ed43ae7bc7098f3a7694617fe44a88c33c6fa4eb9e942c0b
2bb9d2fd56a44e1d6094fc7b9e8b949055
U_prime = 02bec70edf38a3f5c77d5c6f39afd5f94cd266f958c804a954f6104b57
a2c8310862a790cbc6b519f8db989d59aebaf081
X1 = 03ef0f59c9b0cc51c9e603dfcaa9a3e3719e186252b64f9ce1ebec352c5b605
b805af308a9bd697df7c97b0f1147108c3a

// Presentation1
presentation_context = 746573742070726573656e746174696f6e20636f6e746
57874
a = ad00ec0f71b7a8fb7c0aef35c7243e17b78e57df8f0a95d102ff12bbb97e15ed
35c23e54f9b4483d30b76772ee60d886
r = e5cab8c896187b61abe017e57022528742252210dd60ddbbf1a57e3b144e26dd
693b7644a9626a8c36896ede53d12930
z = f61f4c924d3ef04b31e9196935ff27c5f5a4bbcf14e55e357df9f5ccb5ded37b
2b14bc2e1a68e31f86416f0606ee75d1
U = 03383b2ad2831739bc86c0c98119f256e54c9d89a762a9fc91b3904eb3aee726
0350a19085ea093a8059369219f03da2c3
U_prime_commit = 034af7c09ee5150fc914a3bb0adf17f7e90af3c4d9246ec8c51
1f938467174113513b7577329cecd2a7bff0b97e43a9808
m1_commit = 02fb95e1d8010da0c63d38ca212c1f76d768cecc8aa26ab07e775570
70c8343e1da571230f071a15a03973cd57dc33ebf4
nonce = 0x0
tag = 0247e3fd325bc774c27329a78a62f616f5e409d3a4857609cecde3251140f2
bb101905c4cbe66fe06a779e44f5d9e97f08
proof = 87d00bb26882f9795f7aecebf37b05e0b60c5295242d67b3d37d2225e3a8
e67c6ba62896e06530b10296f631ee155be7e8e313c65e587ac6c540c2d2d00f6414
9d27fff086f8c20bcaa31bfae49e233955fe2a9740a7fa08f777efb039bec4c2e07e
3ee0dde1531578b338e0efda7b0ee28a5bad12586ded3c6b563e1529b29afee4a585
49d5be6fcb2252ddce23cf234a36a4fee968e57544d5977b7657c764eb767df50b73
9740dd268926ab22c8feb2c3e42d772e14a29166e8029c9425ef0000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
000000000004

// Presentation2
presentation_context = 746573742070726573656e746174696f6e20636f6e746
57874
a = a8e630484ba024bf9363805bc7a45f1695bcf45150a61f5c44a6cfbf343cd9e0
f593f127b6f49bec0f9b20f0550504a2
r = df6d39c3c0716d7cf8093073168bf967d7ed72750b6d366ed0febdc539b52d89
434f468a578c59d7ca9015b7da240ad6
z = 1b8e374ed4390e5a9023b309ecb94c0791eedfb168c556ff5ca3b89d047f482c
9279b47f584aab6c7f895f7674251771
U = 020c627c7ced92dd621860017ed29361bb78c4a17c8f7deb79f0c49a47723898
99a7e3b7b21e6a6c73abfca1332dc7df6e
U_prime_commit = 023d7eb948df3f49abe39e8ef32f4bb1bcca0f13f04836efd8b
7bc9bd0a73f915531ce845dc8c334d03c13647e5e4cc908
m1_commit = 036eea98df5b8248262fc5b511eef49bef1c2ec2a724df3e3a811296
fcf7891298d99a22f05ef0b08a2d00857117d88ac7
nonce = 0x1
tag = 03f9ceb1690ef6cd9c1b7d4c29dc86cf25565e4045ae431f8d28029e0405f9
ac251ef5a9e873f4a038ecd5a1e43d56bf5d
proof = da57015f71962f554d69220ee28618189b0a0c55ff9e6dc9d043d4a21b18
49be20ff10a5fc509d0c80b3e90d40421e95aa7d66fbf923dc72de9bf826b35f628c
69031fe4b8e899158fc7b4c9eae7965c3b5fb61096dd29cb950a8cc3f03f29ce00bd
0f6d548de12f1c0f87caca4382ec202bca6d82f95636b8268464ed0702b1ec96d8a9
1661d01ccfccf1f0bb8137be558a76edf2d6eb3c065026a941e99bc4a5a758fcab2e
5a33d83d24ef70da15eb4fc512fd74f468be64c56f41e971d22725a8fea08e69d0aa
b296ddf11d79e7e764f5f3aa00619235f71f78dfd91ee421371afd0c4c600a6e6c38
305d8c830ae2

]]></artwork>
      </section>
    </section>
    <section anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The authors would like to acknowledge helpful conversations with Tommy Pauly about rate limiting and Privacy Pass integration.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC8017">
          <front>
            <title>PKCS #1: RSA Cryptography Specifications Version 2.2</title>
            <author fullname="K. Moriarty" initials="K." role="editor" surname="Moriarty"/>
            <author fullname="B. Kaliski" initials="B." surname="Kaliski"/>
            <author fullname="J. Jonsson" initials="J." surname="Jonsson"/>
            <author fullname="A. Rusch" initials="A." surname="Rusch"/>
            <date month="November" year="2016"/>
            <abstract>
              <t>This document provides recommendations for the implementation of public-key cryptography based on the RSA algorithm, covering cryptographic primitives, encryption schemes, signature schemes with appendix, and ASN.1 syntax for representing keys and for identifying the schemes.</t>
              <t>This document represents a republication of PKCS #1 v2.2 from RSA Laboratories' Public-Key Cryptography Standards (PKCS) series. By publishing this RFC, change control is transferred to the IETF.</t>
              <t>This document also obsoletes RFC 3447.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8017"/>
          <seriesInfo name="DOI" value="10.17487/RFC8017"/>
        </reference>
        <reference anchor="I-D.irtf-cfrg-hash-to-curve">
          <front>
            <title>Hashing to Elliptic Curves</title>
            <author fullname="Armando Faz-Hernandez" initials="A." surname="Faz-Hernandez">
              <organization>Cloudflare, Inc.</organization>
            </author>
            <author fullname="Sam Scott" initials="S." surname="Scott">
              <organization>Cornell Tech</organization>
            </author>
            <author fullname="Nick Sullivan" initials="N." surname="Sullivan">
              <organization>Cloudflare, Inc.</organization>
            </author>
            <author fullname="Riad S. Wahby" initials="R. S." surname="Wahby">
              <organization>Stanford University</organization>
            </author>
            <author fullname="Christopher A. Wood" initials="C. A." surname="Wood">
              <organization>Cloudflare, Inc.</organization>
            </author>
            <date day="15" month="June" year="2022"/>
            <abstract>
              <t>This document specifies a number of algorithms for encoding or hashing an arbitrary string to a point on an elliptic curve.  This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.
              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-hash-to-curve-16"/>
        </reference>
        <reference anchor="KEYAGREEMENT">
          <front>
            <title>Recommendation for pair-wise key-establishment schemes using discrete logarithm cryptography</title>
            <author fullname="Elaine Barker" initials="E." surname="Barker">
              <organization/>
            </author>
            <author fullname="Lily Chen" initials="L." surname="Chen">
              <organization/>
            </author>
            <author fullname="Allen Roginsky" initials="A." surname="Roginsky">
              <organization/>
            </author>
            <author fullname="Apostol Vassilev" initials="A." surname="Vassilev">
              <organization/>
            </author>
            <author fullname="Richard Davis" initials="R." surname="Davis">
              <organization/>
            </author>
            <date month="April" year="2018"/>
          </front>
          <seriesInfo name="DOI" value="10.6028/nist.sp.800-56ar3"/>
          <refcontent>National Institute of Standards and Technology</refcontent>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="KVAC" target="https://eprint.iacr.org/2013/516">
          <front>
            <title>Keyed-Verification Anonymous Credentials from Algebraic MACs</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="REVISITING_KVAC" target="https://eprint.iacr.org/2024/1552">
          <front>
            <title>Revisiting Keyed-Verification Anonymous Credentials</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="BBS" target="https://eprint.iacr.org/2004/174">
          <front>
            <title>Short Group Signatures</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="BBDT17" target="https://link.springer.com/chapter/10.1007/978-3-319-69453-5_20">
          <front>
            <title>Improved Algebraic MACs and Practical Keyed-Verification Anonymous Credentials</title>
            <author>
              <organization/>
            </author>
            <date>n.d.</date>
          </front>
        </reference>
        <reference anchor="NISTCurves">
          <front>
            <title>Digital signature standard (DSS)</title>
            <author>
              <organization/>
            </author>
            <date year="2013"/>
          </front>
          <seriesInfo name="DOI" value="10.6028/nist.fips.186-4"/>
          <refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
        </reference>
        <reference anchor="SEC1" target="https://www.secg.org/sec1-v2.pdf">
          <front>
            <title>SEC 1: Elliptic Curve Cryptography</title>
            <author initials="" surname="Standards for Efficient Cryptography Group (SECG)">
              <organization/>
            </author>
            <date/>
          </front>
        </reference>
        <reference anchor="BLIND-RSA">
          <front>
            <title>RSA Blind Signatures</title>
            <author fullname="F. Denis" initials="F." surname="Denis"/>
            <author fullname="F. Jacobs" initials="F." surname="Jacobs"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="October" year="2023"/>
            <abstract>
              <t>This document specifies an RSA-based blind signature protocol. RSA blind signatures were first introduced by Chaum for untraceable payments. A signature that is output from this protocol can be verified as an RSA-PSS signature.</t>
              <t>This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9474"/>
          <seriesInfo name="DOI" value="10.17487/RFC9474"/>
        </reference>
        <reference anchor="OPRFS">
          <front>
            <title>Oblivious Pseudorandom Functions (OPRFs) Using Prime-Order Groups</title>
            <author fullname="A. Davidson" initials="A." surname="Davidson"/>
            <author fullname="A. Faz-Hernandez" initials="A." surname="Faz-Hernandez"/>
            <author fullname="N. Sullivan" initials="N." surname="Sullivan"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="December" year="2023"/>
            <abstract>
              <t>An Oblivious Pseudorandom Function (OPRF) is a two-party protocol between a client and a server for computing the output of a Pseudorandom Function (PRF). The server provides the PRF private key, and the client provides the PRF input. At the end of the protocol, the client learns the PRF output without learning anything about the PRF private key, and the server learns neither the PRF input nor output. An OPRF can also satisfy a notion of 'verifiability', called a VOPRF. A VOPRF ensures clients can verify that the server used a specific private key during the execution of the protocol. A VOPRF can also be partially oblivious, called a POPRF. A POPRF allows clients and servers to provide public input to the PRF computation. This document specifies an OPRF, VOPRF, and POPRF instantiated within standard prime-order groups, including elliptic curves. This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9497"/>
          <seriesInfo name="DOI" value="10.17487/RFC9497"/>
        </reference>
      </references>
    </references>
    <?line 1697?>



  </back>
  <!-- ##markdown-source:
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
pZWXgr6aqzOcOu232KyHi3yY0Lag3x1QbJCQovgTwOKoAotU/3ZwUSH42wFG
heNvBxkVmr8daKSyd4SNivOfBhw/HTYaUL5R2m2dqlcMtnXhcyd1a0ap5I8n
D9Wmsiaf/cf2V3odE9h8k2dsYbpNjPZFgOtvDb4JOH8RM7sTPvdgNLOdylfd
Glrbdg2Va6lo8HOjCSOFZztGf7RSULkq4/aW8VplSHN3peZGlMKri0KZ2ppk
ImENAvlLQmM15MO91q6t3nXcnuWT7bXc3bvh2uuDlt5pplCnEkpJX/Z2VoEM
nenuPKO97dU+QuObfrXdtiit+QLAR/AxCYsVf4m5Y0cmLc2ozaEgUWOQSj/r
z3DbR6WMrIc79gPxbpzqLBK1EQf8a2/qMvuruIV2VE/ts1P+1Kn6vphOee1a
k6XtKe3wy3esqdPJI/VeWLVlrKx35TEzt9aEdywFp/WX2Z2vf2kE6oPCC4aF
rdfVss/WV8NMSrNXUzWjzn3JWlNRfdU5W2zm2+zsLjXuoLI+KquH9mZlu+iu
YyvyOrVu3nvA7XY+2G5W6ggO2XazFN5Z3+3f5dm3FN7XPJP8I0R+wVtOe4v1
9Trnwx4Om+/kjujz4UWq9khrZKdWeLsE0su+RVY9w501daXs5Xbx245wS5SI
Jt2X9cjYK87bE+WOpdlbLMi2bOQZTSmc5bb4GDJL5+apTXfNZ2+dw5AMPTEP
FmjrQDGjE8iEBlonzx/+sexu41vAQR2DXRtlolVVNqi08a9z+lf7W6QdeyIp
0K8J4AMZOBOgtsSaUdNgt1z3CQDtO1FfrsztGX0uhjbVxsvt/aOtz9QPxdbO
bbPw0Cz88eNRnUugMahEjTlbPLbDXaOo1wu3ThloR29fDWb+HVHmreFl70kM
aj3fPlRFjwbN9wStmVyLC/P7wG5jzNpjOgmQbM1gxxbnWq17kf7fk76nZA7P
6FzOD5rGj9WWVPZBbC71ptxL8U4CX0C8jU8rirb1/7zhE0T+YvJMkqus/YNd
p0M5vXpQ489PIOM19/hLb7sak3YM7kPTFLQRalvzLethk9tpsa/eCfcZ1qv+
foFTTQQ8Jf0lVgWcPtsaOqVOZz6rD1EKfXBS9zjR9kbGynHciJ30ySxq8/cO
P/snO1uwG1tY7xebaaY3gLcKtpwCbzWkD9LaDkrhJyOXw6cK8uxZGq9nhQad
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
VFmq/cyrarl5OBzaCbqyrP8H7gDrcegaAQA=

-->

</rfc>
