<?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.43 (Ruby 3.4.9) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ladd-mole-ec-ihat-00" category="info" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.34.1 -->
  <front>
    <title abbrev="EC-IHAT">EC-IHAT: Issuer-Hiding Anonymous Tokens</title>
    <seriesInfo name="Internet-Draft" value="draft-ladd-mole-ec-ihat-00"/>
    <author fullname="Samuel Schlesinger">
      <organization>Google LLC</organization>
      <address>
        <email>sgschlesinger@gmail.com</email>
      </address>
    </author>
    <author fullname="Watson Ladd">
      <organization>Akamai Technologies</organization>
      <address>
        <email>watsonbladd@gmail.com</email>
      </address>
    </author>
    <author fullname="Deep Inder Mohan">
      <organization>Georgia Institute of Technology</organization>
      <address>
        <email>dmohan@gatech.edu</email>
      </address>
    </author>
    <date year="2026" month="November" day="02"/>
    <keyword>moderation</keyword>
    <keyword>endorsement</keyword>
    <keyword>unlinkability</keyword>
    <keyword>privacy</keyword>
    <abstract>
      <?line 151?>

<t>This document specifies EC-IHAT, a cryptographic construction used to
produce and consume MOLE Endorsements. An Endorsement is an anonymous token that
an Anchor issues to a Client, and that the Client later redeems at a Moderator
without the Anchor being able to link the redemption to the issuance.</t>
      <t>This document defines the endorsement issuance protocol, built from a
pairing-free partially blind signature scheme, together with the group,
encoding, and context-binding rules that both the Anchor and the Client follow.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://moderation-of-unlinkable-endorsements.github.io/internet-drafts/draft-ladd-mole-ec-ihat.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ladd-mole-ec-ihat/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/Moderation-of-unLinkable-Endorsements/internet-drafts"/>.</t>
    </note>
  </front>
  <middle>
    <?line 163?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>MOLE Endorsements have a number of constraints imposed by the architecture
<xref target="ARCH"/>. They must be unlinkable by the Anchor that issued them, they must be
publicly verifiable, and a redemption must hide which Anchor issued the
Endorsement among the set of Anchors a Moderator accepts. Existing systems do
not meet all of these needs. This document defines such a system, EC-IHAT,
an Issuer-Hiding Anonymous Token (IHAT).</t>
      <t>EC-IHAT follows the construction described in Section 3.4 of <xref target="FFKLLS26"/>,
which in turn is based on the pairing-free partially blind signature of
<xref target="TESSZHU"/>. An Anchor holds a signing key and issues, in three moves, a
signature on a Client-chosen message that the Anchor never sees. Each
Endorsement is also bound at issuance time to two contexts. These may be used to
limit the validity scope of each Endorsement, i.e., when and for whom it may
later be used:</t>
      <ul spacing="normal">
        <li>
          <t>The issuance context <tt>ctx_iss</tt> is agreed out of band among the Client, the
Anchor, and the Moderator. <tt>ctx_iss</tt> can encode, for instance, the time
period in which the Endorsement is issued, ensuring Endorsements expire.</t>
        </li>
        <li>
          <t>The redemption context <tt>ctx_red</tt> is agreed out of band between the Client
and the Moderator. For example, it may be a long-term identity of the target
Moderator. This may be used to prevent Endorsement reuse across Moderators
without requiring a synchronized state between them.</t>
        </li>
      </ul>
      <t>The remainder of this document is organized as follows. After defining
conventions and cryptographic preliminaries (<xref target="preliminaries"/>), we given an
overview of issuance and specify some functionalities common to issuance and
redemption <xref target="scheme"/>. <xref target="issuance"/> specifies the issuance flow, including
message encodings and session handling. <xref target="redemption"/> specifies issuer-hiding
redemption, including key rerandomization and the proof that the issuing Anchor
belongs to the Moderator's Anchor Set. <xref target="ciphersuites"/> defines the supported
ciphersuites, and <xref target="security-considerations"/> discusses the construction's
security and deployment considerations. <xref target="iana"/> covers IANA considerations, and
<xref target="test-vectors"/> provides test vectors for the ciphersuites defined here.</t>
    </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?>

<t>The terms Client, Anchor, Moderator, Endorsement, Credential, and Anchor Set
are used as defined in <xref target="ARCH"/>.</t>
      <t>Unless otherwise specified, this document encodes protocol messages in TLS
notation (<xref section="3" sectionFormat="of" target="TLS13"/>). Moreover, all constants are in network byte
order. For variable-size vectors written <tt>&lt;V&gt;</tt>, the length prefix is a
variable-length integer (<xref section="16" sectionFormat="of" target="QUIC"/>), whose width depends on the
length of the contents it carries. The minimum-size encoding is recommended.</t>
      <t>Algorithms are specified in Python and use the following functions, types, and
notation.</t>
      <t>Type <tt>bytes</tt> is used for byte strings, <tt>int</tt> for integers, and <tt>Sequence</tt> for a
read-only sequence.</t>
      <t>For any byte string <tt>x</tt>, <tt>len(x)</tt> denotes its length in bytes.</t>
      <t>For two byte strings <tt>x</tt> and <tt>y</tt>, <tt>x + y</tt> denotes their concatenation, and,
if they are of equal length, <tt>_xor(x, y)</tt> denotes their bytewise exclusive or.</t>
      <t>For a byte string <tt>x</tt>, <tt>x[i:j]</tt> denotes the substring of <tt>x</tt> that begins at
its byte with index <tt>i</tt> and ends just before its byte with index <tt>j</tt>, where
indices start at zero. Its length is <tt>j - i</tt> bytes.</t>
      <t>For a list <tt>x</tt>, <tt>x[i]</tt> denotes its element at index <tt>i</tt>, counting from zero,
<tt>x[i:j]</tt> denotes the sublist from index <tt>i</tt> up to but not including index <tt>j</tt>,
and <tt>len(x)</tt> denotes the number of elements it holds.</t>
      <t><tt>I2OSP(value, length)</tt> converts a nonnegative integer into a byte string of the
requested length in big-endian byte order, as described in <xref target="I2OSP"/>. We write
<tt>U16Prefixed(value)</tt> for the concatenation of <tt>I2OSP(len(value), 2)</tt> and
byte string <tt>value</tt>.</t>
      <t><tt>random(n)</tt> returns <tt>n</tt> uniformly random bytes. Implementations <bcp14>MUST</bcp14> generate
them with a cryptographically secure random number generator. It is the only
source of randomness in this document: every other value that has to be
unpredictable is derived from its output (<xref target="derive-scalar"/>).</t>
      <t><tt>Seed(x, k)</tt> denotes the <tt>k</tt>-th seed in a byte string of concatenated seeds,
that is <tt>x[k * Nseed:(k + 1) * Nseed]</tt>, with <tt>k</tt> counted from zero.
<xref target="ciphersuites"/> fixes the seed length <tt>Nseed</tt>. This function is defined as
follows:</t>
      <sourcecode type="python"><![CDATA[
def Seed(value: bytes, index: int) -> bytes:
    return value[index * Nseed : (index + 1) * Nseed]
]]></sourcecode>
      <t>Byte strings such as <tt>b"Challenge"</tt> contain the corresponding ASCII bytes and
do not include a terminating NUL byte.</t>
      <t>The definitions of the record types named in function signatures are implicit.
Parameters become constant values once the ciphersuite is fixed. An algorithm
that can fail raises an error; the errors used in this document are listed in
<xref target="errors"/>.</t>
    </section>
    <section anchor="preliminaries">
      <name>Preliminaries</name>
      <t>The construction has two dependencies:</t>
      <dl>
        <dt>Group:</dt>
        <dd>
          <t>A prime-order group implementing the interface in <xref target="group"/>. <xref target="ciphersuites"/>
gives concrete instances.</t>
        </dd>
        <dt>Hash:</dt>
        <dd>
          <t>A cryptographic hash function whose output length is <tt>Nh</tt> bytes.</t>
        </dd>
      </dl>
      <section anchor="group">
        <name>Prime-Order Group</name>
        <t>This document uses an additive, prime-order group, denoted <tt>G</tt>, of order <tt>p</tt>,
as described in <xref section="2.1" sectionFormat="of" target="OPRF"/>. The types <tt>Element</tt> and <tt>Scalar</tt>
denote elements of the group and of its scalar field respectively. Group
elements are added with <tt>+</tt> and subtracted with <tt>-</tt>; scalar multiplication of
an <tt>Element</tt> <tt>A</tt> by a <tt>Scalar</tt> <tt>r</tt> is written <tt>r * A</tt>. Scalars are added,
subtracted, and multiplied modulo <tt>p</tt>. In the Python snippets, <tt>G.scalar(x)</tt>
converts an integer <tt>x</tt> in <tt>[0, p)</tt> to a <tt>Scalar</tt>.</t>
        <t>The group also provides <tt>G.DeriveScalars</tt>, <tt>G.ExpandScalars</tt>,
<tt>G.DeriveNonces</tt>, <tt>G.DeriveKeyPair</tt>, and <tt>G.GenerateKeyPair</tt>, defined in
<xref target="derive-scalar"/>, <xref target="derive-nonce"/>, and <xref target="keygen"/>.</t>
        <t>The following member functions are used. Except where noted, they are as
defined in <xref section="2.1" sectionFormat="of" target="OPRF"/>.</t>
        <dl>
          <dt>Order():</dt>
          <dd>
            <t>Outputs the order <tt>p</tt> of the group.</t>
          </dd>
          <dt>Identity():</dt>
          <dd>
            <t>Outputs the identity element of the group.</t>
          </dd>
          <dt>Generator():</dt>
          <dd>
            <t>Outputs the generator element <tt>B</tt> of the group.</t>
          </dd>
          <dt>ScalarMultGen(r):</dt>
          <dd>
            <t>Outputs <tt>r * B</tt>, where <tt>B</tt> is the group generator.</t>
          </dd>
          <dt>HashToGroup(x, DST):</dt>
          <dd>
            <t>Deterministically maps a byte string <tt>x</tt> to an <tt>Element</tt>, using the byte
string <tt>DST</tt> as the domain separation tag. The map is specified in
<xref target="ciphersuites"/>.</t>
          </dd>
          <dt>HashToGroup(x):</dt>
          <dd>
            <t>Equivalent to <tt>HashToGroup(x, DST=b"HashToGroup-" + ctx_proto)</tt> where
<tt>ctx_proto</tt> is as defined in <xref target="config"/>.</t>
          </dd>
          <dt>HashToScalar(x, DST):</dt>
          <dd>
            <t>Deterministically maps a byte string <tt>x</tt> to a <tt>Scalar</tt>, using the byte
string <tt>DST</tt> as the domain separation tag. The map is specified in
<xref target="ciphersuites"/>.</t>
          </dd>
          <dt>HashToScalar(x):</dt>
          <dd>
            <t>Equivalent to <tt>HashToScalar(x, DST=b"HashToScalar-" + ctx_proto)</tt> where
<tt>ctx_proto</tt> is as defined in <xref target="config"/>.</t>
          </dd>
          <dt>ScalarInverse(s):</dt>
          <dd>
            <t>Outputs the multiplicative inverse of the nonzero <tt>Scalar</tt> <tt>s</tt> modulo <tt>p</tt>.</t>
          </dd>
          <dt>SerializeElement(A):</dt>
          <dd>
            <t>Maps an <tt>Element</tt> <tt>A</tt> other than the identity element to a canonical byte
string of fixed length <tt>Ne</tt>. Raises a <tt>ValueError</tt> if <tt>A</tt> is the identity
element, which has no such encoding.</t>
          </dd>
          <dt>DeserializeElement(buf):</dt>
          <dd>
            <t>Attempts to map a byte string <tt>buf</tt> to an <tt>Element</tt>. Raises a
<tt>DeserializeError</tt> if <tt>buf</tt> is not the canonical encoding of a group element,
or if it encodes the identity element.</t>
          </dd>
          <dt>SerializeScalar(s):</dt>
          <dd>
            <t>Maps a <tt>Scalar</tt> <tt>s</tt> to a canonical byte string of fixed length <tt>Ns</tt>.</t>
          </dd>
          <dt>DeserializeScalar(buf):</dt>
          <dd>
            <t>Attempts to map a byte string <tt>buf</tt> to a <tt>Scalar</tt>. Raises a
<tt>DeserializeError</tt> if <tt>buf</tt> does not encode a <tt>Scalar</tt> in the range
<tt>[0, p-1]</tt>.</t>
          </dd>
        </dl>
        <t>This document does not use the <tt>RandomScalar()</tt> member of
<xref section="2.1" sectionFormat="of" target="OPRF"/>. Every scalar that has to be unpredictable is instead
obtained from <tt>G.DeriveScalars</tt> (<xref target="derive-scalar"/>), <tt>G.DeriveNonces</tt>
(<xref target="derive-nonce"/>), or <tt>G.DeriveKeyPair</tt> (<xref target="keygen"/>), each deterministic in
its random input. Each algorithm is therefore a deterministic function of its
random input, which the test vectors of <xref target="test-vectors"/> fix.</t>
      </section>
      <section anchor="errors">
        <name>Errors</name>
        <t>The following errors are used.</t>
        <dl>
          <dt>DeserializeError:</dt>
          <dd>
            <t>A byte string is not a canonical encoding of the expected type.</t>
          </dd>
          <dt>VerifyError:</dt>
          <dd>
            <t>A received value failed a verification check.</t>
          </dd>
          <dt>DeriveError:</dt>
          <dd>
            <t>A deterministic derivation failed to produce a usable scalar. See
<xref target="derive-scalar"/>.</t>
          </dd>
          <dt>ValueError:</dt>
          <dd>
            <t>An input has an invalid length or is outside its permitted range.</t>
          </dd>
        </dl>
        <t>An implementation that raises an error <bcp14>MUST</bcp14> abort the protocol run. Errors are
fatal to the affected session; see <xref target="sessions"/>.</t>
      </section>
    </section>
    <section anchor="scheme">
      <name>The Endorsement Scheme</name>
      <t>Issuance is a three-move protocol between a Client and an Anchor, followed by a
local finalization step at the Client. The Anchor moves first and holds
per-session state between its two moves, as shown in
<xref target="fig-issuance"/>.</t>
      <t>The Anchor speaks first. This document does not prescribe how the three
messages are carried, nor how a Client that wants an Endorsement reaches an
Anchor in the first place; both are the business of the transport, and a Client
will in general have to signal its intent by some means that carries no
protocol data. For example, over HTTP a Client might ask for issuance in a
request that names how many Endorsements it wants, receive the commitments in
the response, send the challenges in a second request, and receive the
responses in the reply to that. <xref target="wire"/> specifies the encoding of the three
messages.</t>
      <t>Neither context is carried in these messages. Both parties already hold the
issuance context, having agreed on it out of band; the redemption context is
known only to the Client and Moderator.</t>
      <t>The Client's output is an Endorsement that is publicly verifiable under the
Anchor's public key <tt>pkA</tt> (<xref target="verify"/>). The Anchor learns neither the nullifier
nor the redemption context bound into it, and cannot link the Endorsement to
the session that produced it.</t>
      <section anchor="config">
        <name>Configuration and Protocol Context</name>
        <t>A ciphersuite (<xref target="ciphersuites"/>) is identified by an ASCII string
<tt>identifier</tt>. Both parties <bcp14>MUST</bcp14> agree on the ciphersuite before running the
protocol.</t>
        <t>The protocol context, written <tt>ctx_proto</tt>, is the domain separation tag that
this document derives from that identifier:</t>
        <sourcecode type="python"><![CDATA[
def CreateProtocolContext(identifier: bytes) -> bytes:
    return b"EC-IHATv1-" + identifier
]]></sourcecode>
        <t>Throughout the remainder of this document, <tt>ctx_proto</tt> denotes the output of
<tt>CreateProtocolContext</tt> for the ciphersuite in use. It is distinct from the
issuance and redemption contexts of <xref target="context-binding"/>: those are inputs to
the protocol, chosen by its participants, whereas <tt>ctx_proto</tt> is fixed by the
ciphersuite.</t>
        <t>Every hash this document computes, other than the round functions of the
permutation <tt>P</tt> (<xref target="permutation"/>), is domain-separated by <tt>ctx_proto</tt>, which
appears in its DST. <tt>HashToGroup</tt> and <tt>HashToScalar</tt> are so parameterized
(<xref target="ciphersuites"/>), as are <tt>G.DeriveScalars</tt> and <tt>G.ExpandScalars</tt>
(<xref target="derive-scalar"/>) and <tt>G.DeriveNonces</tt> (<xref target="derive-nonce"/>). Every algorithm
below therefore depends
on <tt>ctx_proto</tt>, even where it does not appear, and a value produced under one
ciphersuite does not verify under another. The Python group instance <tt>G</tt>
stores this context as <tt>G.ctx_proto</tt>. The group methods below use <tt>self</tt> for
that instance, so the context is fixed when <tt>G</tt> is constructed.</t>
      </section>
      <section anchor="derive-scalar">
        <name>Deriving Scalars</name>
        <t>The group method <tt>G.DeriveScalars</tt> derives <tt>count</tt> values in the scalar field
of <tt>G</tt> from <tt>Nseed</tt> bytes of randomness <tt>rand</tt>. An algorithm that needs random
scalars derives them all with one call, under an <tt>info</tt> string that names the
algorithm. <tt>rand</tt> and <tt>info</tt> are hashed into a key, which is expanded into
the scalars:</t>
        <sourcecode type="python"><![CDATA[
def DeriveScalars(
    self, rand: bytes, info: bytes, count: int
) -> list[Scalar]:
    if len(rand) != Nseed:
        raise ValueError(f"rand must be exactly {Nseed} bytes")
    key = expand_message_xmd(
        rand + U16Prefixed(info),
        b"DeriveScalars-" + self.ctx_proto,
        Nh,
    )
    return self.ExpandScalars(key, count)
]]></sourcecode>
        <t>The group method <tt>G.ExpandScalars</tt> hashes the key and an index to each scalar
in turn:</t>
        <sourcecode type="python"><![CDATA[
def ExpandScalars(self, key: bytes, count: int) -> list[Scalar]:
    scalars = []
    for i in range(count):
        s = self.HashToScalar(
            key + I2OSP(i, 4), DST=b"ExpandScalars-" + self.ctx_proto
        )
        if s.isZero():
            raise DeriveError
        scalars.append(s)
    return scalars
]]></sourcecode>
        <t><tt>expand_message_xmd</tt> is that of <xref section="5.3.1" sectionFormat="of" target="HASH2CURVE"/>, over the hash
function of the ciphersuite. <tt>rand</tt> <bcp14>MUST</bcp14> be <tt>Nseed</tt> bytes of output of <tt>random</tt>
and <bcp14>MUST NOT</bcp14> be used for more than one derivation. A derived scalar is zero, and
<tt>DeriveError</tt> raised, with negligible probability; implementations might choose
to panic rather than handle the exception.</t>
        <t>The two-stage derivation used here and in <xref target="derive-nonce"/> avoids the
output-length limit of a single <tt>hash_to_field</tt> call using <tt>expand_message_xmd</tt>.
XMD produces at most <tt>255 * Nh</tt> bytes per call, which allows at most 170 scalars
with SHA-256 and <tt>L = 48</tt> (see <tt>EC-IHAT(P-256, SHA-256)</tt> <xref target="ciphersuites"/>).
Although EC-IHAT's issuer-hiding proof needs fewer scalars, other protocols
that share these methods need larger vectors.</t>
      </section>
      <section anchor="derive-nonce">
        <name>Deriving Nonces</name>
        <t>The nonces of a proof of knowledge, and the other secret values of its first
move, must not be reused under a different challenge. The group method
<tt>G.DeriveNonces</tt> derives them together from <tt>rand</tt>, a secret the party holds,
and a public description of the operation, as the hedged signatures of
<xref target="DETSIGS"/> derive theirs:</t>
        <sourcecode type="python"><![CDATA[
def DeriveNonces(
    self,
    secret: bytes,
    label: bytes,
    instance: bytes,
    rand: bytes,
    count: int,
) -> list[Scalar]:
    if len(rand) != Nseed:
        raise ValueError(f"rand must be exactly {Nseed} bytes")
    derive_nonce_input = (
        PadToBlock(rand)
        + PadToBlock(I2OSP(len(secret), 4) + secret)
        + U16Prefixed(label)
        + I2OSP(len(instance), 4)
        + instance
    )
    key = expand_message_xmd(
        derive_nonce_input, b"DeriveNonces-" + self.ctx_proto, Nh
    )
    return self.ExpandScalars(key, count)
]]></sourcecode>
        <t><tt>PadToBlock</tt> appends zero bytes up to a multiple of <tt>s_in_bytes</tt>, the input
block size of the hash function (<xref section="5.3.1" sectionFormat="of" target="HASH2CURVE"/>):</t>
        <sourcecode type="python"><![CDATA[
def PadToBlock(value: bytes) -> bytes:
    return value + bytes(-len(value) % s_in_bytes)
]]></sourcecode>
        <t><tt>expand_message_xmd</tt> starts its input with a block of zeros, so the hash
function absorbs <tt>rand</tt> in a block of its own and then <tt>secret</tt> in blocks of
its own, before any public input, as <xref target="DETSIGS"/> recommends against
side-channel and fault attacks. When <tt>rand</tt> is uniformly random, the nonces
are distributed as derived scalars (<xref target="derive-scalar"/>). If the random source
fails in a way that does not depend on <tt>secret</tt>, the nonces are still hash
outputs on an input that contains <tt>secret</tt>, so to an adversary that does not
know <tt>secret</tt> a change to any part of <tt>rand</tt> or <tt>instance</tt> changes every
nonce unpredictably, except with negligible probability, and no nonce is
reused under a different challenge. Repeating all of <tt>rand</tt> for the same
operation reproduces the same proof. Every <tt>instance</tt> in this document is an
unambiguous encoding, with its variable-length parts length-prefixed.
Implementations <bcp14>MUST</bcp14> wipe <tt>secret</tt>, <tt>derive_nonce_input</tt>, <tt>key</tt>, and the
returned values once they have been used.</t>
      </section>
      <section anchor="keygen">
        <name>Key Generation</name>
        <t>An Anchor holds a key pair <tt>(skA, pkA)</tt>. It is derived from a seed, which is
what allows the test vectors in <xref target="test-vectors"/> to fix a key. The procedure is
the key generation of <xref section="3.2" sectionFormat="of" target="OPRF"/>. The secrecy of <tt>skA</tt> rests on
that of <tt>seed</tt>; <tt>info</tt> is usually public.</t>
        <sourcecode type="python"><![CDATA[
def DeriveKeyPair(
    self, seed: bytes, info: bytes
) -> tuple[Scalar, Element]:
    if len(seed) != Nseed:
        raise ValueError(f"seed must be exactly {Nseed} bytes")
    derive_input = seed + U16Prefixed(info)
    for counter in range(256):
        skA = self.HashToScalar(
            derive_input + I2OSP(counter, 1),
            DST=b"DeriveKeyPair-" + self.ctx_proto,
        )
        if not skA.isZero():
            return (skA, self.ScalarMultGen(skA))
    raise DeriveError
]]></sourcecode>
        <t>The derivation differs from that of <xref section="3.2" sectionFormat="of" target="OPRF"/> only in its domain
separation tag, which comes from the protocol context of this document rather
than from an OPRF context string, and in the length of the seed. The loop
terminates after one iteration except with probability about <tt>1/p</tt>.</t>
        <t>A fresh key pair is generated by deriving one from a random seed.</t>
        <sourcecode type="python"><![CDATA[
def GenerateKeyPair(self) -> tuple[Scalar, Element]:
    seed = random(Nseed)
    return self.DeriveKeyPair(seed, b"GenerateKeyPair")
]]></sourcecode>
        <t>The Anchor publishes <tt>SerializeElement(pkA)</tt> in its configuration.</t>
      </section>
      <section anchor="context-binding">
        <name>Context Binding</name>
        <t>Each Endorsement is bound at issuance to two contexts, the issuance context and
the redemption context, and a redemption succeeds only if the Client and the
Moderator agree on both values. Both are opaque byte strings. <tt>ctx_iss</tt> is at
most <tt>2^16 - 1</tt> bytes. Because the encoded message is itself passed to
<tt>U16Prefixed</tt>, <tt>ctx_red</tt> is at most <tt>2^16 - 1 - Nn - 4</tt> bytes. These bounds are
enforced by <tt>U16Prefixed</tt>. The two contexts are bound by deliberately different
means, reflecting who is trusted to choose each.</t>
        <t>The examples below illustrate their cryptographic roles.</t>
        <t>The issuance context, written <tt>ctx_iss</tt>, restricts when, and potentially where,
an Endorsement may be redeemed; it might for example name the epoch the
Endorsement was issued in. Both parties hold it. It is bound by deriving the
second commitment base from it:</t>
        <sourcecode type="python"><![CDATA[
def CreateContextBase(ctx_iss: bytes) -> Element:
    context_base_input = U16Prefixed(ctx_iss) + b"ContextBase"
    return G.HashToGroup(context_base_input)
]]></sourcecode>
        <t>The Anchor forms its commitment under this base, and the base is recomputed at
verification time. The Client and the Anchor <bcp14>MUST</bcp14> agree on the issuance context.
Disagreement causes issuance to fail: a Client that uses any other value fails
the commitment-opening check in <tt>Finalize</tt>. The binding is therefore enforced by
the construction rather than by an explicit check, and a Client cannot bind an
Endorsement to an issuance context of its own choosing.</t>
        <t>The redemption context, written <tt>ctx_red</tt>, restricts where an Endorsement
may be redeemed: a redemption succeeds only under the value the Endorsement was
issued under. It might for example identify the Moderator the Client intends to
redeem at, in which case the Endorsement is redeemable at that Moderator and at
no other. It is chosen by the Client and is hidden from the Anchor. It is bound
by placing it, together with a fresh Client-chosen nullifier <tt>nf</tt> of <tt>Nn = 32</tt>
bytes, in the signed message:</t>
        <sourcecode type="python"><![CDATA[
def Message(nf: bytes, ctx_red: bytes) -> bytes:
    if len(nf) != Nn:
        raise ValueError(f"nullifier must be exactly {Nn} bytes")
    return U16Prefixed(nf) + U16Prefixed(ctx_red)
]]></sourcecode>
        <t>A redemption under a different redemption context recomputes a different
message, for which the Client holds no valid signature. Two consequences
follow. A Client has to fix <tt>ctx_red</tt> before it runs <tt>Challenge</tt>, that is,
before the Endorsement exists; and an Endorsement cannot afterwards be re-bound
to another value, so a Client that needs to redeem under several redemption
contexts needs a separate Endorsement, and so a separate issuance, for each.
Anchors bound how many Endorsements they grant a given Client in order to keep
Endorsements scarce (<xref target="ARCH"/>), so that budget is consumed per redemption
context rather than per Client.</t>
        <t>The nullifier <tt>nf</tt> <bcp14>MUST</bcp14> be a fresh string of <tt>Nn</tt> uniformly random bytes,
generated by the Client, and <bcp14>MUST NOT</bcp14> be reused across Endorsements. It is
revealed during redemption, so the Moderator ensures each Endorsement is
redeemed at most once.</t>
        <t>The values the two contexts take determine the anonymity set a Client redeems
in, and a deployment can destroy the unlinkability the construction provides
without breaking any of its cryptographic properties; see
<xref target="security-considerations"/>.</t>
      </section>
    </section>
    <section anchor="issuance">
      <name>Endorsement Issuance</name>
      <t>Issuance produces a signature on the message <tt>Message(nf, ctx_red)</tt> relative to
the public input <tt>ctx_iss</tt>. It consists of four algorithms, run in the order
shown in <xref target="fig-issuance"/>.</t>
      <figure anchor="fig-issuance">
        <name>Endorsement issuance overview</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="384" viewBox="0 0 384 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
              <path d="M 40,64 L 40,144" fill="none" stroke="black"/>
              <path d="M 40,176 L 40,272" fill="none" stroke="black"/>
              <path d="M 80,32 L 80,64" fill="none" stroke="black"/>
              <path d="M 304,32 L 304,64" fill="none" stroke="black"/>
              <path d="M 336,64 L 336,80" fill="none" stroke="black"/>
              <path d="M 336,112 L 336,208" fill="none" stroke="black"/>
              <path d="M 336,240 L 336,320" fill="none" stroke="black"/>
              <path d="M 376,32 L 376,64" fill="none" stroke="black"/>
              <path d="M 8,32 L 80,32" fill="none" stroke="black"/>
              <path d="M 304,32 L 376,32" fill="none" stroke="black"/>
              <path d="M 8,64 L 80,64" fill="none" stroke="black"/>
              <path d="M 304,64 L 376,64" fill="none" stroke="black"/>
              <path d="M 48,128 L 112,128" fill="none" stroke="black"/>
              <path d="M 272,128 L 336,128" fill="none" stroke="black"/>
              <path d="M 40,192 L 144,192" fill="none" stroke="black"/>
              <path d="M 240,192 L 328,192" fill="none" stroke="black"/>
              <path d="M 48,256 L 112,256" fill="none" stroke="black"/>
              <path d="M 280,256 L 336,256" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="336,192 324,186.4 324,197.6" fill="black" transform="rotate(0,328,192)"/>
              <polygon class="arrowhead" points="56,256 44,250.4 44,261.6" fill="black" transform="rotate(180,48,256)"/>
              <polygon class="arrowhead" points="56,128 44,122.4 44,133.6" fill="black" transform="rotate(180,48,128)"/>
              <g class="text">
                <text x="44" y="52">Client</text>
                <text x="340" y="52">Anchor</text>
                <text x="332" y="100">Commit</text>
                <text x="164" y="132">commitment</text>
                <text x="224" y="132">(A,</text>
                <text x="252" y="132">C)</text>
                <text x="40" y="164">Challenge</text>
                <text x="192" y="196">challenge</text>
                <text x="336" y="228">Respond</text>
                <text x="156" y="260">response</text>
                <text x="208" y="260">(s,</text>
                <text x="236" y="260">y,</text>
                <text x="260" y="260">t)</text>
                <text x="36" y="292">Finalize</text>
                <text x="40" y="308">|</text>
                <text x="48" y="324">endorsement</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
+--------+                           +--------+
| Client |                           | Anchor |
+---+----+                           +---+----+
    |                                    |
    |                                 Commit
    |                                    |
    |<-------- commitment (A, C) --------+
    |                                    |
Challenge                                |
    |                                    |
    +------------- challenge ----------->|
    |                                    |
    |                                 Respond
    |                                    |
    |<-------- response (s, y, t) -------+
    |                                    |
Finalize                                 |
    |                                    |
endorsement                              |
]]></artwork>
        </artset>
      </figure>
      <t><tt>Commit</tt> and <tt>Respond</tt> are run by the Anchor; <tt>Challenge</tt> and <tt>Finalize</tt> are
run by the Client. Both parties input the issuance context <tt>ctx_iss</tt>; only the
Client inputs the redemption context <tt>ctx_red</tt>.</t>
      <t>Each of the first three algorithms outputs one protocol message, and the next
algorithm takes that message as a single input. The messages are the commitment,
a pair of points <tt>(A, C)</tt>; the challenge, a single scalar; and the response, a
triple of scalars <tt>(s, y, t)</tt>. The types <tt>Commitment</tt> and <tt>Response</tt> denote the
first and the last of these. The wire format of each message is defined in
<xref target="wire"/>. All four algorithms treat <tt>G</tt>, <tt>ctx_proto</tt>, <tt>Nn</tt>, and <tt>Nseed</tt> as
global variables.</t>
      <section anchor="commit">
        <name>Anchor Commitment</name>
        <t>The Anchor opens a session by committing to the values it will later reveal.</t>
        <sourcecode type="python"><![CDATA[
def Commit(ctx_iss: bytes) -> tuple[AnchorState, Commitment]:
    Z = CreateContextBase(ctx_iss)

    rand = random(Nseed)
    (a, t, y) = G.DeriveScalars(rand, b"Commit", 3)

    A = G.ScalarMultGen(a)
    C = G.ScalarMultGen(t) + y * Z

    state = AnchorState(a, y, t)
    commitment = Commitment(A, C)
    return (state, commitment)
]]></sourcecode>
        <t>The Anchor stores <tt>state</tt> for the duration of the session and sends <tt>commitment</tt>
to the Client in a <tt>CommitMessage</tt> (<xref target="wire"/>). The signing key is not needed
until <tt>Respond</tt>.</t>
      </section>
      <section anchor="challenge">
        <name>Client Challenge</name>
        <t>The Client blinds the Anchor's commitment, derives the challenge over the
blinded values, and returns the challenge in blinded form.</t>
        <sourcecode type="python"><![CDATA[
def Challenge(
    pkA: Element,
    ctx_iss: bytes,
    ctx_red: bytes,
    commitment: Commitment,
) -> tuple[ClientState, Scalar]:
    if pkA.isIdentity():
        raise VerifyError

    (A, C) = commitment

    rand = random(Nn + Nseed)
    nf = rand[:Nn]
    (r1, r2, gamma1, gamma2) = G.DeriveScalars(
        rand[Nn:], b"Challenge", 4
    )

    m = Message(nf, ctx_red)
    gamma = gamma1 * G.ScalarInverse(gamma2)

    blinded_A = G.ScalarMultGen(r1) + gamma * A
    blinded_C = gamma1 * C + G.ScalarMultGen(r2)
    blinded_commitment = Commitment(blinded_A, blinded_C)

    c = ComputeChallenge(ctx_iss, blinded_commitment, m)
    if c.isZero():
        raise VerifyError

    challenge = c * gamma2
    state = ClientState(
        nf,
        ctx_iss,
        commitment,
        r1,
        r2,
        gamma1,
        gamma2,
        challenge,
        c,
    )
    return (state, challenge)
]]></sourcecode>
        <t><tt>ComputeChallenge</tt> is as follows:</t>
        <sourcecode type="python"><![CDATA[
def ComputeChallenge(ctx_iss: bytes, commitment: Commitment, m: bytes) -> Scalar:
    (A, C) = commitment

    Am = G.SerializeElement(A)
    Cm = G.SerializeElement(C)

    challenge_transcript = (
        U16Prefixed(ctx_iss)
        + U16Prefixed(Am)
        + U16Prefixed(Cm)
        + U16Prefixed(m)
        + b"Challenge"
    )

    c = G.HashToScalar(challenge_transcript)

    return c
]]></sourcecode>
        <t>Two challenge values appear here: <tt>c</tt> is computed over the blinded commitment
and is the value that ends up in the Endorsement (<xref target="finalize"/>); it never
leaves the Client. The <tt>challenge</tt> message the Anchor receives is its blinded
form <tt>c * gamma2</tt>, and the Anchor cannot recover <tt>c</tt> from it because <tt>gamma2</tt>
is uniform and secret.</t>
        <t><tt>HashToScalar</tt> can return zero, and the construction requires a nonzero
challenge. <tt>Challenge</tt> aborts in that case, which keeps the challenge a
deterministic function of the transcript; this happens with probability about
<tt>1/p</tt> (<xref target="derive-scalar"/>).</t>
        <t>The Client sends <tt>challenge</tt> to the Anchor encoded as a <tt>ChallengeMessage</tt>
(<xref target="wire"/>) and retains <tt>state</tt> for the next step.</t>
      </section>
      <section anchor="respond">
        <name>Anchor Response</name>
        <t>The Anchor answers the challenge and closes the session.</t>
        <sourcecode type="python"><![CDATA[
def Respond(skA: Scalar, state: AnchorState, challenge: Scalar) -> Response:
    (a, y, t) = state

    if challenge.isZero():
        raise VerifyError

    s = a + challenge * y * skA
    response = Response(s, y, t)

    return response
]]></sourcecode>
        <t>The resulting <tt>Response</tt> is encoded as a <tt>ResponseMessage</tt> (<xref target="wire"/>) and sent
to the Client.</t>
        <t>An Anchor <bcp14>MUST</bcp14> call <tt>Respond</tt> at most once per session state produced by
<tt>Commit</tt>, and <bcp14>MUST</bcp14> destroy that state immediately afterwards. Answering two
distinct challenges on the same state discloses the signing key: from
<tt>s1 = a + c1 * y * skA</tt> and <tt>s2 = a + c2 * y * skA</tt> with <tt>c1 != c2</tt>, and <tt>y</tt>
revealed in the response, an attacker recovers
<tt>skA = (s1 - s2) * ScalarInverse((c1 - c2) * y)</tt>. An Anchor <bcp14>MUST NOT</bcp14> run
<tt>Respond</tt> on a state it has already used or discarded.</t>
      </section>
      <section anchor="finalize">
        <name>Client Finalization</name>
        <t>The Client checks the Anchor's response and unblinds it into an Endorsement.</t>
        <sourcecode type="python"><![CDATA[
def Finalize(pkA: Element, state: ClientState, response: Response) -> Endorsement:
    if pkA.isIdentity():
        raise VerifyError

    (nf, ctx_iss, (A, C), r1, r2, gamma1, gamma2, challenge, c) = state
    (s, y, t) = response

    Z = CreateContextBase(ctx_iss)

    if y.isZero():
        raise VerifyError
    if C != G.ScalarMultGen(t) + y * Z:
        raise VerifyError
    if G.ScalarMultGen(s) != A + (challenge * y) * pkA:
        raise VerifyError

    gamma = gamma1 * G.ScalarInverse(gamma2)

    s_final = gamma * s + r1
    y_final = gamma1 * y
    t_final = gamma1 * t + r2

    return Endorsement(c, s_final, y_final, t_final, nf)
]]></sourcecode>
        <t>The three checks verify that the Anchor opened its commitment honestly and
answered the challenge under its published key. A Client whose <tt>Finalize</tt>
raises an error <bcp14>MUST</bcp14> discard the session state and <bcp14>MUST NOT</bcp14> retry the exchange
with the same state.</t>
        <t>An Endorsement consists of the signature <tt>(c, s, y, t)</tt> together with the
nullifier; its encoding is given in <xref target="endorsement-encoding"/>.</t>
      </section>
      <section anchor="verify">
        <name>Endorsement Verification</name>
        <t>An Endorsement is publicly verifiable under the issuing Anchor's public key.</t>
        <t>The two contexts are inputs to <tt>Verify</tt> in addition to the Endorsement. A
verifier therefore states the pair it is willing to accept and learns whether
the Endorsement was issued under it.</t>
        <sourcecode type="python"><![CDATA[
def Verify(
    pkA: Element,
    endorsement: Endorsement,
    ctx_iss: bytes,
    ctx_red: bytes,
) -> bool:
    if pkA.isIdentity():
        return False

    (c, s, y, t, nf) = endorsement

    if len(nf) != Nn or c.isZero() or y.isZero():
        return False

    Z = CreateContextBase(ctx_iss)
    m = Message(nf, ctx_red)

    C = G.ScalarMultGen(t) + y * Z
    A = G.ScalarMultGen(s) - (c * y) * pkA
    if A.isIdentity() or C.isIdentity():
        return False
    commitment = Commitment(A, C)

    return c == ComputeChallenge(ctx_iss, commitment, m)
]]></sourcecode>
        <t>A Moderator never runs <tt>Verify</tt> under an Anchor's public key: a redemption does
not reveal which Anchor issued the Endorsement, so the Moderator runs it under a
rerandomized key and checks an issuer-hiding proof alongside (<xref target="redemption"/>).
The Client <bcp14>MUST NOT</bcp14> reveal the Anchor's public key to the Moderator.</t>
        <t><tt>Verify</tt> rejects a reconstructed <tt>A</tt> or <tt>C</tt> equal to the identity element, which
<tt>SerializeElement</tt> cannot encode. Under an Anchor's key this happens with
negligible probability, but the rerandomized key is the Client's choice, and a
Client that knows its discrete logarithm <tt>x</tt> reaches the identity by setting
<tt>s = c * y * x</tt>.</t>
        <t>An honestly produced Endorsement always verifies. Writing <tt>gamma</tt> for
<tt>gamma1 * ScalarInverse(gamma2)</tt>, and <tt>A_anchor</tt> and <tt>C_anchor</tt> for the two
elements of the Anchor's commitment, the commitment reconstructed by <tt>Verify</tt> is
exactly the blinded commitment the Client hashed in <tt>Challenge</tt>:</t>
        <artwork><![CDATA[
  C = t_final * B + y_final * Z
    = gamma1 * (t * B + y * Z) + r2 * B
    = gamma1 * C_anchor + r2 * B
    = blinded_C

  A = s_final * B - (c * y_final) * pkA
    = (gamma * s + r1) * B - (c * gamma1 * y) * pkA
    = r1 * B + gamma * A_anchor
    = blinded_A
]]></artwork>
        <t>where the last step uses <tt>s = a + challenge * y * skA</tt> and
<tt>challenge = c * gamma2</tt>, so that the two terms in <tt>skA</tt> cancel.</t>
      </section>
      <section anchor="wire">
        <name>Encodings</name>
        <t>This section gives the encoding of the three messages exchanged during
issuance and of the Endorsement they produce.</t>
        <t><tt>Element</tt> and <tt>Scalar</tt> are the fixed-length encodings produced by
<tt>SerializeElement</tt> and <tt>SerializeScalar</tt>, of <tt>Ne</tt> and <tt>Ns</tt> bytes respectively.
A recipient <bcp14>MUST</bcp14> deserialize every received <tt>Element</tt> and <tt>Scalar</tt>, and <bcp14>MUST</bcp14>
abort the session with a <tt>DeserializeError</tt> if deserialization fails. In
particular, deserializing an <tt>Element</tt> rejects the group identity element.
Deserialization of a structure also fails if its input is truncated, if bytes
remain after it, or if a vector's length is not a multiple of the size of its
elements.</t>
        <section anchor="issuance-messages">
          <name>Issuance Messages</name>
          <t>The Anchor opens a session with its commitment:</t>
          <sourcecode type="tls-presentation"><![CDATA[
struct {
  Element A;
  Element C;
} CommitMessage;
]]></sourcecode>
          <t>The Client replies with the blinded challenge:</t>
          <sourcecode type="tls-presentation"><![CDATA[
struct {
  Scalar challenge;
} ChallengeMessage;
]]></sourcecode>
          <t>The Anchor replies with its response, which closes the session:</t>
          <sourcecode type="tls-presentation"><![CDATA[
struct {
  Scalar s;
  Scalar y;
  Scalar t;
} ResponseMessage;
]]></sourcecode>
        </section>
        <section anchor="endorsement-encoding">
          <name>Endorsement</name>
          <t>The output of <tt>Finalize</tt> is encoded as follows.</t>
          <sourcecode type="tls-presentation"><![CDATA[
struct {
  Scalar c;
  Scalar s;
  Scalar y;
  Scalar t;
  opaque nf[Nn];
} Endorsement;
]]></sourcecode>
          <t>This structure is never sent to an Anchor. The Client holds it until it is
redeemed, and <xref target="redemption"/> defines what is sent to a Moderator then. The
issuance and redemption contexts are not carried in it: they are inputs to
<tt>Verify</tt> (<xref target="verify"/>) and to redemption, held by the verifier.</t>
        </section>
      </section>
      <section anchor="sessions">
        <name>Session Handling</name>
        <t>An Anchor is stateful: it holds the secret state produced by <tt>Commit</tt> from the
moment it sends <tt>CommitMessage</tt> until it answers or discards the session. That
state is single-use; see <xref target="respond"/> and <xref target="security-considerations"/>.</t>
        <t>An Anchor <bcp14>SHOULD</bcp14> bound both the number of concurrent open sessions per Client
and the lifetime of an open session, and <bcp14>SHOULD</bcp14> discard state for sessions that
are not completed within that lifetime. Discarding state early is always safe:
it causes the Client's <tt>Finalize</tt> to be unreachable, but cannot produce an
invalid Endorsement.</t>
      </section>
    </section>
    <section anchor="redemption">
      <name>Endorsement Redemption</name>
      <t>A Client redeems an Endorsement at a Moderator.</t>
      <t>An Endorsement is single-use (<xref target="context-binding"/>), so redemption does not have
to hide the signature: the Client reveals it, and the Moderator deduplicates on
the nullifier. What redemption must hide is which Anchor issued it. The
signature of <xref target="issuance"/> verifies under one Anchor's public key, so presenting
it against that key would name the Anchor. Instead the Client rerandomizes the
key (<xref target="rerandomization"/>) and proves in zero knowledge that the rerandomized key
belongs to some Anchor in the Moderator's Anchor Set (<xref target="issuer-proof"/>).</t>
      <t>Redemption is one message from the Client, answering a challenge from the
Moderator. The Moderator holds the ordered Anchor Set and carries it in that
challenge; the Client learns it there and locates its own Anchor in it. Both
parties input the two contexts.</t>
      <figure anchor="fig-redemption">
        <name>Endorsement redemption overview</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="552" viewBox="0 0 552 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
              <path d="M 40,64 L 40,112" fill="none" stroke="black"/>
              <path d="M 40,144 L 40,224" fill="none" stroke="black"/>
              <path d="M 80,32 L 80,64" fill="none" stroke="black"/>
              <path d="M 432,32 L 432,64" fill="none" stroke="black"/>
              <path d="M 480,64 L 480,176" fill="none" stroke="black"/>
              <path d="M 528,32 L 528,64" fill="none" stroke="black"/>
              <path d="M 8,32 L 80,32" fill="none" stroke="black"/>
              <path d="M 432,32 L 528,32" fill="none" stroke="black"/>
              <path d="M 8,64 L 80,64" fill="none" stroke="black"/>
              <path d="M 432,64 L 528,64" fill="none" stroke="black"/>
              <path d="M 48,96 L 88,96" fill="none" stroke="black"/>
              <path d="M 432,96 L 480,96" fill="none" stroke="black"/>
              <path d="M 40,160 L 200,160" fill="none" stroke="black"/>
              <path d="M 304,160 L 472,160" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="480,160 468,154.4 468,165.6" fill="black" transform="rotate(0,472,160)"/>
              <polygon class="arrowhead" points="56,96 44,90.4 44,101.6" fill="black" transform="rotate(180,48,96)"/>
              <g class="text">
                <text x="44" y="52">Client</text>
                <text x="480" y="52">Moderator</text>
                <text x="136" y="100">challenge</text>
                <text x="228" y="100">(anchor_set,</text>
                <text x="352" y="100">challenge_digest)</text>
                <text x="28" y="132">Redeem</text>
                <text x="252" y="164">redemption</text>
                <text x="484" y="196">VerifyRedemption</text>
                <text x="480" y="212">|</text>
                <text x="484" y="228">nf</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
+--------+                                           +-----------+
| Client |                                           | Moderator |
+---+----+                                           +-----+-----+
    |                                                      |
    |<----- challenge (anchor_set, challenge_digest) ------+
    |                                                      |
Redeem                                                     |
    |                                                      |
    +-------------------- redemption --------------------->|
    |                                                      |
    |                                               VerifyRedemption
    |                                                      |
    |                                                      nf
]]></artwork>
        </artset>
      </figure>
      <t><tt>anchor_set</tt> is the list of Anchor public keys the Moderator accepts. Both
parties <bcp14>MUST</bcp14> use the same list in the same order. A proof computed over a
different list or order will not verify.</t>
      <t><tt>challenge_digest</tt> binds the redemption to the challenge that triggered it.
This document treats it as an opaque byte string. The Moderator <bcp14>SHOULD</bcp14> set it
to a collision-resistant digest, such as SHA-256, of the encoded challenge, so
that a redemption produced for one challenge does not verify under another.
Note that this challenge is the Moderator's, and has nothing to do with the issuance challenge of
<xref target="challenge"/>.</t>
      <t>In the remainder, let <tt>index</tt> denote the index of the issuing Anchor in
<tt>anchor_set</tt>.</t>
      <section anchor="rerandomization">
        <name>Key Rerandomization</name>
        <t>The Client shifts the Anchor's public key by a secret scalar <tt>delta</tt> of its own
choosing and adapts the signature to the shifted key. Writing <tt>pkA</tt> for
<tt>anchor_set[index]</tt> and <tt>(c, s, y, t, nf)</tt> for the Endorsement:</t>
        <artwork><![CDATA[
  X_hat = pkA + delta * B
  s_hat = s + (c * y) * delta
]]></artwork>
        <t>Here <tt>B</tt> denotes the group's base point, i.e., <tt>B = G.Generator()</tt>.</t>
        <t>The result is an Endorsement <tt>(c, s_hat, y, t, nf)</tt> that verifies under <tt>X_hat</tt>
exactly as the original verifies under <tt>pkA</tt>, because the shift cancels in the
reconstruction of <tt>A</tt>:</t>
        <artwork><![CDATA[
  s_hat * B - (c * y) * X_hat
    = (s + c * y * delta) * B - (c * y) * (pkA + delta * B)
    = s * B - (c * y) * pkA
]]></artwork>
        <t>Every other value <tt>Verify</tt> recomputes is untouched, so a Moderator can check
the signature by running <tt>Verify</tt> (<xref target="verify"/>) with <tt>X_hat</tt> in place of <tt>pkA</tt>.</t>
        <t>Because this shift is additive, issuance is left unmodified and the
unforgeability of <xref target="issuance"/> carries over to the modified Endorsement
(<xref target="security-considerations"/>). But <tt>X_hat</tt> by itself provides no evidence that
it was derived from an Anchor key. The Client therefore also proves knowledge
of <tt>delta</tt> relating <tt>X_hat</tt> to a key in <tt>anchor_set</tt>, without revealing which
key.</t>
      </section>
      <section anchor="issuer-proof">
        <name>The Issuer-Hiding Proof</name>
        <t>The Client proves knowledge of <tt>delta</tt> such that
<tt>X_hat - anchor_set[i] = delta * B</tt> for at least one <tt>i</tt>, without revealing
which. This is a one-out-of-<tt>n</tt> disjunction of proofs of knowledge of a discrete
logarithm, all over the base <tt>B = G.Generator()</tt>.</t>
        <t>Such a disjunction is classically composed with the technique of Cramer,
Damgard and Schoenmakers <xref target="CDS94"/>, in which the Client answers the branch it
can and simulates the others, sending one challenge and one response per
branch. That proof is linear in <tt>n</tt>, and the Anchor Set is also the anonymity
set (<xref target="security-considerations"/>). This document instead composes the branches
with the <em>stacking</em> technique of Goel, Green, Hall-Andersen and Kaptchuk
<xref target="STACKSIG"/>, whose proof is logarithmic in <tt>n</tt>: the Client sends a single
response, which every branch reuses, together with a commitment whose opening
forces one branch to have been answered honestly.</t>
        <t>The proof takes the rerandomized key of <xref target="rerandomization"/> as its statement
and leaves issuance and <xref target="verify"/> unchanged.</t>
        <t>The construction below first defines the branch proof, then builds a partially
binding tree commitment over its branches. It finally specifies the
Fiat-Shamir challenge and the proving and verification algorithms.</t>
        <t>Each branch is the discrete logarithm proof of <xref target="SIGMA"/>; this document
specifies the composition, its transcript, and its encodings.</t>
        <section anchor="branch">
          <name>The Branch Proof</name>
          <t>The disjunction is proved over the statements</t>
          <artwork><![CDATA[
  Y[i] = X_hat - anchor_set[i]   for i in range(n)
]]></artwork>
          <t>of which the Client can answer branch <tt>index</tt>, where <tt>Y[index] = delta * B</tt>.</t>
          <t>A single branch is proved by the usual three moves: the Client draws a nonce
<tt>r</tt> and commits <tt>T = r * B</tt>; the verifier sends a challenge <tt>proof_challenge</tt>;
the Client answers <tt>response = r - proof_challenge * delta</tt>; and the verifier
checks that <tt>T = proof_challenge * Y[index] + response * B</tt>.</t>
          <t>Read the other way round, that check determines the commitment from the
challenge and the response:</t>
          <sourcecode type="python"><![CDATA[
def BranchCommitment(
    proof_challenge: Scalar,
    response: Scalar,
    Y: Element,
) -> Element:
    return proof_challenge * Y + G.ScalarMultGen(response)


def Statements(
    anchor_set: Sequence[Element],
    X_hat: Element,
) -> list[Element]:
    return [X_hat - pkA for pkA in anchor_set]
]]></sourcecode>
          <t>Two properties make this branch proof stackable in the sense of
<xref target="STACKSIG"/>. First, a
verifying commitment can be computed for any statement from a challenge and a
response, by the function above, without knowing a witness; this is the
extended honest-verifier zero-knowledge property. Second, the response is
a fixed shift of the derived nonce <tt>r</tt>, and so is statistically close to
uniform independently of the statement and witness; see
<xref target="security-considerations"/>. One response can therefore be reused across
branches without revealing which branch produced it.</t>
          <t>A Moderator given <tt>proof_challenge</tt> and one <tt>response</tt> can therefore compute
an accepting commitment for every branch. Soundness comes from the commitment
of <xref target="pbvc"/>: the Client fixes the commitment of one branch before the
challenge exists and cannot change it afterwards.</t>
        </section>
        <section anchor="pbvc">
          <name>Partially Binding Commitments</name>
          <t>A <em>partially binding vector commitment</em> <xref target="STACKSIG"/> commits to a vector of
values such that one position, chosen when the commitment key is generated and
hidden from the Moderator, is binding, while every other position can afterwards
be opened to any value. The Client commits the branch commitment of <tt>index</tt> at
the binding position, and after the challenge is known it opens every other
position to the branch commitment that the shared response determines. The
branch at the binding position uses the actual witness and a commitment fixed
before the challenge; the index of the branch remains hidden by the commitment
key.</t>
          <t>This document uses the commitment of the appendix of <xref target="STACKSIG"/> over pairs,
and then assembles them into a tree. The inputs to the commitments are arbitrary
strings of bytes, and the outputs are compressed group elements.</t>
          <t>The commitment to a pair uses a permutation <tt>P</tt> on group elements. The
inverse of this permutation is denoted <tt>Pinv</tt> (<xref target="permutation"/>).  The
two values are hashed to scalars and committed under the bases <tt>Q</tt> and
<tt>P(Q)</tt>:</t>
          <sourcecode type="python"><![CDATA[
def CommitStep(
    Q: Element,
    left: bytes,
    right: bytes,
    randomness: Scalar,
) -> bytes:
    C = (
        randomness * B
        + G.HashToScalar(left) * Q
        + G.HashToScalar(right) * G.P(Q)
    )
    return G.SerializeElement(C)
]]></sourcecode>
          <t>The committer knows the discrete logarithm of one base, and that is the
position it can later open to another value. A key that binds the <tt>left</tt>
position is one whose <tt>P(Q)</tt> has the known logarithm, and vice versa:</t>
          <sourcecode type="python"><![CDATA[
def GenerateStep(bind_left: bool, secret: Scalar) -> Element:
    T = secret * B
    (Q, _) = G.PermutationPair(T, bind_left)
    return Q
]]></sourcecode>
          <t><tt>bind_left</tt> is a secret boolean: true binds the left position and false
binds the right. <tt>G.PermutationPair</tt> (<xref target="permutation-pair"/>) returns <tt>(Q, P(Q))</tt>,
with <tt>T = P(Q)</tt> when binding left and <tt>T = Q</tt> when binding right. It walks
the same permutation edge in either case, hiding which endpoint has the
known logarithm. Its second output can be cached for use in <tt>CommitStep</tt>.</t>
          <t>The <tt>secret</tt> is the trapdoor: replacing the equivocal value shifts the
opening by the difference of the hashes times the trapdoor, and the
commitment is unchanged:</t>
          <sourcecode type="python"><![CDATA[
def EquivocateStep(
    oldb: bytes, newb: bytes, randomness: Scalar, secret: Scalar
) -> Scalar:
    old = G.HashToScalar(oldb)
    new = G.HashToScalar(newb)
    return randomness + (old - new) * secret
]]></sourcecode>
          <t>A vector <tt>V[0], ..., V[n-1]</tt> of byte strings is committed by pairing
neighbours level by level. Each level has its own key and its own opening;
a vector of odd length carries its last element up unchanged.</t>
          <sourcecode type="python"><![CDATA[
def VecCommit(
    V: Sequence[bytes],
    commitment_keys: Sequence[Element],
    openings: Sequence[Scalar],
) -> bytes:
    if len(V) == 1:
        return V[0]

    V_prime = []
    for i in range(len(V) // 2):
        V_prime.append(
            CommitStep(
                commitment_keys[0], V[2 * i], V[2 * i + 1], openings[0]
            )
        )

    if len(V) % 2 == 1:
        V_prime.append(V[-1])

    return VecCommit(V_prime, commitment_keys[1:], openings[1:])
]]></sourcecode>
          <t>A vector of <tt>n</tt> values has <tt>Depth(n)</tt> levels, each with one key and one
opening:</t>
          <sourcecode type="python"><![CDATA[
def Depth(n: int) -> int:
    q = 0
    while 2**q < n:
        q += 1
    return q
]]></sourcecode>
          <t>Bit <tt>j</tt> of <tt>index</tt> is the side of its pair that the binding value is on
at level <tt>j</tt>, which fixes the direction of that level's key; each key has
its own trapdoor:</t>
          <sourcecode type="python"><![CDATA[
def GenerateVecBind(
    index: int, trapdoors: Sequence[Scalar]
) -> list[Element]:
    commitment_keys = []
    for j in range(len(trapdoors)):
        bind_left = ((index >> j) & 1) == 0
        commitment_keys.append(GenerateStep(bind_left, trapdoors[j]))
    return commitment_keys
]]></sourcecode>
          <t>The first move commits the value at <tt>index</tt> with every other leaf empty,
under one opening per level:</t>
          <sourcecode type="python"><![CDATA[
def CommitValAtPlace(
    commitment_keys: Sequence[Element],
    n: int,
    index: int,
    value: bytes,
    openings: Sequence[Scalar],
) -> bytes:
    V = [b"" for _ in range(n)]
    V[index] = value
    return VecCommit(V, commitment_keys, openings)
]]></sourcecode>
          <t>Once the other leaves are known, each level's opening is shifted so that the
sibling of the binding path takes its new value and the node above is
unchanged. An odd last element on the binding path has no sibling and keeps
its opening.</t>
          <sourcecode type="python"><![CDATA[
def VecEquivocate(
    commitment_keys: Sequence[Element],
    trapdoors: Sequence[Scalar],
    openings: Sequence[Scalar],
    old: Sequence[bytes],
    new: Sequence[bytes],
    index: int,
) -> list[Scalar]:
    if len(old) != len(new):
        raise ValueError("vectors must have the same length")
    if old[index] != new[index]:
        raise ValueError("the binding position cannot change")
    if len(old) == 1:
        return []

    if index == len(old) - 1 and len(old) % 2 == 1:
        opening = openings[0]
    else:
        partner = index - 1 if index % 2 == 1 else index + 1
        opening = EquivocateStep(
            old[partner], new[partner], openings[0], trapdoors[0]
        )

    old_prime = []
    new_prime = []
    for i in range(len(old) // 2):
        Q = commitment_keys[0]
        old_prime.append(
            CommitStep(Q, old[2 * i], old[2 * i + 1], openings[0])
        )
        new_prime.append(
            CommitStep(Q, new[2 * i], new[2 * i + 1], opening)
        )
    if len(old) % 2 == 1:
        old_prime.append(old[-1])
        new_prime.append(new[-1])

    rest = VecEquivocate(
        commitment_keys[1:],
        trapdoors[1:],
        openings[1:],
        old_prime,
        new_prime,
        index // 2,
    )
    return [opening] + rest


def VecEquivocateFromZero(
    commitment_keys: Sequence[Element],
    trapdoors: Sequence[Scalar],
    openings: Sequence[Scalar],
    new: Sequence[bytes],
    index: int,
) -> list[Scalar]:
    V = [b"" for _ in new]
    V[index] = new[index]
    return VecEquivocate(
        commitment_keys, trapdoors, openings, V, new, index
    )
]]></sourcecode>
        </section>
        <section anchor="permutation">
          <name>The Permutation</name>
          <t><tt>P</tt> is a permutation on the elements of <tt>G</tt>, computed on their compressed
encodings by cycle walking: a permutation of the encoding space is applied
until the result decodes to an element, and <tt>Pinv</tt> walks the same cycle
backwards. Since a permutation partitions its domain into cycles, the two
are inverse to each other.</t>
          <t>The following direct implementations define the permutation and its
inverse for the P-256 group. Other ciphersuites <bcp14>MUST</bcp14>
define the permutation to be used. They <bcp14>MAY</bcp14> be used on public points,
including the commitment keys in <tt>CommitStep</tt>. Key generation instead
uses <tt>G.PermutationPair</tt> (<xref target="permutation-pair"/>), which is designed to
be side-channel resistant. In particular, its execution does not
distinguish the two binding directions when its outputs are fixed.</t>
          <sourcecode type="python"><![CDATA[
def P(self, element: Element) -> Element:
    buf = bytearray(self.SerializeElement(element))
    buf[0] = buf[0] - 0x02
    while True:
        buf = PermuteBytes(buf)
        try:
            return self.DeserializeElement(
                bytes([buf[0] + 0x02]) + bytes(buf[1:])
            )
        except DeserializeError:
            continue

def Pinv(self, element: Element) -> Element:
    buf = bytearray(self.SerializeElement(element))
    buf[0] = buf[0] - 0x02
    while True:
        buf = UnpermuteBytes(buf)
        try:
            return self.DeserializeElement(
                bytes([buf[0] + 0x02]) + bytes(buf[1:])
            )
        except DeserializeError:
            continue
]]></sourcecode>
          <t>The permutation of the encoding space is an eight-round Feistel network over
33-byte strings whose first byte is <tt>0x02</tt> or <tt>0x03</tt>, carried as its low
bit. Each iteration of the loop below computes two rounds, one per half:</t>
          <sourcecode type="python"><![CDATA[
def PermuteBytes(buf: bytearray) -> bytearray:
    left, right = bytearray(buf[0:17]), bytearray(buf[17:33])
    for i in range(4):
        label = f"left round {i}".encode()
        left = bytearray(_xor(left, _sha256(right + label)[0:17]))
        left[0] = left[0] & 0x01
        label = f"right round {i}".encode()
        right = bytearray(_xor(right, _sha256(left + label)[0:16]))
    return left + right

def UnpermuteBytes(buf: bytearray) -> bytearray:
    left, right = bytearray(buf[0:17]), bytearray(buf[17:33])
    for i in reversed(range(4)):
        label = f"right round {i}".encode()
        right = bytearray(_xor(right, _sha256(left + label)[0:16]))
        label = f"left round {i}".encode()
        left = bytearray(_xor(left, _sha256(right + label)[0:17]))
        left[0] = left[0] & 0x01
    return left + right
]]></sourcecode>
          <t>The binding argument of <xref target="security-considerations"/> models <tt>P</tt> as a random
permutation. An eight-round balanced Feistel network with independent random
round functions is indifferentiable from a random permutation <xref target="DS15"/>. Here
the round functions are SHA-256 separated by label, over halves of 129 and
128 bits, an imbalance <xref target="DS15"/> does not cover.</t>
          <section anchor="permutation-pair">
            <name>Walking a Permutation Edge</name>
            <t><tt>G.PermutationPair(T, bind_left)</tt> returns <tt>(Q, P(Q))</tt>. If <tt>bind_left</tt> is true,
it walks backwards from <tt>T = P(Q)</tt> to <tt>Q</tt>. Otherwise it walks forwards from
<tt>T = Q</tt> to <tt>P(Q)</tt>. At each iteration it computes both one-step byte
permutations, selects the next encoding using the secret bit, and tests
whether that encoding is valid. It selects the order of the endpoints before
decoding them, so both final decodings operate on the same public values
<tt>Q</tt> and <tt>P(Q)</tt>, in that order.</t>
            <sourcecode type="python"><![CDATA[
def PermutationPair(
    self, element: Element, bind_left: bool
) -> tuple[Element, Element]:
    if not isinstance(bind_left, bool):
        raise ValueError("bind_left must be a boolean")
    start = bytearray(self.SerializeElement(element))
    start[0] -= 0x02
    buf = start
    while True:
        forward = PermuteBytes(buf)
        backward = UnpermuteBytes(buf)
        buf = SelectBytes(forward, backward, bind_left)
        if IsValidPermutationEncoding(buf):
            break

    left = SelectBytes(start, buf, bind_left)
    right = SelectBytes(buf, start, bind_left)
    Q = self.DeserializeElement(
        bytes([left[0] + 0x02]) + bytes(left[1:])
    )
    PQ = self.DeserializeElement(
        bytes([right[0] + 0x02]) + bytes(right[1:])
    )
    return (Q, PQ)


def SelectBytes(
    left: bytearray, right: bytearray, choose_right: bool
) -> bytearray:
    mask = -int(choose_right)
    return bytearray(
        (a & ~mask) | (b & mask)
        for a, b in zip(left, right, strict=True)
    )
]]></sourcecode>
            <t><tt>SelectBytes</tt> takes equal-length inputs and selects <tt>right</tt> if its boolean
argument is true, or <tt>left</tt> otherwise. Implementations <bcp14>MUST</bcp14> perform this
selection without secret-dependent branches or memory accesses.</t>
            <t>For P-256, encoding validity can be tested without attempting a point
decoding or raising exceptions. Here <tt>FIELD_MODULUS</tt>, <tt>CURVE_A</tt>, and
<tt>CURVE_B</tt> are the P-256 field modulus and Weierstrass coefficients from
<xref target="NISTCurves"/>. Since the field modulus is 3 modulo 4, the fixed exponent
below computes a square-root candidate; squaring it tests whether a root
exists. P-256 has prime, odd order, so an affine point with <tt>y = 0</tt> cannot
occur. Each valid <tt>x</tt> therefore supports both sign bits. The identity has
no affine encoding.</t>
            <sourcecode type="python"><![CDATA[
def IsValidPermutationEncoding(buf: bytearray) -> bool:
    if len(buf) != 33:
        return False
    x = int.from_bytes(buf[1:], "big")
    rhs = (
        pow(x, 3, FIELD_MODULUS) + CURVE_A * x + CURVE_B
    ) % FIELD_MODULUS
    y = pow(rhs, (FIELD_MODULUS + 1) // 4, FIELD_MODULUS)
    return (
        ((buf[0] == 0) | (buf[0] == 1))
        & (x < FIELD_MODULUS)
        & (y * y % FIELD_MODULUS == rhs)
    )
]]></sourcecode>
            <t>The validity test <bcp14>MUST</bcp14> execute in constant time for all 33-byte candidates,
including those with an out-of-range coordinate or no square root. Every
condition is evaluated, so neither an exception-based decoder nor
short-circuit evaluation may be used. The byte permutations, selections, initial
serialization of <tt>T</tt>, and computation of <tt>T = secret * B</tt> <bcp14>MUST</bcp14> likewise
have no secret-dependent timing or memory access patterns. The Python
snippets specify the computation and operation schedule; Python integer
arithmetic and the reference implementation's group operations do not
provide these constant-time guarantees.</t>
            <t>To see why the loop may stop at the first valid encoding, fix the public
output <tt>Q</tt>. Let <tt>k</tt> be the number of applications of <tt>PermuteBytes</tt> needed
to reach <tt>P(Q)</tt> from <tt>Q</tt>. None of the <tt>k - 1</tt> intermediate encodings is
valid. Walking backwards from <tt>P(Q)</tt> therefore reaches <tt>Q</tt> after exactly
<tt>k</tt> applications of <tt>UnpermuteBytes</tt>, with the same sequence of validity
results: <tt>k - 1</tt> failures followed by one success. Each orientation executes
one forward permutation, one inverse permutation, one selection, and one
validity test per iteration. Thus the observable operation schedule depends
only on <tt>Q</tt>, which is included in the proof, and can be reproduced from it.
This argument also covers fixed points and does not assume that <tt>P</tt> is
random.</t>
            <t>Implementations <bcp14>MUST NOT</bcp14> optimize away the unused permutation direction.
Calling <tt>Pinv(T)</tt> only for left binding leaks the direction directly.
Computing <tt>Pinv(T)</tt> for both directions and selecting an endpoint afterwards
also leaks: for a fixed public <tt>Q</tt>, its walk length describes the edge
leaving <tt>Q</tt> in one case and the edge entering <tt>Q</tt> in the other. Both one-step
permutations <bcp14>MUST</bcp14> be computed on each iteration of the selected walk.</t>
          </section>
        </section>
        <section anchor="proof-challenge">
          <name>Challenge Computation</name>
          <t><tt>ProofStatement</tt> encodes the statement being proven: the Anchor Set, the
rerandomized key <tt>X_hat</tt>, the signature being presented (encoded by the
endorsement), the issuance and redemption context, and the challenge digest. The
Fiat-Shamir challenge covers it together with the first move of the proof, which
is the commitment keys and the root of the tree.</t>
          <sourcecode type="python"><![CDATA[
def ProofStatement(
    anchor_set: Sequence[Element],
    X_hat: Element,
    endorsement: Endorsement,
    ctx_iss: bytes,
    ctx_red: bytes,
    challenge_digest: bytes,
) -> bytes:
    (c, s_hat, y, t, nf) = endorsement
    n = len(anchor_set)

    anchor_set_enc = b""
    for i in range(n):
        anchor_set_enc += G.SerializeElement(anchor_set[i])

    return (
        I2OSP(n, 2)
        + anchor_set_enc
        + G.SerializeElement(X_hat)
        + G.SerializeScalar(c)
        + G.SerializeScalar(s_hat)
        + G.SerializeScalar(y)
        + G.SerializeScalar(t)
        + U16Prefixed(nf)
        + U16Prefixed(ctx_iss)
        + U16Prefixed(ctx_red)
        + U16Prefixed(challenge_digest)
    )


def ComputeProofChallenge(
    anchor_set: Sequence[Element],
    X_hat: Element,
    endorsement: Endorsement,
    ctx_iss: bytes,
    ctx_red: bytes,
    challenge_digest: bytes,
    commitment_keys: Sequence[Element],
    root: bytes,
) -> Scalar:
    ck_enc = b""
    for j in range(len(commitment_keys)):
        ck_enc += G.SerializeElement(commitment_keys[j])

    proof_transcript = (
        ProofStatement(
            anchor_set,
            X_hat,
            endorsement,
            ctx_iss,
            ctx_red,
            challenge_digest,
        )
        + ck_enc
        + root
        + b"IssuerProof"
    )

    return G.HashToScalar(proof_transcript)
]]></sourcecode>
          <t>The length of the Anchor Set <tt>n</tt> is prefixed and <tt>Element</tt> encodings are
fixed-length, so <tt>anchor_set_enc</tt> and <tt>ck_enc</tt> are unambiguous without length
prefixes of their own; the number of commitment keys, <tt>q = Depth(n)</tt>, is
determined by <tt>n</tt>. The label <tt>"IssuerProof"</tt> separates this transcript from the
issuance transcript of <xref target="challenge"/>, which is hashed with the same function.</t>
        </section>
        <section anchor="prove-issuer">
          <name>Proving</name>
          <sourcecode type="python"><![CDATA[
def ProveIssuer(
    anchor_set: Sequence[Element],
    index: int,
    delta: Scalar,
    X_hat: Element,
    endorsement: Endorsement,
    ctx_iss: bytes,
    ctx_red: bytes,
    challenge_digest: bytes,
    rand: bytes,
) -> tuple[Scalar, Scalar, Sequence[Element], Sequence[Scalar]]:
    Y = Statements(anchor_set, X_hat)
    q = Depth(len(anchor_set))
    if not 0 <= index < len(anchor_set):
        raise ValueError("index is outside the Anchor Set")
    if len(rand) != Nseed:
        raise ValueError("invalid issuer proof randomness length")

    instance = ProofStatement(
        anchor_set,
        X_hat,
        endorsement,
        ctx_iss,
        ctx_red,
        challenge_digest,
    )
    derived = G.DeriveNonces(
        G.SerializeScalar(delta) + I2OSP(index, 2),
        b"ProveIssuer",
        instance,
        rand,
        2 * q + 1,
    )
    r = derived[0]
    trapdoors = derived[1 : q + 1]
    first_openings = derived[q + 1 :]
    T = r * B

    commitment_keys = GenerateVecBind(index, trapdoors)
    # First move: commit along the binding path; other leaves empty.
    root = CommitValAtPlace(
        commitment_keys,
        len(Y),
        index,
        G.SerializeElement(T),
        first_openings,
    )

    proof_challenge = ComputeProofChallenge(
        anchor_set,
        X_hat,
        endorsement,
        ctx_iss,
        ctx_red,
        challenge_digest,
        commitment_keys,
        root,
    )

    response = r - proof_challenge * delta

    V = []
    for i in range(len(Y)):
        commitment = BranchCommitment(proof_challenge, response, Y[i])
        V.append(G.SerializeElement(commitment))
    openings = VecEquivocateFromZero(
        commitment_keys, trapdoors, first_openings, V, index
    )

    return (proof_challenge, response, commitment_keys, openings)
]]></sourcecode>
          <t><tt>ProveIssuer</tt> derives the nonce <tt>r</tt>, the trapdoors of the <tt>q</tt> commitment
keys, and the <tt>q</tt> openings of its first move with one call to
<tt>G.DeriveNonces</tt> (<xref target="derive-nonce"/>), with <tt>delta</tt> and <tt>index</tt> as the secret
and the proof statement as the instance.</t>
          <t>The first move commits only the path from leaf <tt>index</tt> to the root: at each
level the Client commits the value it holds on one side and an empty value
on the other, having generated that level's key so that the other side is
the equivocal one. The third move then computes the branch commitment of
every statement from the single response, equivocates each level to the
value its sibling subtree now has, and rebuilds the tree with the
equivocated openings. The root is unchanged, so the Moderator recomputes the
same root.</t>
        </section>
        <section anchor="verify-issuer">
          <name>Verifying</name>
          <sourcecode type="python"><![CDATA[
def VerifyIssuer(
    anchor_set: Sequence[Element],
    X_hat: Element,
    endorsement: Endorsement,
    ctx_iss: bytes,
    ctx_red: bytes,
    challenge_digest: bytes,
    proof_challenge: Scalar,
    response: Scalar,
    commitment_keys: Sequence[Element],
    openings: Sequence[Scalar],
) -> bool:
    n = len(anchor_set)
    if n == 0:
        return False

    Y = Statements(anchor_set, X_hat)
    q = Depth(n)
    if len(commitment_keys) != q:
        return False
    if len(openings) != q:
        return False

    V = []
    for i in range(n):
        commitment = BranchCommitment(proof_challenge, response, Y[i])
        if commitment.isIdentity():
            return False
        V.append(G.SerializeElement(commitment))

    root = VecCommit(V, commitment_keys, openings)

    return proof_challenge == ComputeProofChallenge(
        anchor_set,
        X_hat,
        endorsement,
        ctx_iss,
        ctx_red,
        challenge_digest,
        commitment_keys,
        root,
    )
]]></sourcecode>
          <t>The Moderator computes a commitment for every branch from the single response,
rebuilds the whole tree from those commitments and the openings it was given,
and checks that the root it arrives at is the one the challenge was computed
over. Neither the branch commitments nor the interior nodes are transmitted.</t>
          <t><tt>VerifyIssuer</tt> returns <tt>false</tt> rather than raising an error, as <tt>Verify</tt>
(<xref target="verify"/>) does. Its checks on the lengths of <tt>commitment_keys</tt> and
<tt>openings</tt> repeat what deserialization enforces (<xref target="redemption-wire"/>), and an
empty Anchor Set means the Moderator is misconfigured. It also
rejects a branch commitment equal to the identity element, which
<tt>SerializeElement</tt> cannot encode and which a Client can produce on its own
branch by answering <tt>response = -proof_challenge * delta</tt>. An interior node
is the identity only for a Client that knows a discrete logarithm relation
among <tt>B</tt>, <tt>Q</tt>, and <tt>P(Q)</tt> for the key <tt>Q</tt> of its level, which the binding
property of <xref target="pbvc"/> rules out, so <tt>VecCommit</tt> does not check for it.</t>
          <t>A proof produced by <tt>ProveIssuer</tt> is accepted by <tt>VerifyIssuer</tt>. On branch
<tt>index</tt>,</t>
          <artwork><![CDATA[
  proof_challenge * Y[index] + response * B
    = proof_challenge * delta * B
      + (r - proof_challenge * delta) * B
    = r * B
]]></artwork>
          <t>This is the commitment the Client committed at the binding leaf, and every
other leaf holds by definition the commitment the verifier recomputes. Each
level then reproduces the node the Client committed: the binding side is
unchanged, and the equivocal side was shifted to match.</t>
          <t>Conversely, the binding leaf is fixed before <tt>proof_challenge</tt> exists and
cannot be moved afterwards, so a Client that could produce an accepting proof
for two different challenges would yield <tt>delta</tt> for that leaf's statement. The
soundness of the proof rests on that alone; see <xref target="security-considerations"/>.</t>
        </section>
      </section>
      <section anchor="redeem">
        <name>Redemption</name>
        <t>The Client produces a redemption from an Endorsement it holds.</t>
        <sourcecode type="python"><![CDATA[
def Redeem(
    anchor_set: Sequence[Element],
    index: int,
    endorsement: Endorsement,
    ctx_iss: bytes,
    ctx_red: bytes,
    challenge_digest: bytes,
) -> Redemption:
    (c, s, y, t, nf) = endorsement
    n = len(anchor_set)

    if not 0 <= index < n:
        raise ValueError("index is outside the Anchor Set")

    rand = random(2 * Nseed)
    (delta,) = G.DeriveScalars(Seed(rand, 0), b"delta", 1)

    X_hat = anchor_set[index] + delta * B
    s_hat = s + (c * y) * delta
    shown = Endorsement(c, s_hat, y, t, nf)

    (proof_challenge, response, commitment_keys, openings) = ProveIssuer(
        anchor_set,
        index,
        delta,
        X_hat,
        shown,
        ctx_iss,
        ctx_red,
        challenge_digest,
        Seed(rand, 1),
    )

    return Redemption(
        X_hat,
        shown,
        proof_challenge,
        response,
        commitment_keys,
        openings,
    )
]]></sourcecode>
      </section>
      <section anchor="verify-redemption">
        <name>Redemption Verification</name>
        <t>The Moderator checks the signature under the rerandomized key and the proof
against its Anchor Set.</t>
        <sourcecode type="python"><![CDATA[
def VerifyRedemption(
    anchor_set: Sequence[Element],
    redemption: Redemption,
    ctx_iss: bytes,
    ctx_red: bytes,
    challenge_digest: bytes,
) -> bytes:
    (
        X_hat,
        shown,
        proof_challenge,
        response,
        commitment_keys,
        openings,
    ) = redemption

    if not Verify(X_hat, shown, ctx_iss, ctx_red):
        raise VerifyError

    if not VerifyIssuer(
        anchor_set,
        X_hat,
        shown,
        ctx_iss,
        ctx_red,
        challenge_digest,
        proof_challenge,
        response,
        commitment_keys,
        openings,
    ):
        raise VerifyError

    return shown.nf
]]></sourcecode>
        <t>The first check is the endorsement verification of <xref target="verify"/>, run against the
rerandomized key. Together the two checks establish that the Client holds an
Endorsement issued under <tt>ctx_iss</tt> and <tt>ctx_red</tt> by one of the Anchors in
<tt>anchor_set</tt>, and reveal nothing further about which one. On success,
<tt>VerifyRedemption</tt> returns the nullifier; either failed check raises a
<tt>VerifyError</tt>.</t>
        <t><tt>VerifyRedemption</tt> does not enforce single use. The nullifier <tt>nf</tt> is in the
clear in the redemption, and a Moderator that accepts a redemption <bcp14>MUST</bcp14> reject
it if it has already recorded that <tt>nf</tt>, and <bcp14>MUST</bcp14> record <tt>nf</tt> before granting
anything on the strength of it. A Moderator <bcp14>SHOULD</bcp14> scope its nullifier store to
the issuance context, since an Endorsement issued under a different <tt>ctx_iss</tt>
does not verify anyway.</t>
        <t>An Anchor Set of one key gives a tree of depth zero: the redemption carries
no commitment keys or openings, and the issuer-hiding proof is a proof of
knowledge of <tt>delta</tt> for that key. The redemption then names its Anchor, as
the Anchor Set itself does; see <xref target="security-considerations"/>.</t>
      </section>
      <section anchor="redemption-wire">
        <name>Encodings</name>
        <t>A Client sends the encoded <tt>Redemption</tt> to the Moderator in the Redeem &amp; Issue
flow (<xref target="ARCH"/>).</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  Element rerandomized_key;
  Endorsement shown_endorsement;
  Scalar proof_challenge;
  Scalar response;
  Element commitment_keys<V>;
  Scalar openings<V>;
} Redemption;
]]></sourcecode>
        <t><tt>shown_endorsement</tt> uses the <tt>Endorsement</tt> structure of
<xref target="endorsement-encoding"/>, with <tt>s</tt> carrying <tt>s_hat</tt>, but is rerandomized such
that it verifies under <tt>rerandomized_key</tt> (<xref target="rerandomization"/>), not the
Endorsement the Client stored, which the Client <bcp14>MUST NOT</bcp14> send.</t>
        <t>A Moderator deserializes a <tt>Redemption</tt> against its Anchor Set of <tt>n</tt> keys, as
in <xref target="wire"/>. It <bcp14>MUST</bcp14> raise a <tt>DeserializeError</tt> unless <tt>commitment_keys</tt> is
<tt>Depth(n) * Ne</tt> bytes long and <tt>openings</tt> is <tt>Depth(n) * Ns</tt> bytes long
(<xref target="pbvc"/>).</t>
      </section>
    </section>
    <section anchor="ciphersuites">
      <name>Ciphersuites</name>
      <t>A ciphersuite fixes the group, the hash function, the associated encodings,
and a ciphersuite identifier. Both parties are assumed to agree on the
ciphersuite in use (<xref target="config"/>).</t>
      <t>For each ciphersuite, <tt>ctx_proto</tt> is as computed in <xref target="config"/>. The nullifier
length is <tt>Nn = 32</tt> bytes and the seed length, that of the random input to
every derivation, is <tt>Nseed = 48</tt> bytes for the ciphersuite below.</t>
      <section anchor="ec-ihatp-256-sha-256">
        <name>EC-IHAT(P-256, SHA-256)</name>
        <t>This ciphersuite uses P-256 (secp256r1) <xref target="NISTCurves"/> for the group and
SHA-256 for the hash function, with <tt>Nh = 32</tt> and <tt>s_in_bytes = 64</tt>. The
value of the ciphersuite identifier is <tt>"P256-SHA256"</tt>.</t>
        <t>The interface of <xref target="group"/> is instantiated as follows.</t>
        <dl>
          <dt>Order():</dt>
          <dd>
            <t>Return 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551.</t>
          </dd>
          <dt>Identity(), Generator(), ScalarMultGen(r):</dt>
          <dd>
            <t>As defined in <xref target="NISTCurves"/>.</t>
          </dd>
          <dt>HashToGroup(x, DST):</dt>
          <dd>
            <t>Use <tt>hash_to_curve</tt> with suite <tt>P256_XMD:SHA-256_SSWU_RO_</tt> <xref target="HASH2CURVE"/> and
input <tt>x</tt>, using the given <tt>DST</tt>.</t>
          </dd>
          <dt>HashToScalar(x, DST):</dt>
          <dd>
            <t>Use <tt>hash_to_field</tt> from <xref target="HASH2CURVE"/> with <tt>count = 1</tt>, <tt>m = 1</tt>,
<tt>L = 48</tt>, <tt>expand_message_xmd</tt> with SHA-256, input <tt>x</tt>, a prime modulus equal
to <tt>Order()</tt>, and the given <tt>DST</tt>. Return the single resulting field element
as a <tt>Scalar</tt>.</t>
          </dd>
          <dt>ScalarInverse(s):</dt>
          <dd>
            <t>The multiplicative inverse of <tt>s</tt> modulo <tt>Order()</tt>.</t>
          </dd>
          <dt>SerializeElement(A):</dt>
          <dd>
            <t>The compressed Elliptic-Curve-Point-to-Octet-String method of <xref target="SEC1"/>;
<tt>Ne = 33</tt>.</t>
          </dd>
          <dt>DeserializeElement(buf):</dt>
          <dd>
            <t>Deserialize a 33-byte input using the compressed
Octet-String-to-Elliptic-Curve-Point method of <xref target="SEC1"/>, then perform partial
public key validation as in <xref section="4.3" sectionFormat="of" target="OPRF"/>. This includes checking
that the coordinates are in range, that the point is on the curve, and that
the point is not the identity element. Raise a <tt>DeserializeError</tt> if any
check fails.</t>
          </dd>
          <dt>SerializeScalar(s):</dt>
          <dd>
            <t>The Field-Element-to-Octet-String conversion of <xref target="SEC1"/>; <tt>Ns = 32</tt>.</t>
          </dd>
          <dt>DeserializeScalar(buf):</dt>
          <dd>
            <t>Deserialize a 32-byte input using Octet-String-to-Field-Element from
<xref target="SEC1"/>. Raise a <tt>DeserializeError</tt> if the result is not in
<tt>[0, Order()-1]</tt>.</t>
          </dd>
          <dt>P:</dt>
          <dd>
            <t>The SHA-256 Feistel permutation and cycle walk in <xref target="permutation"/>.
Compressed SEC1 prefixes are <tt>0x02</tt> and <tt>0x03</tt>; subtracting <tt>0x02</tt> gives
the one-bit prefix used by the byte permutation. <tt>Pinv</tt> reverses the
walk. <tt>PermutationPair</tt> (<xref target="permutation-pair"/>) is used during commitment
key generation. For a random encoding permutation, the walk takes about
two iterations on average.</t>
          </dd>
        </dl>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>The security of EC-IHAT is studied in <xref target="FFKLLS26"/>. The underlying blind
signature is that of Tessaro and Zhu <xref target="TESSZHU"/>, instantiated with the public
input set to the issuance context. Security is analysed in the random oracle
model, and one-more unforgeability additionally in the algebraic group model
under the discrete logarithm assumption.</t>
      <dl>
        <dt>Blindness:</dt>
        <dd>
          <t>All the Anchor receives in a session is the blinded challenge <tt>c * gamma2</tt>.
With uniform blinding factors, the blinded challenge is uniformly
distributed and independent of the message and of the resulting signature,
and the underlying scheme is perfectly blind <xref target="FFKLLS26"/>. The blinding factors
of this document are derived by hashing, so in the random oracle model the
scheme is statistically blind: an Anchor can link an Endorsement to the
session that produced it only by evaluating the hash function on one of the
secret inputs from which the Client derives its blinding factors
(<xref target="derive-scalar"/>). Endorsement grants and redemptions are therefore
unlinkable, as <xref target="ARCH"/> requires.</t>
        </dd>
        <dt>One-more unforgeability:</dt>
        <dd>
          <t>A Client that completes <tt>k</tt> issuance sessions under a given issuance context
cannot produce <tt>k+1</tt> distinct valid Endorsements under that context,
regardless of how many sessions it has completed under other issuance
contexts <xref target="TESSZHU"/>. This is what allows a Moderator to conclude that an
accepted Endorsement corresponds to exactly one grant by a trusted Anchor.
This security guarantee holds even with concurrent sessions.</t>
        </dd>
        <dt>Unforgeability under rerandomization:</dt>
        <dd>
          <t>Lemma 1 of <xref target="FFKLLS26"/> establishes strong key randomizability of <xref target="TESSZHU"/>.
Thus, Theorem 1 of <xref target="FFKLLS26"/> reduces issuer-hiding one-more unforgeability
to <xref target="TESSZHU"/>, provided the issuer-hiding proof is straight-line extractable.
</t>
          <t>Appendix C of <xref target="FFKLLS26"/> claims straight-line extractability for
<xref target="SIGMA"/>, but does not establish it for the stacked proof used here.
Applying Theorem 1 to this construction therefore remains an open
proof obligation.</t>
        </dd>
        <dt>Issuer hiding:</dt>
        <dd>
          <t>Theorem 2 of <xref target="FFKLLS26"/> establishes issuer-hiding blindness from perfect
blindness of issuance, strong key randomizability (as defined by <xref target="FFKLLS26"/>), and perfect zero knowledge
of the issuer-hiding proof, assuming uniform randomness. Up to a negligible
statistical distance, a redemption reveals nothing
about which Anchor in <tt>anchor_set</tt> issued the Endorsement, so a Moderator, an
Anchor, and the two colluding learn only that some key in <tt>anchor_set</tt> was
used. <tt>X_hat</tt> and the <tt>response</tt> of the single branch proof are
statistically close to uniform independently of the branch (<xref target="branch"/>),
and the commitment of <xref target="pbvc"/> hides which position it binds: a commitment
key is distributed independently of that position, and an opening
independently of whether the value it opens to was committed or
equivocated. The stacked composition is therefore witness indistinguishable
(appendix and Section 7 of <xref target="STACKSIG"/>).</t>
        </dd>
        <dt>Partially binding commitments:</dt>
        <dd>
          <t>The soundness of the issuer-hiding proof rests on two things: the
commitment of <xref target="pbvc"/> binding one position of each node, and the
collision resistance of <tt>HashToScalar</tt> on the leaf and node encodings,
without which a position could be opened to a colliding value and no
discrete logarithm would be extractable. Binding is computational. A
Client that opens the value under base <tt>Q</tt> two ways knows the discrete
logarithm of <tt>Q</tt>, and one that opens the value under <tt>P(Q)</tt> two ways knows
that of <tt>P(Q)</tt>; the key generation gives it one of the two. Opening both
positions would require both logarithms. That a <tt>Q</tt> with both known is as
hard to find as a discrete logarithm when <tt>P</tt> is modelled as a random
permutation (<xref target="permutation"/>) is the assumption under which the pair
commitment of the appendix of <xref target="STACKSIG"/> binds.</t>
        </dd>
        <dt>Constant-time proving:</dt>
        <dd>
          <t><tt>ProveIssuer</tt> treats one leaf, and one side of each node on the path to it,
differently from the others, and that leaf is the secret the proof hides.
Implementations <bcp14>MUST NOT</bcp14> allow the binding path to be distinguished by
timing or memory access patterns.
The first
move places the real branch commitment at <tt>index</tt> and empty values at every
other leaf; both commitment passes visit every node of the tree. That
placement and the later equivocation <bcp14>MUST</bcp14> avoid observable secret-dependent
branches and memory accesses. The number of distinct node commitments at a
level of the first move depends on <tt>index</tt>, so an implementation that
computes each only once <bcp14>MUST</bcp14> compute the same number at every level for
every <tt>index</tt>.</t>
        </dd>
        <dt/>
        <dd>
          <t>Commitment key generation uses the balanced walk of <xref target="permutation-pair"/>.
Its iteration count is determined by the published commitment key, and
both binding directions execute the same operation schedule for that key.
This addresses the permutation walk only: secret-index selection,
scalar arithmetic, and the rest of the proving algorithm still require
constant-time implementations.</t>
        </dd>
        <dt>Single-use sessions:</dt>
        <dd>
          <t>Implementations <bcp14>MUST</bcp14> ensure that the session state produced by <tt>Commit</tt> is
never used more than once. If an Anchor answers two distinct challenges
<tt>c1 != c2</tt> on one <tt>Commit</tt> state, then from the two responses
<tt>s1 = a + c1*y*skA</tt> and <tt>s2 = a + c2*y*skA</tt>, with <tt>y</tt> revealed in both,
anyone recovers the signing key as
<tt>skA = (s1 - s2) * ScalarInverse((c1 - c2) * y)</tt>. The requirement extends to
process restarts, to replicas sharing a signing key, and to any retry or
replay of a <tt>ChallengeMessage</tt>: an Anchor <bcp14>MUST</bcp14> treat a session as closed the
moment it emits a response, and <bcp14>MUST NOT</bcp14> recompute a response for a
repeated challenge on that session. Anchors are stateful for this reason.</t>
        </dd>
        <dt>Context binding:</dt>
        <dd>
          <t>The issuance context enters both the commitment base and the challenge
transcript, and the redemption context enters the signed message, so an
Endorsement does not verify under any other pair of contexts. Neither context
is carried in the Endorsement; both are supplied by the verifier
(<xref target="verify"/>), so a Client cannot assert the pair its Endorsement is checked
against. A Client also cannot select the issuance context unilaterally: it is
never sent from the Client to the Anchor, and using a value other than the one
the Anchor committed under fails the opening check in <tt>Finalize</tt>.</t>
        </dd>
        <dt>Aborts on zero:</dt>
        <dd>
          <t><tt>Challenge</tt> aborts when the challenge hashes to zero and <tt>Respond</tt> aborts on
a zero challenge. Both events occur with probability approximately <tt>1/p</tt> for
honest parties, where <tt>p</tt> is the order of the group. A Client that observes
such an abort learns nothing and <bcp14>SHOULD</bcp14> start a fresh session.</t>
        </dd>
        <dt>Context granularity:</dt>
        <dd>
          <t>The unlinkability arguments above are cryptographic; the anonymity set they
operate over is set by the contexts. Both contexts are visible at redemption,
the issuance context directly and the redemption context through the fact
that the Endorsement verifies under it, so each partitions Clients into the
set that shares its value.
A deployment
that refines either value, for instance by using a per-request timestamp
rather than a shared epoch, or a per-Client identifier rather than a value
shared by every Client redeeming in the same place, reduces the anonymity set
accordingly, down to a single Client, without violating any cryptographic
property of the construction.</t>
        </dd>
        <dt>Session identifiers:</dt>
        <dd>
          <t>Any identifier the transport uses to correlate the messages of <xref target="wire"/>,
such as a per-batch session identifier, is chosen by the Anchor and so is a value the Anchor recognises. It <bcp14>MUST</bcp14> be
confined to the transport: it is not an input to any algorithm of
<xref target="issuance"/>, nor is it included in the challenge transcript. Were it bound
into the Endorsement, the Anchor could recognise its own identifier at
redemption and link the redemption to the issuance session.</t>
        </dd>
        <dt>Anonymity sets:</dt>
        <dd>
          <t>The effective privacy a Client obtains also depends on deployment properties
beyond this document, in particular the number of Clients an Anchor serves per
epoch and the size of a Moderator's Anchor Set; see <xref target="ARCH"/>.</t>
        </dd>
      </dl>
    </section>
    <section anchor="iana">
      <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="ARCH">
          <front>
            <title>Moderation of unLinkable Endorsements (MOLE) Architecture</title>
            <author fullname="Samuel Schlesinger" initials="S." surname="Schlesinger">
              <organization>Google LLC</organization>
            </author>
            <author fullname="Dennis Jackson" initials="D." surname="Jackson">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Thibault Meunier" initials="T." surname="Meunier">
              <organization>Cloudflare</organization>
            </author>
            <date day="2" month="November" year="2026"/>
            <abstract>
              <t>   Moderation of unLinkable Endorsements (MOLE) is an architecture that
   lets a party performing access control (a Moderator) bootstrap trust
   in a client from a third party (an Anchor) that already has a trust
   relationship with that client, and then adjust that trust over time
   in response to the client's behaviour, for example by dynamically
   rate-limiting access.

   MOLE targets open deployments, in which independent parties may be
   responsible for access control and for vouching for clients, whilst
   maintaining strong privacy protections for clients.  These
   protections are designed to hold even if participants in the
   ecosystem collude or otherwise misbehave.

   This document specifies the roles, the information flows between
   them, the privacy and security requirements, and deployment
   considerations.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-jms-mole-architecture-01"/>
        </reference>
        <reference anchor="HASH2CURVE">
          <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="I2OSP">
          <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="OPRF">
          <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>
        <reference anchor="QUIC">
          <front>
            <title>QUIC: A UDP-Based Multiplexed and Secure Transport</title>
            <author fullname="J. Iyengar" initials="J." role="editor" surname="Iyengar"/>
            <author fullname="M. Thomson" initials="M." role="editor" surname="Thomson"/>
            <date month="May" year="2021"/>
            <abstract>
              <t>This document defines the core of the QUIC transport protocol. QUIC provides applications with flow-controlled streams for structured communication, low-latency connection establishment, and network path migration. QUIC includes security measures that ensure confidentiality, integrity, and availability in a range of deployment circumstances. Accompanying documents describe the integration of TLS for key negotiation, loss detection, and an exemplary congestion control algorithm.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9000"/>
          <seriesInfo name="DOI" value="10.17487/RFC9000"/>
        </reference>
        <reference anchor="TLS13">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="NISTCurves" target="https://doi.org/10.6028/NIST.FIPS.186-5">
          <front>
            <title>Digital Signature Standard (DSS)</title>
            <author>
              <organization>National Institute of Standards and Technology (NIST)</organization>
            </author>
            <date year="2023" month="February"/>
          </front>
          <seriesInfo name="FIPS PUB" value="186-5"/>
        </reference>
        <reference anchor="SEC1" target="https://www.secg.org/sec1-v2.pdf">
          <front>
            <title>SEC 1: Elliptic Curve Cryptography</title>
            <author>
              <organization>Standards for Efficient Cryptography Group (SECG)</organization>
            </author>
            <date year="2009"/>
          </front>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="SIGMA">
          <front>
            <title>Sigma Proofs for Linear Relations</title>
            <author fullname="Michele Orrù" initials="M." surname="Orrù">
              <organization>CNRS</organization>
            </author>
            <author fullname="Cathie Yun" initials="C." surname="Yun">
              <organization>Apple, Inc.</organization>
            </author>
            <date day="16" month="August" year="2026"/>
            <abstract>
              <t>   This document describes Sigma Protocols for proving knowledge of
   preimages of linear maps in prime-order elliptic curve groups.  These
   are sometimes also called _Maurer Proofs_, or _proofs of knowledge of
   a preimage of a group homomorphism_.

   Examples include zero-knowledge proofs for discrete logarithm
   relations, ElGamal encryptions, Pedersen commitments, and range
   proofs.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-sigma-protocols-03"/>
        </reference>
        <reference anchor="DETSIGS">
          <front>
            <title>Hedged ECDSA and EdDSA Signatures</title>
            <author fullname="John Preuß Mattsson" initials="J. P." surname="Mattsson">
              <organization>Ericsson</organization>
            </author>
            <author fullname="Erik Thormarker" initials="E." surname="Thormarker">
              <organization>Ericsson</organization>
            </author>
            <author fullname="Sini Ruohomaa" initials="S." surname="Ruohomaa">
              <organization>Ericsson</organization>
            </author>
            <date day="3" month="March" year="2025"/>
            <abstract>
              <t>   Deterministic elliptic-curve signatures such as deterministic ECDSA
   and EdDSA have gained popularity over randomized ECDSA as their
   security does not depend on a source of high-quality randomness.
   Recent research, however, has found that implementations of these
   signature algorithms may be vulnerable to certain side-channel and
   fault injection attacks due to their deterministic nature.  One
   countermeasure to such attacks is hedged signatures where the
   calculation of the per-message secret number includes both fresh
   randomness and the message.  This document updates RFC 6979 and RFC
   8032 to recommend hedged constructions in deployments where side-
   channel attacks and fault injection attacks are a concern.  The
   updates are invisible to the validator of the signature and
   compatible with existing ECDSA and EdDSA validators.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-det-sigs-with-noise-05"/>
        </reference>
        <reference anchor="CDS94" target="https://doi.org/10.1007/3-540-48658-5_19">
          <front>
            <title>Proofs of Partial Knowledge and Simplified Design of Witness Hiding Protocols</title>
            <author initials="R." surname="Cramer" fullname="Ronald Cramer">
              <organization/>
            </author>
            <author initials="I." surname="Damgard" fullname="Ivan Damgard">
              <organization/>
            </author>
            <author initials="B." surname="Schoenmakers" fullname="Berry Schoenmakers">
              <organization/>
            </author>
            <date year="1994"/>
          </front>
          <seriesInfo name="CRYPTO" value="1994"/>
        </reference>
        <reference anchor="DS15" target="https://eprint.iacr.org/2015/1069">
          <front>
            <title>Indifferentiability of 8-Round Feistel Networks</title>
            <author initials="Y." surname="Dai" fullname="Yuanxi Dai">
              <organization/>
            </author>
            <author initials="J." surname="Steinberger" fullname="John Steinberger">
              <organization/>
            </author>
            <date year="2015"/>
          </front>
        </reference>
        <reference anchor="FFKLLS26" target="https://eprint.iacr.org/2026/870">
          <front>
            <title>Issuer-Hiding Anonymous Tokens and Credentials from Key-Randomizable Signatures</title>
            <author initials="A." surname="Flamini" fullname="Andrea Flamini">
              <organization/>
            </author>
            <author initials="K." surname="Friedrichs" fullname="Karla Friedrichs">
              <organization/>
            </author>
            <author initials="J." surname="Katz" fullname="Jonathan Katz">
              <organization/>
            </author>
            <author initials="W." surname="Ladd" fullname="Watson Ladd">
              <organization/>
            </author>
            <author initials="A." surname="Lehmann" fullname="Anja Lehmann">
              <organization/>
            </author>
            <author initials="M." surname="Sefranek" fullname="Marek Sefranek">
              <organization/>
            </author>
            <date year="2026" month="October" day="05"/>
          </front>
        </reference>
        <reference anchor="STACKSIG" target="https://eprint.iacr.org/2021/422">
          <front>
            <title>Stacking Sigmas: A Framework to Compose Sigma-Protocols for Disjunctions</title>
            <author initials="A." surname="Goel" fullname="Aarushi Goel">
              <organization/>
            </author>
            <author initials="M." surname="Green" fullname="Matthew Green">
              <organization/>
            </author>
            <author initials="M." surname="Hall-Andersen" fullname="Mathias Hall-Andersen">
              <organization/>
            </author>
            <author initials="G." surname="Kaptchuk" fullname="Gabriel Kaptchuk">
              <organization/>
            </author>
            <date year="2022"/>
          </front>
          <seriesInfo name="EUROCRYPT" value="2022"/>
        </reference>
        <reference anchor="TESSZHU" target="https://eprint.iacr.org/2022/047">
          <front>
            <title>Short Pairing-Free Blind Signatures with Exponential Security</title>
            <author initials="S." surname="Tessaro" fullname="Stefano Tessaro">
              <organization/>
            </author>
            <author initials="C." surname="Zhu" fullname="Chenzhi Zhu">
              <organization/>
            </author>
            <date year="2022"/>
          </front>
          <seriesInfo name="EUROCRYPT" value="2022"/>
        </reference>
      </references>
    </references>
    <?line 2143?>

<section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>The vectors below cover the ciphersuite of <xref target="ciphersuites"/>: <tt>G.DeriveScalars</tt>,
the permutation <tt>P</tt>, a key pair, one issuance, and redemptions of the
resulting Endorsement against Anchor Sets of two keys, of five, and of
one. Byte strings are in hexadecimal, wrapped at 64 digits with the
continuation lines indented; integers are decimal.</t>
      <t>Every algorithm is a deterministic function of the bytes it draws from
<tt>random</tt>. <tt>derive.rand</tt> is the <tt>rand</tt> argument of <tt>G.DeriveScalars</tt>; every
other <tt>rand</tt> entry is the concatenation of every <tt>random</tt> call the algorithm
makes, in the order made, and an implementation replays it by serving those
bytes in place of <tt>random</tt>.</t>
      <t>For <tt>G.GenerateKeyPair</tt> the <tt>rand</tt> entry is the key seed; for <tt>Commit</tt>, the
<tt>Nseed</tt> bytes of <tt>(a, t, y)</tt>; for <tt>Challenge</tt>, the <tt>Nn</tt> bytes of the
nullifier and then the <tt>Nseed</tt> bytes of the blinding factors; and for
<tt>Redeem</tt>, the <tt>Nseed</tt> bytes of <tt>delta</tt> and then the <tt>Nseed</tt> bytes of the
issuer-hiding proof. The <tt>commit.state</tt> entry is the
<tt>AnchorState</tt> <tt>(a, y, t)</tt> as
<tt>SerializeScalar(a) + SerializeScalar(y) + SerializeScalar(t)</tt>, and the
<tt>challenge.state</tt> entry is <tt>nf + SerializeScalar(r1) + SerializeScalar(r2)</tt>
followed by <tt>SerializeScalar(gamma1) + SerializeScalar(gamma2) +
SerializeScalar(c)</tt>. <tt>issue.Z</tt> is <tt>CreateContextBase(ctx_iss)</tt>, and
<tt>key.P_pkA</tt> is <tt>P(pkA)</tt>. Every message and <tt>endorsement</tt> entry is an encoding
of <xref target="wire"/> or <xref target="redemption-wire"/>. The keys of each Anchor Set other than
<tt>key.pkA</tt> were generated for the vectors. Every redemption presents the same
Endorsement, which a Moderator would accept only once; each <tt>nf</tt> entry is the
output of <tt>VerifyRedemption</tt>.</t>
      <section anchor="ec-ihat-tv-suite">
        <name>Ciphersuite</name>
        <artwork><![CDATA[
suite.identifier = 503235362d534841323536
]]></artwork>
      </section>
      <section anchor="ec-ihat-tv-derive">
        <name>Scalar Derivation</name>
        <artwork><![CDATA[
derive.info = 45432d49484154207465737420766563746f7273
derive.rand =
    35caeadd114fe2b6e3de7d4f2218945d5c4a330e9563376f8ac44bc14775ba75
    54be242ad0e048032ff55604907693e7
derive.scalars =
    f3504696233573f8189111eb5fca015633f3ec155005d6159d367b9abd05e001
    8374a7a63cd6f59088b984ece9621d9eb279ec3b166a1dca0a4ade2703bfdb10
    6fe6ded8c73bfb6ada8a5476c6775b3f01bd498fe7dff0b4968e2bed7148d89e
]]></artwork>
      </section>
      <section anchor="ec-ihat-tv-key">
        <name>Key Pair</name>
        <artwork><![CDATA[
key.rand =
    fff81520add7b90fb45470d601bc701577c23a136e47bf17f25f509b28a41149
    a8e96cb8e1bb68fbcf8367a690a430ba
key.skA =
    f9e911e97a24cf3fd425ea7d11845ff75b3dad0ab58997b54e3448a2aaf60979
key.pkA =
    024d804bd96c34e6b1708374c9da148db973cc69e4920f9f6d32d3cdeec53758
    3f
key.P_pkA =
    0275d05750b95cb2dc26b3a961ce6eb7e90b19f31388dfdb5654bc504541b1d8
    b7
]]></artwork>
      </section>
      <section anchor="ec-ihat-tv-issue">
        <name>Issuance</name>
        <artwork><![CDATA[
issue.ctx_iss =
    45432d49484154207465737420766563746f72732069737375616e636520636f
    6e74657874
issue.ctx_red =
    45432d49484154207465737420766563746f727320726564656d7074696f6e20
    636f6e74657874
issue.Z =
    02f9a6afb059d15adcaec09ed5b5986bdbff2d2f48102a8e0d5340f32b135534
    5a
issue.commit.rand =
    0ba14197ea1f9b5f586cf5c3041288e81e9dc08fdefaf1c2aec55a90b7a2119b
    fe112f9c69b25a25ba8778044c8b8193
issue.commit.state =
    7c06761dde72d25f6271330c2a215ac13158ac77e47080592f5e34a5d143bb4b
    129b59d6269a5f982b314865ca56fc7ecf907529ff1c2c0944e23b7e915d92fe
    c34d0a3f8cd5d3e20875b244e1530bba5dbec428af00027d22039f7dda8db087
issue.commit.message =
    033f90a0d4b5e1ea3f6c18976a84012bfbcbd8507f77c064ab7bd9fb60ab7f49
    c803c38d94c9d4ff61f0e27f63099cfd7a0894f8829837b94fd7706e738f57e5
    2bf4
issue.challenge.rand =
    1e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915ed9
    157dcf74f191746f856077f6eb58b77d46d82e07ffd44f96d5942622a779df2b
    e02a4e2cae2ba49e86d969a38cfb0f29
issue.challenge.state =
    1e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915ed9
    f10fda352447af1471a9138cd978536c6a2ca4e1d0b8c6276d7c73295d1dc583
    fc92457347bcb123e11829df470496cf285ab9dc788aea530f63de240798a4ee
    098abe35e32374ccafd832471789a93d8b4e04c82897497528e07dc05f0d6624
    b09aa9f4e511dd6d87a9df6cbf59dc076388ae8fa79962364d4e70102bcd22ff
    f97e91e88b4fe26b2f6f80faa20499b2cc8448674d53792e386223cc1396dd19
issue.challenge.message =
    838f0e04447101fc590f5ec39c90a8be7bd45329346c6216148a1467bc325eef
issue.response.message =
    455e3d35da4bd2ce0930aacafdcbee388a9c0a753c2d35574853badb06ad7a7c
    129b59d6269a5f982b314865ca56fc7ecf907529ff1c2c0944e23b7e915d92fe
    c34d0a3f8cd5d3e20875b244e1530bba5dbec428af00027d22039f7dda8db087
issue.endorsement =
    f97e91e88b4fe26b2f6f80faa20499b2cc8448674d53792e386223cc1396dd19
    5962f7763329f82b5cc83a13fcadc9469b22d6963ccae504e01eb122b3583252
    2718a87ea08bc1c93febf220569485c963a24ef239a16f816cf6f3119b8575c1
    c966ac47b7faf614ac00a21a8f1d96fbf2688d96bb91c048141790f793721495
    1e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915ed9
]]></artwork>
      </section>
      <section anchor="ec-ihat-tv-redeem2">
        <name>Redemption Against 2 Anchors</name>
        <artwork><![CDATA[
redeem2.index = 1
redeem2.anchor_set =
    02eb95f5cedca77363bcb9808b656de3082c23d67506f96c717952e8cce9d240
    a8024d804bd96c34e6b1708374c9da148db973cc69e4920f9f6d32d3cdeec537
    583f
redeem2.challenge_digest =
    45432d49484154207465737420766563746f7273206368616c6c656e67652064
    6967657374
redeem2.rand =
    bb214c063c44660b2193e4ff68f6acb3643d54257e6a03f27d7162b210794faa
    40d383b6ed9f37de84973d1232dd3ce30106ddb4ed4f130968ddc9d54066d004
    1ce24800e438f27ff3aa9c3fa1575f10cee63ab4bbac324a1a4895786f016573
redeem2.delta =
    d3aca91a849c8f30aa7a3f31842ff2bb535b6b34d676c7cd77c5a0125e72db28
redeem2.message =
    029dc60bb0c07274bb09cff84e5202354bc5116b9f56f4776ad74a6f296428c4
    7ef97e91e88b4fe26b2f6f80faa20499b2cc8448674d53792e386223cc1396dd
    19de7841f140ca998aef6a9862b3e49c5c64a22dcd1c4dc017a8e1de28238614
    192718a87ea08bc1c93febf220569485c963a24ef239a16f816cf6f3119b8575
    c1c966ac47b7faf614ac00a21a8f1d96fbf2688d96bb91c048141790f7937214
    951e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915e
    d9dcdb1bf2752d262faa01e23f63177aab005ca60ef098b466ba32c4c09b13c5
    5f68ce1afdfbc9550f9e4f6aca1b57cd42e9607f199b96f3835d986364aec9b2
    4021026202ce942dc5798ae14695d4ca00e2955493c40a0dbce1c068e8ad3e73
    345128206ff15e6c7ae1ad15f0e8419c98b5f3d8608f7997489f1aa2d3fd7e01
    6b9365c8
redeem2.nf =
    1e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915ed9
]]></artwork>
      </section>
      <section anchor="ec-ihat-tv-redeem5">
        <name>Redemption Against 5 Anchors</name>
        <artwork><![CDATA[
redeem5.index = 3
redeem5.anchor_set =
    027c0c7a8f7ebc13b50e2392c122f9a66799a1e71189a86a0d30b492bfaa371a
    7802d8a8886b22bee6d1777f8c76a695d477a3c60a0962a4cd8a02cc4e6431f3
    40b7025f2dc1fe0b5573ebf4ce1f1ae0492350fdcc04d5ba2b48c8b21f73cb63
    5fa99d024d804bd96c34e6b1708374c9da148db973cc69e4920f9f6d32d3cdee
    c537583f03affc2c254d196c3effcd4e69667bc152370df56313b19c03af3f31
    0f4b6a87f2
redeem5.challenge_digest =
    45432d49484154207465737420766563746f7273206368616c6c656e67652064
    6967657374
redeem5.rand =
    558fe7711d3f49116fd154a013e42aaf828ebb19e9e2352819990100eb1c1c9a
    abf55df1e84433158c6876394920204f12fd2b344628dfc2748d70d3aa80aa23
    0608494028ab6ec5236a2bf4876c767dd834ca244fb1af8ce935c346cafa1005
redeem5.delta =
    b8efd6a9a93354b0ef988ba6add03fbb843c83f7d776c5088e80537440776855
redeem5.message =
    036e54617195473504812e14b44912097f62b6f7d72f7e88b6e571bc41a0394a
    7cf97e91e88b4fe26b2f6f80faa20499b2cc8448674d53792e386223cc1396dd
    196851575c8c96e72bc1b05cc88fe39d9f6c5df5c435aa7174be1e0d055d3df2
    662718a87ea08bc1c93febf220569485c963a24ef239a16f816cf6f3119b8575
    c1c966ac47b7faf614ac00a21a8f1d96fbf2688d96bb91c048141790f7937214
    951e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915e
    d950529d143f3c4f71f4270f4d7f84b9c3d2b1d1c5daa4c0caf8ee1d338885f1
    a4691136fa0520c546bbff2a00faf6a012faf8c281ee8385c0d6a8116e85a2c8
    704063038d292aa5b69f1dea681c1f753f5d53f9d10b45bb399cee7b1fc6531d
    72b908c1027b75353c0b05b768798410106bb01a761634cc29423c8b45e96b3a
    f1441349bb037610019efbae269ac174e983ecae9ffa9c73e225e8ba54b706d7
    c164e4392e1540609574c0a33b601e403d4fd5bbf057fd6e5d05f11fb9168629
    9a16416ae73880abd3d3ddef893007f0933b35454109117b243e8ff280c6435e
    dcf1087b97724a42a805bd91e9545402352ca0200f3bdcd0117ad57684009761
    b065ee322027e03f
redeem5.nf =
    1e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915ed9
]]></artwork>
      </section>
      <section anchor="ec-ihat-tv-redeem1">
        <name>Redemption Against 1 Anchor</name>
        <artwork><![CDATA[
redeem1.index = 0
redeem1.anchor_set =
    024d804bd96c34e6b1708374c9da148db973cc69e4920f9f6d32d3cdeec53758
    3f
redeem1.challenge_digest =
    45432d49484154207465737420766563746f7273206368616c6c656e67652064
    6967657374
redeem1.rand =
    0ab3d707e39d461b2861cb6e8e6a2c6c3bf2640081448678f846db0886fd053b
    4dd223e71416f52740000183803b28f7a55ad488794504e01619d2f2600ec071
    5ff5bbe0b582a64a6f2db846184d541ab636e578683fcb9b9acc2ab1bbf1bdac
redeem1.delta =
    ff8c0a8d5403241b69df67b3ef9f16474021cb373a4715dc5426ef490e5231c3
redeem1.message =
    03300196a535ec07e6d8462cc80360e9630ca3a6d5d3a2b67fa241f6a929c816
    a5f97e91e88b4fe26b2f6f80faa20499b2cc8448674d53792e386223cc1396dd
    19128120835a8453057e46c2ecbaf20f7dd97d30a94480e62dcc26c8425ef305
    182718a87ea08bc1c93febf220569485c963a24ef239a16f816cf6f3119b8575
    c1c966ac47b7faf614ac00a21a8f1d96fbf2688d96bb91c048141790f7937214
    951e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915e
    d9c2dcc7d873582ac78015ba03d96201b2298130e72106175eff6662cf33ed95
    8daf5bb5d6a461ab7e310351640c454fbc9fb654c64c1f7b53fffd44c018a92f
    830000
redeem1.nf =
    1e431d9d3344384352c666d070c4c56c55ccb150b6765addbdb264c0c3915ed9
]]></artwork>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The authors thank Christopher Patton and Thibault Meunier for review and
improvements to the protocol description.</t>
    </section>
    <section numbered="false" anchor="changelog">
      <name>Changelog</name>
      <t>draft-ladd-mole-ec-ihat-00</t>
      <ul spacing="normal">
        <li>
          <t>Initial version.</t>
        </li>
      </ul>
    </section>
  </back>
  <!-- ##markdown-source:
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
K3NaV99d/6JflVBP18dTjr6/+hesrLx/zloBAA==

-->

</rfc>
