<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-yun-privacypass-crypto-arc-00" category="info" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.31.0 -->
  <front>
    <title abbrev="ARC">Anonymous Rate-Limited Credentials</title>
    <seriesInfo name="Internet-Draft" value="draft-yun-privacypass-crypto-arc-00"/>
    <author initials="C." surname="Yun" fullname="Cathie Yun">
      <organization>Apple, Inc.</organization>
      <address>
        <email>cathieyun@gmail.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="October" day="20"/>
    <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-privacypass-crypto-arc.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-yun-privacypass-crypto-arc/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        PRIVACYPASS Privacy Pass mailing list (<eref target="mailto:privacy-pass@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/privacy-pass"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/privacy-pass/"/>.
      </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) = CreateCredentialRequest(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 CreateCredentialRequest(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="pseudocode"><![CDATA[
response = CreateCredentialResponse(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 CreateCredentialResponse(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];
} CredentialResponse
]]></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):
  return PresentationState(credential, presentationContext, [], 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];
} Presentation
]]></artwork>
          <t>The length of this structure is <tt>Npresentation = 4*Ne + 5*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, tag = 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).
  - 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.
- tag: Bytes, the value of the presentation tag used for rate limiting.

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)

  return validity, presentation.tag
]]></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 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 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 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 = t1 * generatorH (t1 = b * x1)
  5b. X1Aux = b * X1 (X1 = x1 * generatorH)
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. 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 = t1 * generatorH (t1 = b * x1)
  prover.Constrain(X1AuxVar, [(t1Var, genHVar)])
  # 5b. X1Aux = b * X1 (X1 = x1 * generatorH)
  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. 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 = t1 * generatorH (t1 = b * x1)
  verifier.Constrain(X1AuxVar, [(t1Var, genHVar)])
  # 5b. X1Aux = b * X1 (X1 = x1 * generatorH)
  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 + "CredentialPresentation")

  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 + "CredentialPresentation")

  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-256">
        <name>ARC(P-256)</name>
        <t>This ciphersuite uses P-256 <xref target="NISTCurves"/> for the Group.
The value of the ciphersuite identifier is "P256". The value of
contextString is "ARCV1-P256".</t>
        <ul spacing="normal">
          <li>
            <t>Group: P-256 (secp256r1) <xref target="NISTCurves"/>
            </t>
            <ul spacing="normal">
              <li>
                <t>Order(): Return 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551.</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
[1, <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 P256_XMD:SHA-256_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 = 48, <tt>expand_message_xmd</tt> with SHA-256, 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 = 33.</t>
              </li>
              <li>
                <t>DeserializeElement(buf): Implemented by attempting to deserialize a 33-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 = 32.</t>
              </li>
              <li>
                <t>DeserializeScalar(buf): Implemented by attempting to deserialize a Scalar from a 32-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 [1, 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 and is non-zero,
return the result. Otherwise, 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-request-unlinkability">
        <name>Credential Request 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 statistically 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="credential-issuance-unlinkability">
        <name>Credential Issuance Unlinkability</name>
        <t>The server commitment to <tt>x0</tt> is defined as <tt>X0 = x0 * G.generatorG() + x0Blinding * G.GeneratorH()</tt>, following the definitions in <xref target="KVAC"/>. This is computationally binding to the secret key <tt>x0</tt>. This means that unless the discrete log is broken, the credentials issued under one server commitment <tt>X0, X1, ...</tt> will all be issued under the same private keys <tt>x0, x1, ...</tt></t>
        <t>However, an adversary breaking the discrete log (e.g., a quantum adversary) can find pairs <tt>(x0, x0Blinding)</tt> and <tt>(x0', x0Blinding')</tt> both committing to <tt>X0</tt> and use them to issue different credentials. This capability would let the adversary partitioning the client anonymity set by linking clients to the underlying secret used for credential issuance, i.e., <tt>x0</tt> or <tt>x0'</tt>. This requires an active attack and therefore is not an immediate concern.</t>
        <t>Statistical anonymity is possible by committing to <tt>x0</tt> and x0Blinding` separately, as in <xref target="REVISITING_KVAC"/>. However, the security of this construction requires additional analysis.</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-p256">
        <name>ARCV1-P256</name>
        <artwork><![CDATA[
// ServerKey
x0 = 3338fa65ec36e0290022b48eb562889d89dbfa691d1cde91517fa222ed7ad36
4
x1 = f9db001266677f62c095021db018cd8cbb55941d4073698ce45c405d1348b7b
1
x2 = 350e8040f828bf6ceca27405420cdf3d63cb3aef005f40ba51943c802687796
3
xb = fd293126bb49a6d793cd77d7db960f5692fec3b7ec07602c60cd32aee595dff
d
X0 = 0232b5e93dc2ff489c20a986a84757c5cc4512f057e1ea92011a26d3ad2c562
88d
X1 = 03c413230a9bd956718aa46138a33f774f4c708d61c1d6400d404243049d4a3
1dc
X2 = 02db00f6f8e6d235786a120017bd356fe1c9d09069d3ac9352cc9be10ef1505
a55

// CredentialRequest
Blinding_0 = 0000000000000000000000000000000000000000000000000000000
000000001
Blinding_1 = 0000000000000000000000000000000000000000000000000000000
000000002
Blinding_2 = 0000000000000000000000000000000000000000000000000000000
000000003
Blinding_3 = 0000000000000000000000000000000000000000000000000000000
000000004
request_context = 74657374207265717565737420636f6e74657874
m1 = eedfe7939e2382934ab5b0f76aae44124955d2c5ebf9b41d88786259c34692d
2
m2 = 911fb315257d9ae29d47ecb48c6fa27074dee6860a0489f8db6ac9a486be6a3
e
r1 = 008035081690bfde3b1e68b91443c22cc791d244340fe957d5aa44d7313740d
f
r2 = d59c5e6ff560cc597c2b8ca25256c720bceca2ab03921492c5e9e4ad3b55800
2
m1_enc = 03b8f11506a5302424143573e087fa20195cb5e893a67ef354eae3a78e2
63c54e4
m2_enc = 03f1ae4d7b78ba8030bd63859d4f4a909395c52bda34716b6620a2fdd52
b336fc9
proof = 0f361327abbc724ff0d37db365065bc4bd60e18125842bb4c03a7e5a632a
1e95e74dcc440fcb9fb39106922e0d2544e6c82ca710abf35e8b10bf5d61296c9adb
7d683eaed9a76a755b73f2b4b6e763a7c7883ce4b5c21bd02cd96b9af18cfb227f1a
cb4ead77c85049d291ed7841405610843f163e9cc2f6a8869111582324cd32bf1300
0c129d274ccf5386cb90e839916d5dff7eade18e3eabec415f613911

// CredentialResponse
Blinding_0 = 0000000000000000000000000000000000000000000000000000000
000000001
Blinding_1 = 0000000000000000000000000000000000000000000000000000000
000000002
Blinding_2 = 0000000000000000000000000000000000000000000000000000000
000000003
Blinding_3 = 0000000000000000000000000000000000000000000000000000000
000000004
Blinding_4 = 0000000000000000000000000000000000000000000000000000000
000000005
Blinding_5 = 0000000000000000000000000000000000000000000000000000000
000000006
Blinding_6 = 0000000000000000000000000000000000000000000000000000000
000000007
b = e699140babbe599f7dd8f6e3e8f615e5f201d1c2b0bc2f821f19e80a0a0e1e7b
U = 033ee1ebbcff622bc26b10932ed1eb147226d832048fb2337dc0ad7722cb0748
3d
enc_U_prime = 035b8e09ce8776f1a2c7ef8610c9a6a39936c5666ab8b28d6629d3
685056716482
X0_aux = 02d453c121324114367906bd11ffc3b6e6a77b75382497279b1a60ab841
2c1dec6
X1_aux = 03b0e4b1f376c6207bf34efda46ce54b132a20b90bc28b9152f3e441fe2
b508b63
X2_aux = 0327369efcb7577abaeb7b56940e6e042126900bdf8bd8944c0adbb7be3
ad98e2a
H_aux = 03d3cd09eeb8d19716586a49260c69309c495a717a36cad3381f6c02ac80
b70e64
proof = dd4596175db0b4273fcdff330370d2b5e7a4bf92bf518141f4553af37ef0
e1260cb8312affc2462800adba102117448b449985d1704d8afd0df9ac708231561d
ca56faae325cb56b0a9e8ad07bdc6ce90f6e7430090e970a7240e289218de7a17672
bea9a66187d102ffef976fb01af69d8d3aa3156a5a4223dc6d08b8ce9f1d2639a2ed
c7052404bf1410adf6c41465bd687e3dfa5372ea71f804b56d947bae9482e5707f42
dbe35f8b0e11b4a0d27a5a01e1b9a75b66d82b7945eb0b002ee400bebcdc4c3133f8
04b22bd2d771762058cc35a5033365d2e15150fe46d3b0e98e18ee55f0451b0b1714
20f73592292e4ff50603c1f0d7769dbd090936090f63

// Credential
m1 = eedfe7939e2382934ab5b0f76aae44124955d2c5ebf9b41d88786259c34692d
2
U = 033ee1ebbcff622bc26b10932ed1eb147226d832048fb2337dc0ad7722cb0748
3d
U_prime = 02637fe04cc143281ee607bd8f898e670293dce44a2840b9cbb9e0d1fc
7a2b29b4
X1 = 03c413230a9bd956718aa46138a33f774f4c708d61c1d6400d404243049d4a3
1dc

// Presentation1
Blinding_0 = 0000000000000000000000000000000000000000000000000000000
000000001
Blinding_1 = 0000000000000000000000000000000000000000000000000000000
000000002
Blinding_2 = 0000000000000000000000000000000000000000000000000000000
000000003
Blinding_3 = 0000000000000000000000000000000000000000000000000000000
000000004
presentation_context = 746573742070726573656e746174696f6e20636f6e746
57874
a = b78e57df8f0a95d102ff12bbb97e15ed35c23e54f9b4483d30b76772ee60d886
r = 42252210dd60ddbbf1a57e3b144e26dd693b7644a9626a8c36896ede53d12930
z = f5a4bbcf14e55e357df9f5ccb5ded37b2b14bc2e1a68e31f86416f0606ee75d1
U = 032704f22133d2ec70f9e6f4bbf64c582220b666f2e2c1d37c3f8995a2a5568c
7e
U_prime_commit = 03533cf1b2fd53a0716e02425eb42e4c55835aa6b2992d364cb
a70810d0f8aeb51
m1_commit = 03e412408579105213ed10b6447c85bcd672ba73ecae1e21c463d0df
4ef7beb814
nonce = 0x0
tag = 031a774fd87a8f18f6420bea43cf5425e7426eec8ba7b8df5c13dc05f10ec6
52d9
proof = a558da5f17c04adcb0898827aaded14be1dc612dcd12b0579c11bb387ce9
ae4b7dbcb3bbe413caaaf754d99e5a342abb7e0041458d670f4b58eda37e745a6752
95d7a7b86248141d6547b53d793e5c77896ec4dc8dd438ab66d9c8b43ef6b060938a
1ca793057b154970ebc3c7ec3a23134e0852d0041f9098ce77311e5b5eca00000000
00000000000000000000000000000000000000000000000000000004

// Presentation2
Blinding_0 = 0000000000000000000000000000000000000000000000000000000
000000001
Blinding_1 = 0000000000000000000000000000000000000000000000000000000
000000002
Blinding_2 = 0000000000000000000000000000000000000000000000000000000
000000003
Blinding_3 = 0000000000000000000000000000000000000000000000000000000
000000004
presentation_context = 746573742070726573656e746174696f6e20636f6e746
57874
a = 95bcf45150a61f5c44a6cfbf343cd9e0f593f127b6f49bec0f9b20f0550504a2
r = d7ed72750b6d366ed0febdc539b52d89434f468a578c59d7ca9015b7da240ad6
z = 91eedfb168c556ff5ca3b89d047f482c9279b47f584aab6c7f895f7674251771
U = 035fd233dee2c147155c6008ea64941b6ff7b315aced12531468f2e27bf22e3e
f0
U_prime_commit = 02434af337b87fd21d1e3d950aebfc8033a3d2e9dd2bb8b9e79
53488078754496d
m1_commit = 02a578fd3a84eb5b657367b02de39b45fd48ab7781ef8f94efe60127
4a5ded2a07
nonce = 0x1
tag = 03084fe6fff0ecc7c33ef5c49b492dda38083f52e9a2b70b88f3d4b4ba7b50
afba
proof = 050965cde906fc4723333b100ce0fd9f7b026315f1db16984d4cccb2bc4a
a65eb7a17f5b8dfe4f14d40006506ee5fb323e829dd4cb9dc3c455b2e04dd691600a
ec3cc3f1939198a80acb78b7f90b3bff769cab890f33e4d69b7c302d21ad35ec457d
048d3ed7d13ee82c3c0aac2129ad0c8375cf29cd8ea3948a16b9247b1cc5faf69a31
16f903b9dcccc4eff31f026041e49797b53c87eca66cfe1040187ef7

]]></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. F." 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 month="February" year="2023"/>
          </front>
          <seriesInfo name="DOI" value="10.6028/nist.fips.186-5"/>
          <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 1756?>



  </back>
  <!-- ##markdown-source:
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
7av1CjVeUalSA/aVLgsdGCojb+nZV+1HQ7yNy4Pk7d97K7pdFV15N/jeil5X
Ra+8UGg/tShwoAyBpPG6Gq6q4eoa3nU1PFXDUzWeXlPhqSyvwKgKrW8ZZHUk
SHneKMa9dJoxbs0K1GJdFWF3Bmxdfbi6j1awTi3tCvG6WvJ0S13x9z37xlHh
vb1xYatfNTnUc9Q1hE8LJDunpeqxMQ+KlnLM14ah924ViHbMXkVK0TmBN49d
r2le8pbFpRzeteHuvVsFvB0i1erfM8bWCpCbcfE1TRbdgtodTXe09aopdk8M
4u4WfVPNPFus5/wV6FGrCW6BxURd2SYHri6SVQfeVkIj9zhVLOkahelbDEY7
ytIosdK+kR9Jvmmnd/u1mVo64ZaLM7e8CKQjN/Bbh89/3kh0wxj3N7mR6NOX
y8z4+RMi6E+IoT8hiv4McfTdI+lPiKXvHE3/4RJaX2pV8jf45uOTrf2d1iS7
EgE7lggvnQMz6t9VSi43Xu5fbryUS5fNeH5nz2VEbwTtOwq3wvYd5QpJaLGf
0OL/o3XRMiDfVe/VgXlRV0dsvquiGZ2XDXSG6btauEGgvrPq9aH6zqo3CtZ3
0yxD43LEXXH7bqqblTtC+N10Nyu3o/lddZ82qn5iYN+xgv0rhPZdvdw1uO9q
68uE9x09/9oBfuf0/FYhfucsfs4g/5oOvkCY3ylcnxroX9PoLUP9jtb+kMF+
xzg+c7jf3lCjbGZjR03tCG+9l6bjTHV9JFvreO7rvnagM+oPG2GZcSSn+rbR
OHGrOrhVfxyxCN+K8nRLPqxVxg90Sgb185PTdW8SsPM1X02UVzDsunEBRl3f
CtB1FQDs9I1PT9W90BDUNQTqsoDRsDxXtbxAoPvKp65tHr/dPQNV/uZuR0jf
6gDp748fPnnyvbrGyNgb8AmnSH/GM6SNwOql0eKND/X+33HD8i3uvntdny+W
2wsxX4vy239OAHRtwtEDnV+VH00l9TnL6pfTUEu/fLaWqvPX95+93j4TnPXG
GHd9vOVM6Y+ef719JHXCvuz3QL/ccSvJYHPHrSQ8P799GuWGezM+zWp3up8b
mPJbbdAwSbzpZ0W1O3L4DqY9NX45IMRASOaZ2LeXYrBBwcGGSvJw9hTl9wdq
2F9488LNNhK82V3EmP2DujDIdIz8e//2iLK6/pOqvt5X5zUKv77hXoPajUnq
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
V5b1/wDvmIyFKh0BAA==

-->

</rfc>
