<?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-schlesinger-cfrg-act-00" category="info" submissionType="IRTF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.30.0 -->
  <front>
    <title abbrev="ACT">Anonymous Credit Tokens</title>
    <seriesInfo name="Internet-Draft" value="draft-schlesinger-cfrg-act-00"/>
    <author fullname="Samuel Schlesinger">
      <organization>Google</organization>
      <address>
        <email>samschlesinger@google.com</email>
      </address>
    </author>
    <author fullname="Jonathan Katz">
      <organization>Google</organization>
      <address>
        <email>jkcrypto@google.com</email>
      </address>
    </author>
    <date year="2025" month="August" day="18"/>
    <abstract>
      <?line 64?>

<t>This document specifies Anonymous Credit Tokens (ACT), a
privacy-preserving authentication protocol that enables numerical
credit systems without tracking individual clients. Based on
keyed-verification anonymous credentials and privately verifiable
BBS-style signatures, the protocol allows issuers to grant tokens
containing credits that clients can later spend anonymously with
that issuer.</t>
      <t>The protocol's key features include: (1) unlinkable transactions -
the issuer cannot correlate credit issuance with spending, or link
multiple spends by the same client, (2) partial spending - clients
can spend a portion of their credits and receive anonymous change,
and (3) double-spend prevention through cryptographic nullifiers
that preserve privacy while ensuring each token is used only once.</t>
      <t>Anonymous Credit Tokens are designed for modern web services
requiring rate limiting, usage-based billing, or resource allocation
while respecting user privacy. Example applications include rate
limiting and API credits.</t>
      <t>This document is a product of the Crypto Forum Research Group (CFRG)
in the IRTF.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://SamuelSchlesinger.github.io/draft-act/draft-schlesinger-cfrg-act.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-schlesinger-cfrg-act/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Crypto Forum Research Group mailing list (<eref target="mailto:cfrg@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/cfrg"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/cfrg/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/SamuelSchlesinger/draft-act"/>.</t>
    </note>
  </front>
  <middle>
    <?line 89?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>Modern web services face a fundamental tension between operational
needs and user privacy. Services need to implement rate limiting to
prevent abuse, charge for API usage to sustain operations, and
allocate computational resources fairly. However, traditional
approaches require tracking client identities and creating detailed
logs of client behavior, raising significant privacy concerns in an
era of increasing data protection awareness and regulation.</t>
      <t>Anonymous Credit Tokens (ACT) helps to resolve this tension by
providing a cryptographic protocol that enables credit-based systems
without client tracking. Built on keyed-verification anonymous
credentials <xref target="KVAC"/> and privately verifiable BBS-style signatures
<xref target="BBS"/>, the protocol allows services to issue, track, and spend
credits while maintaining client privacy.</t>
      <section anchor="key-properties">
        <name>Key Properties</name>
        <t>The protocol provides four essential properties that make it
suitable for privacy-preserving credit systems:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Unlinkability</strong>: The issuer cannot link credit issuance to
spending, or connect multiple transactions by the same client.
This property is information-theoretic, not merely computational.</t>
          </li>
          <li>
            <t><strong>Partial Spending</strong>: Clients can spend any amount up to their
balance and receive anonymous change without revealing their
previous or current
balance, enabling flexible spending.</t>
          </li>
          <li>
            <t><strong>Double-Spend Prevention</strong>: Cryptographic nullifiers ensure each
token is used only once, without linking it to issuance.</t>
          </li>
          <li>
            <t><strong>Balance Privacy</strong>: During spending, only the amount being spent
is revealed, not the total balance in the token, protecting
clients from balance-based profiling.</t>
          </li>
          <li>
            <t><strong>Performance</strong>: The protocol's operations are performant enough
to make it useful in modern web systems. This protocol has
performance characteristics which make it suitable for a large
number of applications.</t>
          </li>
        </ol>
      </section>
      <section anchor="use-cases">
        <name>Use Cases</name>
        <t>Anonymous Credit Tokens can be applied to various scenarios:</t>
        <ul spacing="normal">
          <li>
            <t><strong>Rate Limiting</strong>: Services can issue daily credit allowances that
clients spend anonymously for API calls or resource access.</t>
          </li>
          <li>
            <t><strong>API Credits</strong>: API providers can sell credit packages that
developers use to pay for API requests without creating a detailed
usage history linked to their identity. This enables:  </t>
            <ul spacing="normal">
              <li>
                <t>Pre-paid API access without requiring credit cards for each
transaction</t>
              </li>
              <li>
                <t>Anonymous API usage for privacy-sensitive applications</t>
              </li>
              <li>
                <t>Usage-based billing without tracking individual request patterns</t>
              </li>
              <li>
                <t>Protection against competitive analysis through usage monitoring</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="protocol-overview">
        <name>Protocol Overview</name>
        <t>The protocol involves two parties: an issuer (typically a service
provider) and clients (typically users of the service). The
interaction follows three main phases:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Setup</strong>: The issuer generates a key pair and publishes the
public key.</t>
          </li>
          <li>
            <t><strong>Issuance</strong>: A client requests credits from the issuer. The
issuer creates a blind signature on the credit value and a
client-chosen nullifier, producing a credit token.</t>
          </li>
          <li>
            <t><strong>Spending</strong>: To spend credits, the client reveals a nullifier
and proves possession of a valid token associated with that
nullifier having sufficient balance. The issuer verifies the
proof, checks the nullifier hasn't been used before, and issues a
new token (which remains hidden from the issuer) for any remaining
balance.</t>
          </li>
        </ol>
      </section>
      <section anchor="design-goals">
        <name>Design Goals</name>
        <t>The protocol is designed with the following goals:</t>
        <ul spacing="normal">
          <li>
            <t><strong>Privacy</strong>: The issuer cannot link credit tokens to specific clients or link
multiple transactions by the same client.</t>
          </li>
          <li>
            <t><strong>Security</strong>: Clients cannot spend more credits than they possess or use the
same credits multiple times.</t>
          </li>
          <li>
            <t><strong>Efficiency</strong>: All operations should be computationally efficient, suitable
for high-volume web services.</t>
          </li>
          <li>
            <t><strong>Simplicity</strong>: The protocol should be straightforward to implement and
integrate into existing systems relative to other comparable solutions.</t>
          </li>
        </ul>
      </section>
      <section anchor="relation-to-existing-work">
        <name>Relation to Existing Work</name>
        <t>This protocol builds upon several cryptographic primitives:</t>
        <ul spacing="normal">
          <li>
            <t><strong>BBS Signatures</strong> <xref target="BBS"/>: The core signature scheme that enables efficient
proofs of possession. We use a variant that is privately verifiable, which
avoids the need for pairings and makes our protocol more efficient.</t>
          </li>
          <li>
            <t><strong>Sigma Protocols</strong> <xref target="ORRU-SIGMA"/>: The zero-knowledge proof framework used
for spending proofs.</t>
          </li>
          <li>
            <t><strong>Fiat-Shamir Transform</strong> <xref target="ORRU-FS"/>: The technique to make the interactive
proofs non-interactive.</t>
          </li>
        </ul>
        <t>The protocol can be viewed as a specialized instantiation of keyed-verification
anonymous credentials <xref target="KVAC"/> optimized for numerical values and partial
spending.</t>
      </section>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<section anchor="notation">
        <name>Notation</name>
        <t>This document uses the following notation:</t>
        <ul spacing="normal">
          <li>
            <t><tt>||</tt>: Concatenation of byte strings</t>
          </li>
          <li>
            <t><tt>x &lt;- S</tt>: Sampling x uniformly from the set S</t>
          </li>
          <li>
            <t><tt>x := y</tt>: Assignment of the value y to the variable x</t>
          </li>
          <li>
            <t><tt>[n]</tt>: The set of integers {0, 1, ..., n-1}</t>
          </li>
          <li>
            <t><tt>|x|</tt>: The length of byte string x</t>
          </li>
          <li>
            <t><tt>0x</tt> prefix: Hexadecimal values</t>
          </li>
          <li>
            <t>We use additive notation for group operations, so group elements are added
together like <tt>a + b</tt> and scalar multiplication of a group element by a scalar
is written as <tt>a * n</tt>, with group element <tt>a</tt> and scalar <tt>n</tt>.</t>
          </li>
        </ul>
      </section>
      <section anchor="data-types">
        <name>Data Types</name>
        <t>The protocol uses the following data types:</t>
        <ul spacing="normal">
          <li>
            <t><strong>Scalar</strong>: An integer modulo the group order q</t>
          </li>
          <li>
            <t><strong>Element</strong>: An element of the Ristretto255 group</t>
          </li>
          <li>
            <t><strong>ByteString</strong>: A sequence of bytes</t>
          </li>
        </ul>
      </section>
      <section anchor="cryptographic-parameters">
        <name>Cryptographic Parameters</name>
        <t>The protocol uses the Ristretto group <xref target="RFC9496"/>, which provides a prime-order
group abstraction over Curve25519. It would be easy to adapt this approach to
using any other prime order group based on the contents of this document. The
key parameters are:</t>
        <ul spacing="normal">
          <li>
            <t><strong>q</strong>: The prime order of the group (2^252 + 27742317777372353535851937790883648493)</t>
          </li>
          <li>
            <t><strong>G</strong>: The standard generator of the Ristretto group</t>
          </li>
          <li>
            <t><strong>L</strong>: The bit length for credit values</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="protocol-specification">
      <name>Protocol Specification</name>
      <section anchor="system-parameters">
        <name>System Parameters</name>
        <t>The protocol requires the following system parameters:</t>
        <artwork><![CDATA[
Parameters:
  - G: Generator of the Ristretto group
  - H1, H2, H3: Additional generators for commitments
  - L: Bit length for credit values (configurable, must satisfy L <= 252)
]]></artwork>
        <t>The generators H1, H2, and H3 <bcp14>MUST</bcp14> be generated deterministically from a
nothing-up-my-sleeve value to ensure they are independent of each other and of
G. This prevents attacks whereby malicious parameters could compromise security. Note that these generators are independent of the choice of L.</t>
        <artwork><![CDATA[
GenerateParameters(domain_separator):
  Input:
    - domain_separator: ByteString identifying the deployment
  Output:
    - params: System parameters (H1, H2, H3)

  Steps:
    1. seed = BLAKE3(LengthPrefixed(domain_separator))
    2. counter = 0
    3. H1 = HashToRistretto255(seed, counter++)
    4. H2 = HashToRistretto255(seed, counter++)
    5. H3 = HashToRistretto255(seed, counter++)
    6. return (H1, H2, H3)

HashToRistretto255(seed, counter):
  Input:
    - seed: 32-byte seed value
    - counter: Integer counter for domain separation
  Output:
    - P: A valid Ristretto255 point

  Steps:
    1. hasher = BLAKE3.new()
    2. hasher.update(LengthPrefixed(domain_separator))
    3. hasher.update(LengthPrefixed(seed))
    4. hasher.update(LengthPrefixed(counter.to_le_bytes(4)))
    5. uniform_bytes = hasher.finalize_xof(64)
    6. P = OneWayMap(uniform_bytes)
    7. return P
]]></artwork>
        <t>The domain_separator <bcp14>MUST</bcp14> be unique for each deployment to ensure
cryptographic isolation between different services. The domain separator <bcp14>SHOULD</bcp14>
follow this structured format:</t>
        <artwork><![CDATA[
domain_separator = "ACT-v1:" || organization || ":" || service || ":" || deployment_id || ":" || version
]]></artwork>
        <t>Where:</t>
        <ul spacing="normal">
          <li>
            <t><tt>organization</tt>: A unique identifier for the organization (e.g., "example-corp", "acme-inc")</t>
          </li>
          <li>
            <t><tt>service</tt>: The specific service or application name (e.g., "payment-api", "rate-limiter")</t>
          </li>
          <li>
            <t><tt>deployment_id</tt>: The deployment environment (e.g., "production", "staging", "us-west-1")</t>
          </li>
          <li>
            <t><tt>version</tt>: An ISO 8601 date (YYYY-MM-DD) indicating when parameters were generated</t>
          </li>
        </ul>
        <t>Example: <tt>"ACT-v1:example-corp:payment-api:production:2024-01-15"</tt></t>
        <t>This structured format ensures:
1. Protocol identification through the "ACT-v1:" prefix
2. Organizational namespace isolation
3. Service-level separation within organizations
4. Environment isolation (production vs staging)
5. Version tracking for parameter updates</t>
        <t>Using generic or unstructured domain separators creates security risks through
parameter collision and <bcp14>MUST NOT</bcp14> be used. When parameters need to be updated
(e.g., for security reasons or protocol upgrades), a new version date <bcp14>MUST</bcp14> be
used, creating entirely new parameters.</t>
        <t>The OneWayMap function is defined in <xref target="RFC9496"/> Section 4.3.4, which provides a
cryptographically secure mapping from uniformly random byte strings to valid
Ristretto255 points.</t>
      </section>
      <section anchor="key-generation">
        <name>Key Generation</name>
        <t>The issuer generates a key pair as follows:</t>
        <artwork><![CDATA[
KeyGen():
  Input: None
  Output:
    - sk: Private key (Scalar)
    - pk: Public key (Group Element)

  Steps:
    1. x <- Zq
    2. W = G * x
    3. sk = x
    4. pk = W
    5. return (sk, pk)
]]></artwork>
      </section>
      <section anchor="token-issuance">
        <name>Token Issuance</name>
        <t>The issuance protocol is an interactive protocol between a client and the
issuer:</t>
        <section anchor="client-issuance-request">
          <name>Client: Issuance Request</name>
          <artwork><![CDATA[
IssueRequest():
  Output:
    - request: Issuance request
    - state: Client state for later verification

  Steps:
    1. k <- Zq  // Nullifier (will prevent double-spending)
    2. r <- Zq  // Blinding factor
    3. K = H2 * k + H3 * r
    4. // Generate proof of knowledge of k, r
    5. k' <- Zq
    6. r' <- Zq
    7. K1 = H2 * k' + H3 * r'
    8. transcript = CreateTranscript("request")
    9. AddToTranscript(transcript, K)
    10. AddToTranscript(transcript, K1)
    11. gamma = GetChallenge(transcript)
    12. k_bar = k' + gamma * k
    13. r_bar = r' + gamma * r
    14. request = (K, gamma, k_bar, r_bar)
    15. state = (k, r)
    16. return (request, state)
]]></artwork>
        </section>
        <section anchor="issuer-issuance-response">
          <name>Issuer: Issuance Response</name>
          <artwork><![CDATA[
Issue(sk, request, c):
  Input:
    - sk: Issuer's private key
    - request: Client's issuance request
    - c: Credit amount to issue (c > 0)
  Output:
    - response: Issuance response or INVALID

  Steps:
    1. Parse request as (K, gamma, k_bar, r_bar)
    2. // Verify proof of knowledge
    3. K1 = H2 * k_bar + H3 * r_bar - K * gamma
    4. transcript = CreateTranscript("request")
    5. AddToTranscript(transcript, K)
    6. AddToTranscript(transcript, K1)
    7. if GetChallenge(transcript) != gamma:
    8.     return INVALID
    9. // Create BBS signature on (c, k, r)
    10. e <- Zq
    11. A = (G + H1 * c + K) * (1/(e + sk))  // K = H2 * k + H3 * r
    12. // Generate proof of correct computation
    13. alpha <- Zq
    14. Y_A = A * alpha
    15. Y_G = G * alpha
    16. X_A = G + H1 * c + K
    17. X_G = G * e + pk
    18. transcript_resp = CreateTranscript("respond")
    19. AddToTranscript(transcript_resp, c)
    20. AddToTranscript(transcript_resp, e)
    21. AddToTranscript(transcript_resp, A)
    22. AddToTranscript(transcript_resp, X_A)
    23. AddToTranscript(transcript_resp, X_G)
    24. AddToTranscript(transcript_resp, Y_A)
    25. AddToTranscript(transcript_resp, Y_G)
    26. gamma_resp = GetChallenge(transcript_resp)
    27. z = gamma_resp * (sk + e) + alpha
    28. response = (A, e, gamma_resp, z, c)
    29. return response
]]></artwork>
        </section>
        <section anchor="client-token-verification">
          <name>Client: Token Verification</name>
          <artwork><![CDATA[
VerifyIssuance(pk, request, response, state):
  Input:
    - pk: Issuer's public key
    - request: The issuance request sent
    - response: Issuer's response
    - state: Client state from request generation
  Output:
    - token: Credit token or INVALID

  Steps:
    1. Parse request as (K, gamma, k_bar, r_bar)
    2. Parse response as (A, e, gamma_resp, z, c)
    3. Parse state as (k, r)
    4. // Verify proof
    6. X_A = G + H1 * c + K
    7. X_G = G * e + pk
    8. Y_A = A * z - X_A * gamma_resp
    9. Y_G = G * z - X_G * gamma_resp
    10. transcript_resp = CreateTranscript("respond")
    11. AddToTranscript(transcript_resp, c)
    12. AddToTranscript(transcript_resp, e)
    13. AddToTranscript(transcript_resp, A)
    14. AddToTranscript(transcript_resp, X_A)
    15. AddToTranscript(transcript_resp, X_G)
    16. AddToTranscript(transcript_resp, Y_A)
    17. AddToTranscript(transcript_resp, Y_G)
    18. if GetChallenge(transcript_resp) != gamma_resp:
    19.     return INVALID
    20. token = (A, e, k, r, c)
    21. return token
]]></artwork>
        </section>
      </section>
      <section anchor="token-spending">
        <name>Token Spending</name>
        <t>The spending protocol allows a client to spend s credits from a token
containing c credits (where 0 &lt; s &lt;= c):</t>
        <section anchor="client-spend-proof-generation">
          <name>Client: Spend Proof Generation</name>
          <artwork><![CDATA[
ProveSpend(token, s):
  Input:
    - token: Credit token (A, e, k, r, c)
    - s: Amount to spend (0 < s <= c)
  Output:
    - proof: Spend proof
    - state: Client state for receiving change

  Steps:
    1. // Randomize the signature
    2. r1, r2 <- Zq
    3. B = G + H1 * c + H2 * k + H3 * r
    4. A' = A * (r1 * r2)
    5. B_bar = B * r1
    6. r3 = 1/r1

    7. // Generate initial proof components
    8. c' <- Zq
    9. r' <- Zq
    10. e' <- Zq
    11. r2' <- Zq
    12. r3' <- Zq

    13. // Compute first round messages
    14. A1 = A' * e' + B_bar * r2'
    15. A2 = B_bar * r3' + H1 * c' + H3 * r'

    16. // Decompose c - s into bits
    17. m = c - s
    18. (i[0], ..., i[L-1]) = BitDecompose(m)  // See Section 3.7

    19. // Create commitments for each bit
    20. k* <- Zq
    21. s[0] <- Zq
    22. Com[0] = H1 * i[0] + H2 * k* + H3 * s[0]
    23. For j = 1 to L-1:
    24.     s[j] <- Zq
    25.     Com[j] = H1 * i[j] + H3 * s[j]

    26. // Initialize range proof arrays
    27. C = array[L][2]
    28. C' = array[L][2]
    29. gamma0 = array[L]
    30. z = array[L][2]

    31. // Process bit 0 (with k* component)
    32. C[0][0] = Com[0]
    33. C[0][1] = Com[0] - H1
    34. k0' <- Zq
    35. s_prime = array[L]
    36. s_prime[0] <- Zq
    37. gamma0[0] <- Zq
    38. w0 <- Zq
    39. z[0] <- Zq

    40. if i[0] == 0:
    41.     C'[0][0] = H2 * k0' + H3 * s_prime[0]
    42.     C'[0][1] = H2 * w0 + H3 * z[0] - C[0][1] * gamma0[0]
    43. else:
    44.     C'[0][0] = H2 * w0 + H3 * z[0] - C[0][0] * gamma0[0]
    45.     C'[0][1] = H2 * k0' + H3 * s_prime[0]

    46. // Process remaining bits
    47. For j = 1 to L-1:
    48.     C[j][0] = Com[j]
    49.     C[j][1] = Com[j] - H1
    50.     s_prime[j] <- Zq
    51.     gamma0[j] <- Zq
    52.     z[j] <- Zq
    53.
    54.     if i[j] == 0:
    55.         C'[j][0] = H3 * s_prime[j]
    56.         C'[j][1] = H3 * z[j] - C[j][1] * gamma0[j]
    57.     else:
    58.         C'[j][0] = H3 * z[j] - C[j][0] * gamma0[j]
    59.         C'[j][1] = H3 * s_prime[j]

    60. // Compute K' commitment
    61. K' = Sum(Com[j] * 2^j for j in [L])
    62. r* = Sum(s[j] * 2^j for j in [L])
    63. k' <- Zq
    64. s' <- Zq
    65. C = H1 * (-c') + H2 * k' + H3 * s'

    66. // Generate challenge using transcript
    67. transcript = CreateTranscript("spend")
    68. AddToTranscript(transcript, k)
    69. AddToTranscript(transcript, A')
    70. AddToTranscript(transcript, B_bar)
    71. AddToTranscript(transcript, A1)
    72. AddToTranscript(transcript, A2)
    73. For j = 0 to L-1:
    74.     AddToTranscript(transcript, Com[j])
    75. For j = 0 to L-1:
    76.     AddToTranscript(transcript, C'[j][0])
    77.     AddToTranscript(transcript, C'[j][1])
    78. AddToTranscript(transcript, C)
    79. gamma = GetChallenge(transcript)

    80. // Compute responses
    81. e_bar = -gamma * e + e'
    82. r2_bar = gamma * r2 + r2'
    83. r3_bar = gamma * r3 + r3'
    84. c_bar = -gamma * c + c'
    85. r_bar = -gamma * r + r'

    86. // Complete range proof responses
    87. z_final = array[L][2]
    88. gamma0_final = array[L]
    89.
    90. // For bit 0
    91. if i[0] == 0:
    92.     gamma0_final[0] = gamma - gamma0[0]
    94.     w00 = gamma0_final[0] * k* + k0'
    95.     w01 = w0
    96.     z_final[0][0] = gamma0_final[0] * s[0] + s_prime[0]
    97.     z_final[0][1] = z[0]
    98. else:
    99.     gamma0_final[0] = gamma0[0]
    100.    w00 = w0
    101.    w01 = (gamma - gamma_final[0]) * k* + k'[0]
    102.    z_final[0][0] = z[0]
    103.    z_final[0][1] = (gamma - gamma0_final[0]) * s[0] + s_prime[0]

    104. // For remaining bits
    105. For j = 1 to L-1:
    106.     if i[j] == 0:
    107.         gamma0_final[j] = gamma - gamma0[j]
    108.         z_final[j][0] = gamma0_final[j] * s[j] + s_prime[j]
    109.         z_final[j][1] = z[j]
    110.     else:
    111.         gamma0_final[j] = gamma0[j]
    112.         z_final[j][0] = z[j]
    113.         z_final[j][1] = (gamma - gamma0_final[j]) * s[j] + s_prime[j]

    114. k_bar = gamma * k* + k'
    115. s_bar = gamma * r* + s'

    116. // Construct proof
    117. proof = (k, s, A', B_bar, Com, gamma, e_bar,
    118.          r2_bar, r3_bar, c_bar, r_bar,
    119.          w00, w01, gamma0_final, z_final,
    120.          k_bar, s_bar)
    121. state = (k*, r*, m)
    122. return (proof, state)
]]></artwork>
        </section>
        <section anchor="issuer-spend-verification-and-refund">
          <name>Issuer: Spend Verification and Refund</name>
          <artwork><![CDATA[
VerifyAndRefund(sk, proof):
  Input:
    - sk: Issuer's private key
    - proof: Client's spend proof
  Output:
    - refund: Refund for remaining credits or INVALID

  Steps:
    1. Parse proof and extract nullifier k
    2. // Check nullifier hasn't been used
    3. if k in used_nullifiers:
    4.     return INVALID
    5. // Verify the proof (see Section 3.5.2)
    6. if not VerifySpendProof(sk, proof):
    7.     return INVALID
    8. // Record nullifier
    9. used_nullifiers.add(k)
    10. // Issue refund for remaining balance
    11. K' = Sum(Com[j] * 2^j for j in [L])
    12. refund = IssueRefund(sk, K')
    13. return refund
]]></artwork>
        </section>
        <section anchor="refund-issuance">
          <name>Refund Issuance</name>
          <t>After verifying a spend proof, the issuer creates a refund token for the
remaining balance:</t>
          <artwork><![CDATA[
IssueRefund(sk, K'):
  Input:
    - sk: Issuer's private key
    - K': Commitment to remaining balance and new nullifier
  Output:
    - refund: Refund response

  Steps:
    1. // Create new BBS signature on remaining balance
    2. e* <- Zq
    3. X_A* = G + K'
    4. A* = X_A* * (1/(e* + sk))

    5. // Generate proof of correct computation
    6. alpha <- Zq
    7. Y_A = A* * alpha
    8. Y_G = G * alpha
    9. X_G = G * e* + pk

    10. // Create challenge using transcript
    11. transcript = CreateTranscript("refund")
    12. AddToTranscript(transcript, e*)
    13. AddToTranscript(transcript, A*)
    14. AddToTranscript(transcript, X_A*)
    15. AddToTranscript(transcript, X_G)
    16. AddToTranscript(transcript, Y_A)
    17. AddToTranscript(transcript, Y_G)
    18. gamma = GetChallenge(transcript)

    19. // Compute response
    20. z = gamma * (sk + e*) + alpha

    21. refund = (A*, e*, gamma, z)
    22. return refund
]]></artwork>
        </section>
        <section anchor="client-refund-token-construction">
          <name>Client: Refund Token Construction</name>
          <t>The client verifies the refund and constructs a new credit token:</t>
          <artwork><![CDATA[
ConstructRefundToken(pk, spend_proof, refund, state):
  Input:
    - pk: Issuer's public key
    - spend_proof: The spend proof sent to issuer
    - refund: Issuer's refund response
    - state: Client state (k*, r*, m)
  Output:
    - token: New credit token or INVALID

  Steps:
    1. Parse refund as (A*, e*, gamma, z)
    2. Parse state as (k*, r*, m)

    3. // Reconstruct commitment
    4. K' = Sum(spend_proof.Com[j] * 2^j for j in [L])
    5. X_A* = G + K'
    6. X_G = G * e* + pk

    7. // Verify proof
    8. Y_A = A* * z + X_A* * (-gamma)
    9. Y_G = G * z + X_G * (-gamma)

    10. // Check challenge using transcript
    11. transcript = CreateTranscript("refund")
    12. AddToTranscript(transcript, e*)
    13. AddToTranscript(transcript, A*)
    14. AddToTranscript(transcript, X_A*)
    15. AddToTranscript(transcript, X_G)
    16. AddToTranscript(transcript, Y_A)
    17. AddToTranscript(transcript, Y_G)
    18. if GetChallenge(transcript) != gamma:
    19.     return INVALID

    20. // Construct new token
    21. token = (A*, e*, k*, r*, m)
    22. return token
]]></artwork>
        </section>
        <section anchor="spend-verification">
          <name>Spend Proof Verification</name>
          <t>The issuer verifies a spend proof as follows:</t>
          <artwork><![CDATA[
VerifySpendProof(sk, proof):
  Input:
    - sk: Issuer's private key
    - proof: Spend proof from client
  Output:
    - valid: Boolean indicating if proof is valid

  Steps:
    1. Parse proof as (k, s, A', B_bar, Com, gamma, e_bar,
                      r2_bar, r3_bar, c_bar, r_bar, w00, w01,
                      gamma0, z, k_bar, s_bar)

    2. // Check A' is not identity
    3. if A' == Identity:
    4.     return false

    5. // Compute issuer's view of signature
    6. A_bar = A' * sk
    7. H1_prime = G + H2 * k

    8. // Verify sigma protocol
    9. A1 = A' * e_bar + B_bar * r2_bar - A_bar * gamma
    10. A2 = B_bar * r3_bar + H1 * c_bar + H3 * r_bar - H1_prime * gamma

    11. // Initialize arrays for range proof verification
    12. gamma1 = array[L]
    13. C = array[L][2]
    14. C' = array[L][2]

    15. // Process bit 0 (with k* component)
    16. gamma1[0] = gamma - gamma0[0]
    17. C[0][0] = Com[0]
    18. C[0][1] = Com[0] - H1
    19. C'[0][0] = H2 * w00 + H3 * z[0][0] - C[0][0] * gamma0[0]
    20. C'[0][1] = H2 * w01 + H3 * z[0][1] - C[0][1] * gamma1[0]

    21. // Verify remaining bits
    22. For j = 1 to L-1:
    23.     gamma1[j] = gamma - gamma0[j]
    24.     C[j][0] = Com[j]
    25.     C[j][1] = Com[j] - H1
    26.     C'[j][0] = H3 * z[j][0] - C[j][0] * gamma0[j]
    27.     C'[j][1] = H3 * z[j][1] - C[j][1] * gamma1[j]

    28. // Verify final commitment
    29. K' = Sum(Com[j] * 2^j for j in [L])
    30. Com_total = H1 * s + K'
    31. C_final = H1 * (-c_bar) + H2 * k_bar + H3 * s_bar - Com_total * gamma

    32. // Recompute challenge using transcript
    33. transcript = CreateTranscript("spend")
    34. AddToTranscript(transcript, k)
    35. AddToTranscript(transcript, A')
    36. AddToTranscript(transcript, B_bar)
    37. AddToTranscript(transcript, A1)
    38. AddToTranscript(transcript, A2)
    39. For j = 0 to L-1:
    40.     AddToTranscript(transcript, Com[j])
    41. For j = 0 to L-1:
    42.     AddToTranscript(transcript, C'[j][0])
    43.     AddToTranscript(transcript, C'[j][1])
    44. AddToTranscript(transcript, C_final)
    45. gamma_check = GetChallenge(transcript)

    46. // Verify challenge matches
    47. if gamma != gamma_check:
    48.     return false

    49. return true
]]></artwork>
        </section>
      </section>
      <section anchor="cryptographic-primitives">
        <name>Cryptographic Primitives</name>
        <section anchor="protocol-version">
          <name>Protocol Version</name>
          <t>The protocol version string for domain separation is:</t>
          <artwork><![CDATA[
PROTOCOL_VERSION = "curve25519-ristretto anonymous-credits v1.0"
]]></artwork>
          <t>This version string <bcp14>MUST</bcp14> be used consistently across all implementations for
interoperability. The curve specification is included to prevent cross-curve
attacks and ensure implementations using different curves cannot accidentally
interact.</t>
        </section>
        <section anchor="hash-function-and-fiat-shamir-transform">
          <name>Hash Function and Fiat-Shamir Transform</name>
          <t>The protocol uses BLAKE3 <xref target="BLAKE3"/> as the underlying hash function for the
Fiat-Shamir transform <xref target="ORRU-FS"/>. Following the sigma protocol framework
<xref target="ORRU-SIGMA"/>, challenges are generated using a transcript that accumulates
all protocol messages:</t>
          <artwork><![CDATA[
CreateTranscript(label):
  Input:
    - label: ASCII string identifying the proof type
  Output:
    - transcript: A new transcript object

  Steps:
    1. hasher = BLAKE3.new()
    2. hasher.update(LengthPrefixed(PROTOCOL_VERSION))
    3. hasher.update(LengthPrefixed(Encode(H1)))
    4. hasher.update(LengthPrefixed(Encode(H2)))
    5. hasher.update(LengthPrefixed(Encode(H3)))
    6. hasher.update(LengthPrefixed(label))
    7. return transcript with hasher

AddToTranscript(transcript, value):
  Input:
    - transcript: Existing transcript
    - value: Element or Scalar to add

  Steps:
    1. encoded = Encode(value)
    2. transcript.hasher.update(LengthPrefixed(encoded))

GetChallenge(transcript):
  Input:
    - transcript: Completed transcript
  Output:
    - challenge: Scalar challenge value

  Steps:
    1. hash = transcript.hasher.output(64)  // 64 bytes of output
    3. challenge = from_little_endian_bytes(hash) mod q
    4. return challenge
]]></artwork>
          <t>This approach ensures:</t>
          <ul spacing="normal">
            <li>
              <t>Domain separation through the label and protocol version</t>
            </li>
            <li>
              <t>Inclusion of all public parameters to prevent parameter substitution attacks</t>
            </li>
            <li>
              <t>Proper ordering with length prefixes to prevent ambiguity</t>
            </li>
            <li>
              <t>Deterministic challenge generation from the complete transcript</t>
            </li>
          </ul>
        </section>
        <section anchor="encoding-functions">
          <name>Encoding Functions</name>
          <t>Elements and scalars are encoded as follows:</t>
          <artwork><![CDATA[
Encode(value):
  Input:
    - value: Element or Scalar
  Output:
    - encoding: ByteString

  Steps:
    1. If value is an Element:
    2.     return value.compress()  // 32 bytes, compressed Ristretto point
    3. If value is a Scalar:
    4.     return value.to_bytes_le()  // 32 bytes, little-endian
]]></artwork>
          <t>The following function provides consistent length-prefixing for hash inputs:</t>
          <artwork><![CDATA[
LengthPrefixed(data):
  Input:
    - data: ByteString to be length-prefixed
  Output:
    - prefixed: ByteString with length prefix

  Steps:
    1. length = len(data)
    2. return length.to_be_bytes(8) || data  // 8-byte big-endian length prefix
]]></artwork>
          <t>Note: Implementations <bcp14>MAY</bcp14> use standard serialization formats (e.g. CBOR) for
complex structures, but <bcp14>MUST</bcp14> ensure deterministic encoding for hash inputs.</t>
        </section>
        <section anchor="binary-decomposition">
          <name>Binary Decomposition</name>
          <t>To decompose a scalar into its binary representation:</t>
          <artwork><![CDATA[
BitDecompose(s):
  Input:
    - s: Scalar value
  Output:
    - bits: Array of L scalars (each 0 or 1)

  Steps:
    1. bytes = s.to_bytes_le()  // 32 bytes, little-endian
    2. For i = 0 to L-1:
    3.     byte_index = i / 8
    4.     bit_position = i % 8
    5.     bit = (bytes[byte_index] >> bit_position) & 1
    6.     bits[i] = Scalar(bit)
    7. return bits
]]></artwork>
          <t>Note: This algorithm produces bits in LSB-first order (i.e., <tt>bits[0]</tt> is the
least significant bit). The algorithm works for any L &lt; 252, as the scalar is
represented in 32 bytes (256 bits), which accommodates the full range of the
Ristretto group order.</t>
        </section>
        <section anchor="scalar-conversion">
          <name>Scalar Conversion</name>
          <t>Converting between credit amounts and scalars:</t>
          <artwork><![CDATA[
CreditToScalar(amount):
  Input:
    - amount: Integer credit amount (0 <= amount < 2^L)
  Output:
    - s: Scalar representation

  Steps:
    1. if amount >= 2^L:
    2.     return ERROR
    3. return Scalar(amount)

ScalarToCredit(s):
  Input:
    - s: Scalar value
  Output:
    - amount: Integer credit amount or ERROR

  Steps:
    1. bytes = s.to_bytes_le()
    2. // Check high bytes are zero
    3. For i = 16 to 31:
    4.     if bytes[i] != 0:
    5.         return ERROR
    6. amount = bytes[0..15] as u128
    7. return amount
]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="protocol-messages-and-wire-format">
      <name>Protocol Messages and Wire Format</name>
      <section anchor="message-encoding">
        <name>Message Encoding</name>
        <t>All protocol messages <bcp14>SHOULD</bcp14> be encoded using deterministic CBOR (RFC 8949) for
interoperability. The following sections define the structure of each message
type.</t>
        <section anchor="issuance-request-message">
          <name>Issuance Request Message</name>
          <artwork><![CDATA[
IssuanceRequestMsg = {
    1: bstr,  ; K (compressed Ristretto point, 32 bytes)
    2: bstr,  ; gamma (scalar, 32 bytes)
    3: bstr,  ; k_bar (scalar, 32 bytes)
    4: bstr   ; r_bar (scalar, 32 bytes)
}
]]></artwork>
        </section>
        <section anchor="issuance-response-message">
          <name>Issuance Response Message</name>
          <artwork><![CDATA[
IssuanceResponseMsg = {
    1: bstr,  ; A (compressed Ristretto point, 32 bytes)
    2: bstr,  ; e (scalar, 32 bytes)
    3: bstr,  ; gamma_resp (scalar, 32 bytes)
    4: bstr,  ; z (scalar, 32 bytes)
    5: bstr   ; c (scalar, 32 bytes)
}
]]></artwork>
        </section>
        <section anchor="spend-proof-message">
          <name>Spend Proof Message</name>
          <artwork><![CDATA[
SpendProofMsg = {
    1: bstr,           ; k (nullifier, 32 bytes)
    2: bstr,           ; s (spend amount, 32 bytes)
    3: bstr,           ; A' (compressed point, 32 bytes)
    4: bstr,           ; B_bar (compressed point, 32 bytes)
    5: [* bstr],       ; Com array (L compressed points)
    6: bstr,           ; gamma (scalar, 32 bytes)
    7: bstr,           ; e_bar (scalar, 32 bytes)
    8: bstr,           ; r2_bar (scalar, 32 bytes)
    9: bstr,           ; r3_bar (scalar, 32 bytes)
    10: bstr,          ; c_bar (scalar, 32 bytes)
    11: bstr,          ; r_bar (scalar, 32 bytes)
    12: bstr,          ; w00 (scalar, 32 bytes)
    13: bstr,          ; w01 (scalar, 32 bytes)
    14: [* bstr],      ; gamma0 array (L scalars)
    15: [* [bstr, bstr]], ; z array (L pairs of scalars)
    16: bstr,          ; k_bar (scalar, 32 bytes)
    17: bstr           ; s_bar (scalar, 32 bytes)
}
]]></artwork>
        </section>
        <section anchor="refund-message">
          <name>Refund Message</name>
          <artwork><![CDATA[
RefundMsg = {
    1: bstr,  ; A* (compressed Ristretto point, 32 bytes)
    2: bstr,  ; e* (scalar, 32 bytes)
    3: bstr,  ; gamma (scalar, 32 bytes)
    4: bstr   ; z (scalar, 32 bytes)
}
]]></artwork>
        </section>
      </section>
      <section anchor="error-responses">
        <name>Error Responses</name>
        <t>Error responses <bcp14>SHOULD</bcp14> use the following format:</t>
        <artwork><![CDATA[
ErrorMsg = {
    1: uint,   ; error_code
    2: tstr    ; error_message (for debugging only)
}
]]></artwork>
        <t>Error codes are defined in Section 5.3.</t>
      </section>
      <section anchor="protocol-flow">
        <name>Protocol Flow</name>
        <t>The complete protocol flow with message types:</t>
        <artwork><![CDATA[
Client                                          Issuer
  |                                               |
  |-- IssuanceRequestMsg ------------------------>|
  |                                               |
  |<-- IssuanceResponseMsg -----------------------|
  |                                               |
  | (client creates token)                        |
  |                                               |
  |-- SpendProofMsg ----------------------------->|
  |                                               |
  |<-- RefundMsg or ErrorMsg ---------------------|
  |                                               |
]]></artwork>
        <section anchor="example-usage-scenario">
          <name>Example Usage Scenario</name>
          <t>Consider an API service that sells credits in bundles of 1000:</t>
          <ol spacing="normal" type="1"><li>
              <t><strong>Purchase</strong>: Alice buys 1000 API credits
              </t>
              <ul spacing="normal">
                <li>
                  <t>Alice generates a random nullifier k and blinding factor r</t>
                </li>
                <li>
                  <t>Alice sends IssuanceRequestMsg to the service</t>
                </li>
                <li>
                  <t>Service creates a BBS signature on (1000, k, r) and returns it</t>
                </li>
                <li>
                  <t>Alice now has a token worth 1000 credits</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>First API Call</strong>: Alice makes an API call costing 50 credits
              </t>
              <ul spacing="normal">
                <li>
                  <t>Alice creates a SpendProofMsg proving she has ≥ 50 credits</t>
                </li>
                <li>
                  <t>Alice reveals nullifier k to prevent double-spending</t>
                </li>
                <li>
                  <t>Service verifies the proof and records k as used</t>
                </li>
                <li>
                  <t>Service issues a RefundMsg for a new token worth 950 credits</t>
                </li>
                <li>
                  <t>Alice generates new nullifier k' for the refund token</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Subsequent Calls</strong>: Alice continues using the API
              </t>
              <ul spacing="normal">
                <li>
                  <t>Each call repeats the spend/refund process</t>
                </li>
                <li>
                  <t>Each new token has a fresh nullifier</t>
                </li>
                <li>
                  <t>The service cannot link Alice's calls together</t>
                </li>
              </ul>
            </li>
          </ol>
          <t>This example demonstrates how the protocol maintains privacy while preventing double-spending and enabling flexible partial payments.</t>
        </section>
      </section>
    </section>
    <section anchor="implementation-considerations">
      <name>Implementation Considerations</name>
      <section anchor="nullifier-management">
        <name>Nullifier Management</name>
        <t>Implementations <bcp14>MUST</bcp14> maintain a persistent database of used nullifiers to
prevent double-spending. The nullifier storage requirements grow linearly with
the number of spent tokens. Implementations <bcp14>MAY</bcp14> use the following strategies to
manage storage:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Expiration</strong>: If tokens have expiration dates, old nullifiers can be
pruned.</t>
          </li>
          <li>
            <t><strong>Sharding</strong>: Nullifiers can be partitioned across multiple databases.</t>
          </li>
          <li>
            <t><strong>Bloom Filters</strong>: Probabilistic data structures can reduce memory usage
with a small false-positive rate.</t>
          </li>
        </ol>
      </section>
      <section anchor="constant-time-operations">
        <name>Constant-Time Operations</name>
        <t>To prevent timing attacks, implementations <bcp14>MUST</bcp14> use constant-time operations
for:</t>
        <ul spacing="normal">
          <li>
            <t>Scalar arithmetic</t>
          </li>
          <li>
            <t>Point operations</t>
          </li>
          <li>
            <t>Conditional selections in range proofs</t>
          </li>
        </ul>
        <t>In particular, the range proof generation <bcp14>MUST</bcp14> use constant-time conditional
selection when choosing between bit values 0 and 1. The following pattern
should be used:</t>
        <artwork><![CDATA[
ConstantTimeSelect(condition, value_if_true, value_if_false):
  // Returns value_if_true if condition is true (1),
  // value_if_false if condition is false (0)
  // Must execute in constant time regardless of condition
]]></artwork>
        <t>This is critical in the range proof generation where bit values must not leak
through timing channels.</t>
      </section>
      <section anchor="randomness-generation">
        <name>Randomness Generation</name>
        <t>The security of the protocol critically depends on the quality of random number
generation. Implementations <bcp14>MUST</bcp14> use cryptographically secure random number
generators (CSPRNGs) for:</t>
        <ul spacing="normal">
          <li>
            <t>Private key generation</t>
          </li>
          <li>
            <t>Blinding factors (r, k)</t>
          </li>
          <li>
            <t>Proof randomness (nonces)</t>
          </li>
        </ul>
        <section anchor="rng-requirements">
          <name>RNG Requirements</name>
          <ol spacing="normal" type="1"><li>
              <t><strong>Entropy Source</strong>: Use OS-provided entropy (e.g., /dev/urandom on Unix systems)</t>
            </li>
            <li>
              <t><strong>Fork Safety</strong>: Reseed after fork() to prevent nonce reuse</t>
            </li>
            <li>
              <t><strong>Backtracking Resistance</strong>: Use forward-secure PRNGs when possible</t>
            </li>
          </ol>
        </section>
        <section anchor="nonce-generation">
          <name>Nonce Generation</name>
          <t>Following <xref target="ORRU-SIGMA"/>, nonces (the randomness used in proofs) <bcp14>MUST</bcp14> be
generated with extreme care:</t>
          <ol spacing="normal" type="1"><li>
              <t><strong>Fresh Randomness</strong>: Generate new nonces for every proof</t>
            </li>
            <li>
              <t><strong>No Reuse</strong>: Never reuse nonces across different proofs</t>
            </li>
            <li>
              <t><strong>Full Entropy</strong>: Use the full security parameter (256 bits) of randomness</t>
            </li>
            <li>
              <t><strong>Zeroization</strong>: Clear nonces from memory after use</t>
            </li>
          </ol>
          <t>WARNING: Leakage of even a few bits of a nonce can allow complete recovery of the witness (secret values). Implementations <bcp14>MUST</bcp14> use constant-time operations and secure memory handling for all nonce-related computations.</t>
        </section>
      </section>
      <section anchor="point-validation">
        <name>Point Validation</name>
        <t>All Ristretto points received from external sources <bcp14>MUST</bcp14> be validated:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Deserialization</strong>: Verify the point deserializes to a valid Ristretto point</t>
          </li>
          <li>
            <t><strong>Non-Identity</strong>: Verify the point is not the identity element</t>
          </li>
          <li>
            <t><strong>Subgroup Check</strong>: Ristretto guarantees prime-order subgroup membership</t>
          </li>
        </ol>
        <t>Example validation:</t>
        <artwork><![CDATA[
ValidatePoint(P):
  1. If P fails to deserialize:
  2.     return INVALID
  3. If P == Identity:
  4.     return INVALID
  5. // Ristretto ensures prime-order subgroup membership
  6. return VALID
]]></artwork>
        <t>All implementations <bcp14>MUST</bcp14> validate points at these locations:</t>
        <ul spacing="normal">
          <li>
            <t>When receiving <tt>K</tt> in issuance request</t>
          </li>
          <li>
            <t>When receiving <tt>A</tt> in issuance response</t>
          </li>
          <li>
            <t>When receiving <tt>A'</tt> and <tt>B_bar</tt> in spend proof</t>
          </li>
          <li>
            <t>When receiving <tt>Com[j]</tt> commitments in spend proof</t>
          </li>
          <li>
            <t>When receiving <tt>A*</tt> in refund response</t>
          </li>
        </ul>
      </section>
      <section anchor="error-handling">
        <name>Error Handling</name>
        <t>Implementations <bcp14>SHOULD NOT</bcp14> provide detailed error messages that could leak
information about the verification process. A single INVALID response should be
returned for all verification failures.</t>
        <section anchor="error-codes">
          <name>Error Codes</name>
          <t>While detailed error messages should not be exposed to untrusted parties,
implementations <bcp14>MAY</bcp14> use the following internal error codes:</t>
          <ul spacing="normal">
            <li>
              <t><tt>INVALID_PROOF</tt>: Proof verification failed</t>
            </li>
            <li>
              <t><tt>NULLIFIER_REUSE</tt>: Double-spend attempt detected</t>
            </li>
            <li>
              <t><tt>MALFORMED_REQUEST</tt>: Request format is invalid</t>
            </li>
            <li>
              <t><tt>INVALID_AMOUNT</tt>: Credit amount exceeds maximum (2^L - 1)</t>
            </li>
          </ul>
        </section>
      </section>
      <section anchor="parameter-selection">
        <name>Parameter Selection</name>
        <t>Implementations <bcp14>MUST</bcp14> choose L based on their maximum credit requirements and
performance constraints. Note that L <bcp14>MUST</bcp14> be less than 252 to fit within the
Ristretto group order.</t>
        <t>The bit length L is configurable and determines the range of credit values (0
to 2^L - 1). The choice of L involves several trade-offs:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Range</strong>: Larger L supports higher credit values</t>
          </li>
          <li>
            <t><strong>Performance</strong>: Proof size and verification time scale linearly with L</t>
          </li>
          <li>
            <t><strong>Security</strong>: L must be less than the bit length of the group order (252 bits for Ristretto)</t>
          </li>
        </ol>
        <t>The implementation <bcp14>MUST</bcp14> enforce L &lt; 252 to ensure proper scalar arithmetic
within the group order.</t>
        <section anchor="performance-characteristics">
          <name>Performance Characteristics</name>
          <t>The protocol has the following computational complexity:</t>
          <t><strong>Notation for Operations:</strong></t>
          <ul spacing="normal">
            <li>
              <t><strong>Group Operations</strong>: Point additions in the Ristretto255 group (e.g., P + Q)</t>
            </li>
            <li>
              <t><strong>Group Exponentiations</strong>: Scalar multiplication of group elements (e.g., P * s)</t>
            </li>
            <li>
              <t><strong>Scalar Additions/Multiplications</strong>: Arithmetic operations modulo the group order q</t>
            </li>
            <li>
              <t><strong>Issuance</strong>:</t>
            </li>
          </ul>
          <table>
            <thead>
              <tr>
                <th align="left">Operation</th>
                <th align="left">Group Operations</th>
                <th align="left">Group Exponentiations</th>
                <th align="left">Scalar Additions</th>
                <th align="left">Scalar Multiplications</th>
                <th align="left">Hashes</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">Client Request</td>
                <td align="left">2</td>
                <td align="left">4</td>
                <td align="left">2</td>
                <td align="left">1</td>
                <td align="left">1</td>
              </tr>
              <tr>
                <td align="left">Issuer Response</td>
                <td align="left">5</td>
                <td align="left">8</td>
                <td align="left">3</td>
                <td align="left">1</td>
                <td align="left">2</td>
              </tr>
              <tr>
                <td align="left">Client Credit Token Construction</td>
                <td align="left">5</td>
                <td align="left">5</td>
                <td align="left">0</td>
                <td align="left">0</td>
                <td align="left">1</td>
              </tr>
            </tbody>
          </table>
          <ul spacing="normal">
            <li>
              <t><strong>Spending</strong>:</t>
            </li>
          </ul>
          <table>
            <thead>
              <tr>
                <th align="left">Operation</th>
                <th align="left">Group Operations</th>
                <th align="left">Group Exponentiations</th>
                <th align="left">Scalar Additions</th>
                <th align="left">Scalar Multiplications</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">Client Request</td>
                <td align="left">17 + 4L</td>
                <td align="left">27 + 8L</td>
                <td align="left">13 + 5L</td>
                <td align="left">12 + 3L</td>
              </tr>
              <tr>
                <td align="left">Issuer Response</td>
                <td align="left">16 + 4L</td>
                <td align="left">24 + 5L</td>
                <td align="left">4 + L</td>
                <td align="left">1</td>
              </tr>
              <tr>
                <td align="left">Client Credit Token Construction</td>
                <td align="left">3</td>
                <td align="left">5</td>
                <td align="left">L</td>
                <td align="left">L</td>
              </tr>
            </tbody>
          </table>
          <t>Note: L is the configurable bit length for credit values.</t>
          <ul spacing="normal">
            <li>
              <t><strong>Storage</strong>:</t>
            </li>
          </ul>
          <table>
            <thead>
              <tr>
                <th align="left">Component</th>
                <th align="left">Size</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td align="left">Token size</td>
                <td align="left">160 bytes (5 × 32 bytes)</td>
              </tr>
              <tr>
                <td align="left">Spend proof size</td>
                <td align="left">32 × (14 + 4L) bytes</td>
              </tr>
              <tr>
                <td align="left">Nullifier database entry</td>
                <td align="left">32 bytes per spent token</td>
              </tr>
            </tbody>
          </table>
          <t>Note: Token size is independent of L.</t>
        </section>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <section anchor="security-model-and-definitions">
        <name>Security Model and Definitions</name>
        <section anchor="threat-model">
          <name>Threat Model</name>
          <t>We consider a setting with:</t>
          <ul spacing="normal">
            <li>
              <t>Multiple issuers who can operate independently, though malicious issuers may collude with each other</t>
            </li>
            <li>
              <t>Potentially malicious clients who may attempt to spend more credits than they should (whether by forging tokens, spending more credits than a token has, or double-spending a token)</t>
            </li>
          </ul>
        </section>
        <section anchor="security-properties">
          <name>Security Properties</name>
          <t>The protocol provides the following security guarantees:</t>
          <ol spacing="normal" type="1"><li>
              <t><strong>Unforgeability</strong>: For an honest isser I, no probabilistic polynomial-time (PPT) adversary controlling a set of malicious clients and other malicious issuers can spend more credits than have been issued by I.</t>
            </li>
            <li>
              <t><strong>Anonymity/Unlinkability</strong>: For an honest client C, no adversary controlling a set of malicious issuers and other malicious clients can link a token issuance/refund to C with a token spend by C. This property is information-theoretic in nature.</t>
            </li>
          </ol>
        </section>
      </section>
      <section anchor="cryptographic-assumptions">
        <name>Cryptographic Assumptions</name>
        <t>Security relies on:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>The q-SDH Assumption</strong> in the Ristretto255 group. We refer to <xref target="TZ23"/> for the formal definition.</t>
          </li>
          <li>
            <t><strong>Random Oracle Model</strong>: The BLAKE3 hash function H is modeled as a random oracle.</t>
          </li>
        </ol>
      </section>
      <section anchor="privacy-properties">
        <name>Privacy Properties</name>
        <t>The protocol provides the following privacy guarantees:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Unlinkability</strong>: The issuer cannot link a token issuance/refund to a later spend of that token.</t>
          </li>
        </ol>
        <t>However, the protocol does NOT provide:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Network-Level Privacy</strong>: IP addresses and network metadata can still link transactions.</t>
          </li>
          <li>
            <t><strong>Amount Privacy</strong>: The spent amount s is revealed to the issuer.</t>
          </li>
          <li>
            <t><strong>Timing Privacy</strong>: Transaction timing patterns could potentially be used for correlation.</t>
          </li>
        </ol>
      </section>
      <section anchor="security-properties-1">
        <name>Security Properties</name>
        <t>The protocol ensures:</t>
        <ol spacing="normal" type="1"><li>
            <t><strong>Unforgeability</strong>: Clients cannot spend more credits than they have been issued by the issuer.</t>
          </li>
        </ol>
      </section>
      <section anchor="implementation-vulnerabilities-and-mitigations">
        <name>Implementation Vulnerabilities and Mitigations</name>
        <section anchor="critical-security-requirements">
          <name>Critical Security Requirements</name>
          <ol spacing="normal" type="1"><li>
              <t><strong>RNG Failures</strong>: Weak randomness can completely break the protocol's security.  </t>
              <t><strong>Attack Vector</strong>: Predictable or repeated nonces in proofs can allow complete recovery of secret values including private keys and token contents.  </t>
              <t><strong>Mitigations</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t><bcp14>MUST</bcp14> use cryptographically secure RNGs (e.g., OS-provided entropy sources)</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> reseed after fork() operations to prevent nonce reuse</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> implement forward-secure RNG state management</t>
                </li>
                <li>
                  <t><bcp14>SHOULD</bcp14> use separate RNG instances for different protocol components</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> zeroize RNG state on process termination</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Timing Attacks</strong>: Variable-time operations can leak information about secret values.  </t>
              <t><strong>Attack Vector</strong>: Timing variations in scalar arithmetic or bit operations can reveal secret bit patterns, potentially exposing credit balances or allowing token forgery.  </t>
              <t><strong>Mitigations</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t><bcp14>MUST</bcp14> use constant-time scalar arithmetic libraries</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> use constant-time conditional selection for range proof conditionals</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> avoid early-exit conditions based on secret values</t>
                </li>
                <li>
                  <t>Critical constant-time operations include:
                  </t>
                  <ul spacing="normal">
                    <li>
                      <t>Scalar multiplication and addition</t>
                    </li>
                    <li>
                      <t>Binary decomposition in range proofs</t>
                    </li>
                    <li>
                      <t>Conditional assignments based on secret bits</t>
                    </li>
                    <li>
                      <t>Challenge verification comparisons</t>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Nullifier Database Attacks</strong>: Corruption or manipulation of the nullifier database enables double-spending.  </t>
              <t><strong>Attack Vectors</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t>Database corruption allowing nullifier deletion</t>
                </li>
                <li>
                  <t>Race conditions in concurrent nullifier checks</t>
                </li>
              </ul>
              <t>
<strong>Mitigations</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t><bcp14>MUST</bcp14> use ACID-compliant database transactions</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> check nullifier uniqueness within the same transaction as insertion</t>
                </li>
                <li>
                  <t><bcp14>SHOULD</bcp14> implement append-only audit logs for nullifier operations</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> implement proper database backup and recovery procedures</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Eavesdropping/Message Modification Attacks</strong>: A network-level adversary can copy spend proofs or modify messages sent between an honest client and issuer.  </t>
              <t><strong>Attack Vectors</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t>Eavesdropping and copying of proofs</t>
                </li>
                <li>
                  <t>Message modifications causing protocol failure</t>
                </li>
              </ul>
              <t>
<strong>Mitigations</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t>Client and issuer <bcp14>MUST</bcp14> use TLS 1.3 or above when communicating.</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>State Management Vulnerabilities</strong>: Improper state handling can lead to security breaches.  </t>
              <t><strong>Attack Vectors</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t>State confusion between protocol sessions</t>
                </li>
                <li>
                  <t>Memory disclosure of sensitive state</t>
                </li>
                <li>
                  <t>Incomplete state cleanup</t>
                </li>
              </ul>
              <t>
<strong>Mitigations</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t><bcp14>MUST</bcp14> use separate state objects for each protocol session</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> zeroize all sensitive data (keys, nonces, intermediate values) after use</t>
                </li>
                <li>
                  <t><bcp14>SHOULD</bcp14> use memory protection mechanisms (e.g., mlock) for sensitive data</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> implement proper error handling that doesn't leak state information</t>
                </li>
                <li>
                  <t><bcp14>SHOULD</bcp14> use explicit state machines for protocol flow</t>
                </li>
              </ul>
            </li>
            <li>
              <t><strong>Concurrency and Race Conditions</strong>: Parallel operations can introduce vulnerabilities.  </t>
              <t><strong>Attack Vectors</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t>TOCTOU (Time-of-check to time-of-use) vulnerabilities in nullifier checking</t>
                </li>
                <li>
                  <t>Race conditions in balance updates</t>
                </li>
                <li>
                  <t>Concurrent modification of shared state</t>
                </li>
              </ul>
              <t>
<strong>Mitigations</strong>:  </t>
              <ul spacing="normal">
                <li>
                  <t><bcp14>MUST</bcp14> use appropriate locking for all shared resources</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> perform nullifier check and insertion atomically</t>
                </li>
                <li>
                  <t><bcp14>SHOULD</bcp14> document thread-safety guarantees</t>
                </li>
                <li>
                  <t><bcp14>MUST</bcp14> ensure atomic read-modify-write for all critical operations</t>
                </li>
              </ul>
            </li>
          </ol>
        </section>
      </section>
      <section anchor="known-attack-scenarios">
        <name>Known Attack Scenarios</name>
        <section anchor="parallel-spend-attack">
          <name>1. Parallel Spend Attack</name>
          <t><strong>Scenario</strong>: A malicious client attempts to spend the same token multiple times by initiating parallel spend operations before any nullifier is recorded.</t>
          <t><strong>Prevention</strong>: The issuer <bcp14>MUST</bcp14> ensure atomic nullifier checking and recording within a single database transaction. Network-level rate limiting can provide additional protection.</t>
        </section>
        <section anchor="balance-inflation-attack">
          <name>2. Balance Inflation Attack</name>
          <t><strong>Scenario</strong>: An attacker attempts to create a proof claiming to have more credits than actually issued by manipulating the range proof.</t>
          <t><strong>Prevention</strong>: The cryptographic soundness of the range proof prevents this attack.</t>
        </section>
        <section anchor="token-linking-attack">
          <name>3. Token Linking Attack</name>
          <t><strong>Scenario</strong>: An issuer attempts to link transactions by analyzing patterns in nullifiers, amounts, or timing.</t>
          <t><strong>Prevention</strong>: Nullifiers are cryptographically random and unlinkable. However, implementations <bcp14>MAY</bcp14> add random delays and amount obfuscation where possible.</t>
        </section>
      </section>
      <section anchor="protocol-composition-and-state-management">
        <name>Protocol Composition and State Management</name>
        <section anchor="state-management-requirements">
          <name>State Management Requirements</name>
          <t>Before they make a spend request or an issue request, the client <bcp14>MUST</bcp14> store
their private state (the nullifier, the blinding factor, and the new balance)
durably.</t>
          <t>For the issuer, the spend and refund operations <bcp14>MUST</bcp14> be treated as an atomic
transaction. However, even more is required. If a nullifier associated with a
given spend is persisted to the database, clients <bcp14>MUST</bcp14> be able to access the
associated refund. If they cannot access this, then they can lose access to the
rest of their credits. For performance reasons, an issuer <bcp14>SHOULD</bcp14> automatically
clean these up after some expiry, but if they do so, they <bcp14>MUST</bcp14> inform the
client of this policy so the client can ensure they can retry to retrieve the
rest of their credits in time. Issuers <bcp14>MAY</bcp14> implement functionality to notify
the issuer that the refund request was processed, so they can delete the refund
record. It is not clear that this is worth the cost relative to just cleaning
them up in bulk at some specified expiration date, however if you are memory
constrained this could be useful.</t>
        </section>
        <section anchor="session-management">
          <name>Session Management</name>
          <t>Each protocol session (issuance or spend/refund) <bcp14>MUST</bcp14>:</t>
          <ul spacing="normal">
            <li>
              <t>Use fresh randomness</t>
            </li>
            <li>
              <t>Not reuse any random values across sessions</t>
            </li>
          </ul>
        </section>
        <section anchor="version-negotiation">
          <name>Version Negotiation</name>
          <t>To support protocol evolution, implementations <bcp14>MAY</bcp14> include version negotiation
in the initial handshake. All parties <bcp14>MUST</bcp14> agree on the protocol version before
proceeding.</t>
        </section>
      </section>
      <section anchor="quantum-resistance">
        <name>Quantum Resistance</name>
        <t>This protocol is NOT quantum-resistant. The discrete logarithm problem can be
solved efficiently by quantum computers using Shor's algorithm. Organizations
requiring long-term security should consider post-quantum alternatives. However,
user privacy is preserved even in the presence of a cryptographically relevant
quantum computer.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8949">
          <front>
            <title>Concise Binary Object Representation (CBOR)</title>
            <author fullname="C. Bormann" initials="C." surname="Bormann"/>
            <author fullname="P. Hoffman" initials="P." surname="Hoffman"/>
            <date month="December" year="2020"/>
            <abstract>
              <t>The Concise Binary Object Representation (CBOR) is a data format whose design goals include the possibility of extremely small code size, fairly small message size, and extensibility without the need for version negotiation. These design goals make it different from earlier binary serializations such as ASN.1 and MessagePack.</t>
              <t>This document obsoletes RFC 7049, providing editorial improvements, new details, and errata fixes while keeping full compatibility with the interchange format of RFC 7049. It does not create a new version of the format.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="94"/>
          <seriesInfo name="RFC" value="8949"/>
          <seriesInfo name="DOI" value="10.17487/RFC8949"/>
        </reference>
        <reference anchor="RFC9380">
          <front>
            <title>Hashing to Elliptic Curves</title>
            <author fullname="A. Faz-Hernandez" initials="A." surname="Faz-Hernandez"/>
            <author fullname="S. Scott" initials="S." surname="Scott"/>
            <author fullname="N. Sullivan" initials="N." surname="Sullivan"/>
            <author fullname="R. S. Wahby" initials="R. S." surname="Wahby"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="August" year="2023"/>
            <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="RFC" value="9380"/>
          <seriesInfo name="DOI" value="10.17487/RFC9380"/>
        </reference>
        <reference anchor="RFC9496">
          <front>
            <title>The ristretto255 and decaf448 Groups</title>
            <author fullname="H. de Valence" initials="H." surname="de Valence"/>
            <author fullname="J. Grigg" initials="J." surname="Grigg"/>
            <author fullname="M. Hamburg" initials="M." surname="Hamburg"/>
            <author fullname="I. Lovecruft" initials="I." surname="Lovecruft"/>
            <author fullname="G. Tankersley" initials="G." surname="Tankersley"/>
            <author fullname="F. Valsorda" initials="F." surname="Valsorda"/>
            <date month="December" year="2023"/>
            <abstract>
              <t>This memo specifies two prime-order groups, ristretto255 and decaf448, suitable for safely implementing higher-level and complex cryptographic protocols. The ristretto255 group can be implemented using Curve25519, allowing existing Curve25519 implementations to be reused and extended to provide a prime-order group. Likewise, the decaf448 group can be implemented using edwards448.</t>
              <t>This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9496"/>
          <seriesInfo name="DOI" value="10.17487/RFC9496"/>
        </reference>
        <reference anchor="BLAKE3" target="https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf">
          <front>
            <title>BLAKE3: One Function, Fast Everywhere</title>
            <author>
              <organization/>
            </author>
            <date year="2020" month="January" day="09"/>
          </front>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="RFC9474">
          <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="ORRU-SIGMA" target="https://www.ietf.org/archive/id/draft-orru-zkproof-sigma-protocols-00.txt">
          <front>
            <title>Sigma Protocols</title>
            <author>
              <organization/>
            </author>
            <date year="2025" month="January" day="19"/>
          </front>
        </reference>
        <reference anchor="ORRU-FS" target="https://mmaker.github.io/draft-zkproof-sigma-protocols/draft-orru-zkproof-fiat-shamir.html">
          <front>
            <title>The Fiat-Shamir Transform</title>
            <author>
              <organization/>
            </author>
            <date year="2025" month="January" day="19"/>
          </front>
        </reference>
        <reference anchor="BBS" target="https://crypto.stanford.edu/~dabo/pubs/papers/groupsigs.pdf">
          <front>
            <title>Short Group Signatures</title>
            <author>
              <organization/>
            </author>
            <date year="2004"/>
          </front>
        </reference>
        <reference anchor="KVAC" target="https://eprint.iacr.org/2013/516.pdf">
          <front>
            <title>Keyed-Verification Anonymous Credentials</title>
            <author>
              <organization/>
            </author>
            <date year="2014"/>
          </front>
        </reference>
        <reference anchor="TZ23" target="https://eprint.iacr.org/2023/275">
          <front>
            <title>Revisiting BBS Signatures</title>
            <author>
              <organization/>
            </author>
            <date year="2023"/>
          </front>
        </reference>
      </references>
    </references>
    <?line 1461?>

<section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>This appendix provides test vectors for implementers to verify their
implementations. All values are encoded in hexadecimal.</t>
      <t>TODO</t>
    </section>
    <section anchor="implementation-status">
      <name>Implementation Status</name>
      <t>This section records the status of known implementations of the protocol
defined by this specification at the time of posting of this Internet-Draft,
and is based on a proposal described in RFC 7942.</t>
      <section anchor="anonymous-credit-tokens">
        <name>anonymous-credit-tokens</name>
        <t>Organization: Google</t>
        <t>Description: Reference implementation in Rust</t>
        <t>Maturity: Beta</t>
        <t>Coverage: Complete protocol implementation</t>
        <t>License: Apache 2.0</t>
        <t>Contact: sgschlesinger@gmail.com</t>
        <t>URL: https://github.com/SamuelSchlesinger/anonymous-credit-tokens</t>
      </section>
    </section>
    <section anchor="terminology-glossary">
      <name>Terminology Glossary</name>
      <t>This glossary provides quick definitions of key terms used throughout this document:</t>
      <t><strong>ACT (Anonymous Credit Tokens)</strong>: The privacy-preserving authentication protocol specified in this document.</t>
      <t><strong>Blind Signature</strong>: A cryptographic signature where the signer signs a message without seeing its content.</t>
      <t><strong>Refund</strong>: The refund issued for the remaining balance after a partial spend.</t>
      <t><strong>Credit</strong>: A numerical unit of authorization that can be spent by clients.</t>
      <t><strong>Domain Separator</strong>: A unique string used to ensure cryptographic isolation between different deployments.</t>
      <t><strong>Element</strong>: A point in the Ristretto255 elliptic curve group.</t>
      <t><strong>Issuer</strong>: The entity that creates and signs credit tokens.</t>
      <t><strong>Nullifier</strong>: A unique value revealed during spending that prevents double-spending of the same token.</t>
      <t><strong>Partial Spending</strong>: The ability to spend less than the full value of a token and receive change.</t>
      <t><strong>Scalar</strong>: An integer modulo the group order q, used in cryptographic operations.</t>
      <t><strong>Sigma Protocol</strong>: An interactive zero-knowledge proof protocol following a commit-challenge-response pattern.</t>
      <t><strong>Token</strong>: A cryptographic credential containing a BBS signature and associated data (A, e, k, r, c).</t>
      <t><strong>Unlinkability</strong>: The property that transactions cannot be correlated with each other or with token issuance.</t>
    </section>
    <section anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The authors would like to thank the Crypto Forum Research Group for their
valuable feedback and suggestions. Special thanks to the contributors who
provided implementation guidance and security analysis.</t>
      <t>This work builds upon the foundational research in anonymous credentials and
zero-knowledge proofs by numerous researchers in the cryptographic community,
particularly the work on BBS signatures by Boneh, Boyen, and Shacham, and
keyed-verification anonymous credentials by Chase, Meiklejohn, and Zaverucha.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
jyZPxj6Wzm5CF9Ujhwc/fEU6QjxndyQlYA3p6fGpLl1hMXYh1rlGZQ7IUYjB
FaO12lrACJb3R5E5lIZC0kRikXge7+sQHZP4FE2crF63zIDHbkhmRppzvvAS
GDdoPXpsHiZvBzVyarR1KEqJDEY79yi/hCPbu3h3enLy4uO+6Am1jegxNn77
/vj46MXR89OL0+fvz55D82eeNYcKv54tCoqajgru8ubg+MXJ6Zvnzy7wCdDn
Z+cf921EU15yoaRovojmLejgzcn7t9i6XF5efx6BugDaX/Q5ni1n+LreMRjm
vTXmvlZwnRntfIUNS+q6VselVwDjzI4rYfWSGYqPJ4OwoGXPRyJHsohe9fBe
UTu27Js0X3plGl8ABARexoV5NeauXIrKC37HpCZ7D9fRCTWxaXON2iRpVB68
6wYwvAGSZKa759vcc/fmSeYCX2cJ08tL++b8KY6MfP04yjDj4BhY3mKRZkVO
yQK6+rwgyZV3Dk5iltLduS+89hJ9kRTG8IMu2/jqWASM96j3Mav9JdgWZWiV
Hl+UNBsEP6kWeFIt1NfkSmfZNyIJXtBypE1SjfdQ34LzNfOaZerw2pAZ44ED
5GSEKfk6Ixu9+rziNKq+rFh6Plz0oM8kuAKU3967qc4e319f5/cp+UEX9wUh
gwR7JI8q5sbwqj8TarT6d+p79fc1b7znn/nqXewGPVv10mrl3VY75LrK17zX
Tu0jj/nGm9IY7PWzcPb1tZVPotK4xpMM/YPgm4OB+qaqULEfVTYGn1dX5z6q
LBO+wOsVcJS+Bd98L3+D439VIOXhTd0XMJupKGAY6zfVh3+b8t8e/4NmHH1y
2RXf1Bb824V/A2nXV95wwnnrxRykI/7ryj+cgLEpjr3/NKj/pwC7Cca9HTgW
m8cINfxtF3/rYaW+LfoNq/oNjlfAvbdt+26aHvjLscXVA3AwEBwc8z+ThHgs
WYRlkXHXi7DmLXp2fgrmDs39WoQ9Mu5GSONSeXHE3HFnXZNeuKX+z/9w8WTa
lX97XTpAA2jW6m0SRNakMzZ2LmnrW0Z3wy134nbEi53310HBWxQpGKVHTI/J
KW4ES5M73H73BnSlpP5OPDL18ylGcrgF6HSsEHDkDR/TLkx+NGlab4wPl2+U
o1MiJfOW+VnpndXkFp2T5M9yj7mafrPolt5rW461OBjsE7HkHS3oIKFjyfXl
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

-->

</rfc>
