<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.23 (Ruby 2.6.10) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-orru-zkproof-sigma-protocols-00" category="info" submissionType="independent" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.26.0 -->
  <front>
    <title>Sigma Protocols</title>
    <seriesInfo name="Internet-Draft" value="draft-orru-zkproof-sigma-protocols-00"/>
    <author fullname="Michele Orrù">
      <organization>CNRS</organization>
      <address>
        <email>m@orru.net</email>
      </address>
    </author>
    <date year="2025" month="February" day="26"/>
    <keyword>zero-knowledge</keyword>
    <abstract>
      <?line 40?>

<t>This document describes Sigma protocols, a secure, general-purpose non-interactive zero-knowledge proof of knowledge. Concretely, the scheme allows proving knowledge of a witness, without revealing any information about the undisclosed messages or the signature itself, while at the same time, guarantying soundness of the overall protocols.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://mmaker.github.io/stdsigma/draft-orru-zkproof-sigma-protocols.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-orru-zkproof-sigma-protocols/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/mmaker/stdsigma"/>.</t>
    </note>
  </front>
  <middle>
    <?line 44?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>A Sigma Protocol is a simple zero-knowledge proof of knowledge. Any sigma protocols must define three objects:</t>
      <ul spacing="normal">
        <li>
          <t>A commitment, sometimes also called nonce. This message is computed by the prover.</t>
        </li>
        <li>
          <t>A challenge, computed using the Fiat-Shamir transformation using a hash function.</t>
        </li>
        <li>
          <t>A response, computed by the prover, which depends on the commitment and the challenge.</t>
        </li>
      </ul>
      <t>A sigma protocol allows to convince a <strong>verifier</strong> of the knowledge of a secret <strong>witness</strong> satisfying a <strong>statement</strong>.</t>
      <section anchor="generic-interface">
        <name>Generic interface</name>
        <t>A sigma protocol is an interface exposing the following functions:</t>
        <artwork><![CDATA[
def prove_short(label, statement, witness):
    sp = SigmaProtocol.new(statement)
    (prover_state, commitment) = sp.prover_commmit(witness)
    challenge = SHO
        .init(label)
        .absorb(commitment)
        .squeeze(1)

    response = sp.prover_response(commitment, challenge)
    return scalar_to_bytes(challenge) + scalar_to_bytes(response)

def prove_batchable(label, statement, witness):
    sp = SigmaProtocol.new(statement)
    (prover_state, commitment) = sp.prover_commit(witness)
    challenge = SHO
        .init(label)
        .absorb(commitment)
        .squeeze(1)
    response = sp.prover_response(commitment, challenge)
    return point_to_bytes(commitment) + scalar_to_bytes(response)

def verify_batchable(label, statement, proof):
    sp = SigmaProtocol.new(statement)
    commitment = read_group_elements(proof)
]]></artwork>
        <t>Internally, each sigma protocol implements the following methods.</t>
        <artwork><![CDATA[
class SigmaProtocol:
   def new(instance: Statement) -> SigmaProtocol
   def prover_commit(self, witness: Witness) -> (commitment, prover_state)
   def prover_response(self, prover_state, challenge) -> response
   def verifier(self, commitment, challenge, response) -> bool
   # optional
   def simulate_response() -> response
   # optional
   def simulate_commitment(response, challenge) -> commitment
]]></artwork>
        <t>Where:</t>
        <ul spacing="normal">
          <li>
            <t><tt>new(il: [u8], cs: ConstraintSystem) -&gt; SigmaProtocol</tt>, denoting the initialization function. This function takes as input a label identifying local context information (such as: session identifiers, to avoid replay attacks; protocol metadata, to avoid hijacking; optionally, a timestamp and some pre-shared randomness, to guarantee freshness of the proof) and an instance generated via the <tt>ConstraintSystem</tt>, the public information shared between prover and verifier.
This function should pre-compute parts of the statement, or initialize the state of the hash function.</t>
          </li>
          <li>
            <t><tt>prover_commit(self, witness: Witness) -&gt; (commitment, prover_state)</tt>, denoting the <strong>commitment phase</strong>, that is, the computation of the first message sent by the prover in a Sigma protocol. This method outputs a new commitment together with its associated prover state, depending on the witness known to the prover and the statement to be proven. This step generally requires access to a high-quality entropy source. Leakage of even just of a few bits of the nonce could allow for the complete recovery of the witness. The commitment meant to be shared, while <tt>prover_state</tt> must be kept secret.</t>
          </li>
          <li>
            <t><tt>prover_response(self, prover_state, challenge) -&gt; response</tt>, denoting the <strong>response phase</strong>, that is, the computation of the second message sent by the prover, depending on the witness, the statement, the challenge received from the verifier, and the internal state <tt>prover_state</tt>. The returned value <tt>response</tt> is meant to be shared.</t>
          </li>
          <li>
            <t><tt>verifier(self, commitment, challenge, response) -&gt; bool</tt>, denoting the <strong>verifier algorithm</strong>. This method checks that the protocol transcript is valid for the given statement. The verifier algorithm outputs nothing if verification succeeds, or an error if verification fails.</t>
          </li>
        </ul>
        <t>The final two algorithms describe the <strong>zero-knowledge simulator</strong> and are optional. The simulator is primarily an efficient algorithm for proving zero-knowledge in a theoretical construction, but it is also needed for verifying short proofs and for or-composition, where a witness is not known and thus has to be simulated. We have:</t>
        <ul spacing="normal">
          <li>
            <t><tt>simulate_response() -&gt; response</tt>, denoting the first stage of the simulator. It is an algorithm drawing a random response that follows the same output distribution of the algorithm  <tt>prover_response</tt></t>
          </li>
          <li>
            <t><tt>simulate_commitment(response, challenge) -&gt; commitment</tt>, returning a simulated commitment -- the second phase of the zero-knowledge simulator.</t>
          </li>
        </ul>
        <t>The abstraction <tt>SigmaProtocol</tt> allows implementing different types of statements and combiners of those, such as OR statements, validity of t-out-of-n statements, and more.</t>
      </section>
    </section>
    <section anchor="protocols-over-prime-order-groups">
      <name>Σ-protocols over prime-order groups</name>
      <t>The following sub-section present concrete instantiations of Σ-protocols over prime-order groups such as elliptic curves.
Traditionally, Σ-protocols are defined in Camenish-Stadtler notation as (for example):</t>
      <artwork><![CDATA[
VRF(A, B, G, H) = PoK{
  (x):        // Secret variables
  A = x * B,  // Statements to prove
  G = x * H
}
]]></artwork>
      <t>This section describes how to build and prove statements of this form programmatically.</t>
      <section anchor="group-abstraction">
        <name>Group abstraction</name>
        <t>Because of their dominance, the presentation in the following focuses on proof goals over elliptic curves, therefore leveraging additive notation. For prime-order
subgroups of residue classes, all notation needs to be changed to multiplicative, and references to elliptic curves (e.g., curve) need to be replaced by their respective
counterparts over residue classes.
We therefore assume two objects are available to the programmer:</t>
        <artwork><![CDATA[
Group: Zero + Add<Group> + Sub<Group> + Mul<Scalar> + From<int> + Eq<Group> + Serialize + Deserialize
Scalar: Zero + One + Div<Scalar> + Add<Scalar> + Sub<Scalar> + From<int> + Eq<Group> + Serialize + Deserialize
]]></artwork>
        <t>We detail the functions that can be invoked on these objects. Example choices can be found in <xref target="ciphersuites"/>.</t>
        <section anchor="group">
          <name>Group</name>
          <ul spacing="normal">
            <li>
              <t><tt>order()</tt>: Outputs the order of the group <tt>p</tt>.</t>
            </li>
            <li>
              <t><tt>random()</tt>: outputs a random element</t>
            </li>
            <li>
              <t><tt>serialize([Group; N])</tt>: serializes a list of group elements and returns a canonical byte array <tt>buf</tt> of fixed length <tt>Ng * N</tt>.</t>
            </li>
            <li>
              <t><tt>deserialize(buf)</tt>: Attempts to map a byte array <tt>buf</tt> of size <tt>Ng * N</tt> into <tt>[Group; N]</tt>, and fails if the input is not the valid canonical byte representation of an element of the group. This function can raise a DeserializeError if deserialization fails.</t>
            </li>
          </ul>
        </section>
        <section anchor="scalar">
          <name>Scalar</name>
          <ul spacing="normal">
            <li>
              <t><tt>random()</tt>: outputs a random element</t>
            </li>
            <li>
              <t><tt>serialize([Scalar; N])</tt>: serializes a list of scalars and returns their canonical representation of fixed length <tt>Ns * N</tt>.</t>
            </li>
          </ul>
        </section>
      </section>
      <section anchor="witness-representation">
        <name>Witness representation</name>
        <t>A witness is simply a list of <tt>num_scalars</tt> elements.</t>
        <artwork><![CDATA[
struct Witness {
    scalars: [Scalar; num_scalars] // The set of secret scalars
}
]]></artwork>
        <section anchor="constraint-representation">
          <name>Constraint representation</name>
          <t>Internally, the constraint can be represented as:</t>
          <artwork><![CDATA[
struct Equations {
    // the list of statements to be proven
    matrix: [LinearCombination<ScalarIndex, &Group>; num_statements]
    // An list of references to group elements representing the left-hand side part of the equations
    image: [&Group; num_statements]

    // the number of secret scalars
    num_scalars: usize
    // the number of equations to be proven
    num_statements: usize
}
]]></artwork>
          <t>The object <tt>LinearCombination</tt> encodes pairs of indices of the witness vector with group elements.
The initial example of the VRF can therefore be expressed with the following constraints:</t>
          <artwork><![CDATA[
cs = Equations()
[x] = cs.allocate_scalars(1)
[A, B, G, H] = cs.allocate_group_elt(4)
cs.append_equation(lhs=A, rhs=[(x, B)])
cs.append_equation(lhs=G, rhs=[(x, H)])
]]></artwork>
          <t>In the above, <tt>Equations.new()</tt> creates a new <tt>Equations</tt> with label <tt>"VRF"</tt>.</t>
          <section anchor="instantiation-of-the-constraints">
            <name>Instantiation of the constraints</name>
            <artwork><![CDATA[
new(label)

Inputs:

- labels, a byte array

Outputs:

- a ConstraintSystem instance

Procedure:

1.  return Equations {
2.        label,
3.        num_statements: 0,
4.        num_scalars: 0,
5.        group_elements: [],
6.        matrix: [],
7.        image: []
8.    }
]]></artwork>
          </section>
          <section anchor="scalar-witness-allocation">
            <name>Scalar witness allocation</name>
            <artwork><![CDATA[
allocate_scalars(self, n)

Inputs:
    - self, the current state of the ConstraintSystem
    - n, the number of scalars to allocate
Outputs:
    - indices, a list of integers each pointing to the new allocated scalars

Procedure:

1. indices = range(self.num_scalars, self.num_scalars + n)
2. self.num_scalars += n
3. return indices
]]></artwork>
          </section>
          <section anchor="public-group-element-allocation">
            <name>Public group element allocation</name>
            <artwork><![CDATA[
allocate_group_elt(self, n)

Inputs:

   - self, the current state of the constraint system
   - n, the number of group elements to allocate

Outputs:

   - indices, a list of integers each pointing to the new allocated group elements.

Procedure:

1. indices = range(len(self.group_elts), len(self.group_elements) + n)
2. self.group_elements.extend([None] * n)
3. return indices
]]></artwork>
          </section>
          <section anchor="group-element-assignment">
            <name>Group element assignment</name>
            <artwork><![CDATA[
assign_point(self, ptr, value)

Inputs:

    - self, the current state of the constraint system
    - ptr, the pointer to the group element to be assigned
    - value, the value to be assigned to the group element

Procedure:

1. self.group_elements[ptr] = value
]]></artwork>
          </section>
          <section anchor="enforcing-an-equation">
            <name>Enforcing an equation</name>
            <t>This function adds an equation statement constraint to the instance, expressed as a left-hand side (the target group element), and a list of pairs encoding a linear combination of scalars and group elements.</t>
            <artwork><![CDATA[
append_equation(self, lhs, rhs)

Inputs:

- self, the current state of the constraint system
- lhs, the left-hand side of the equation
- rhs, the right-hand side of the equation (a list of (ScalarIndex, GroupEltIndex) pairs)

Outputs:

- An Equation instance that enforces the desired relation

Procedure:

1. self.num_statements += 1
2. self.image.append(lhs)
3. self.matrix.append(rhs)
]]></artwork>
            <t>A witness can be mapped to a group element via:</t>
            <artwork><![CDATA[
def map(self, witness: [Scalar; num_scalars]):
  assert self.num_scalars = self.scalars.len()
  image = [0; Group]
  for i in range(self.num_statements):
      eq_scalars = [self.scalars[idx_pair[0]]
                    for idx_pair in self.matrix[i]]
      eq_group_elt = [self..group_elements[idx_pair[1]] for idx_pair in self.matrix[i]]
      image[i] = multi_scalar_multiplication(eq_scalars, eq_group_elt)
  return image
]]></artwork>
          </section>
        </section>
      </section>
      <section anchor="core-protocol">
        <name>Core protocol</name>
        <artwork><![CDATA[
class SigmaProtocol:
    def new(statement: Statement):
        self.statement = statement

    def prover_commit(self, witness: Witness):
        nonces = Scalar::random()
        prover_state = (witness, nonces)
        commitment = self.statement.map(witness)
        return (prover_state, commitment)

    def prover_response(self, prover_state, challenge):
        response = [0; self.cs.num_scalars]
        for i in range(self.cs.num_scalars):
            response[i] = witness[i] + challenge * nonces[i]
        return response
]]></artwork>
        <section anchor="verifier-procedure">
          <name>Verifier procedure</name>
          <artwork><![CDATA[
verify(self, commitment, challenge, response)

Inputs:

- self, the current state of the SigmaProtocol
- commitment, the commitment generated by the prover
- challenge, the challenge generated by the verifier
- response, the response generated by the prover

Outputs:

- A boolean indicating whether the verification succeeded

Procedure:

1. image = [equation.lhs for equation in self.statement.equations]
2. expected_commitment = challenge * image + self.statement.map(response)
3. return expected_commitment == commitment
]]></artwork>
        </section>
        <section anchor="prover">
          <name>Prover</name>
          <t>We describe below the prover's wrapping function.</t>
          <artwork><![CDATA[
def prove_short(statement, witness):
  sp = SigmaProtocol.new(statement)
  (prover_state, commitment) = sp.prover_commmit(witness)
  challenge = sp.challenge(commitment)
  response = sp.prover_response(commitment, challenge)
  return scalar_to_bytes(challenge) + scalar_to_bytes(response)

def prove_batchable(statement, witness):
  sp = SigmaProtocol.new(statement)
  (prover_state, commitment) = sp.prover_commmit(witness)
  challenge = sp.challenge(commitment)
  response = sp.prover_response(commitment, challange)
  return point_to_bytes(commitment) + scalar_to_bytes(response)
]]></artwork>
        </section>
        <section anchor="verifier">
          <name>Verifier</name>
          <artwork><![CDATA[
def verify_batchable(statement, proof):
  sp = SigmaProtocol.new(statement)
  commitment = read_group_elements(proof)
]]></artwork>
        </section>
      </section>
      <section anchor="nonce-and-challenge-derivation">
        <name>Nonce and challenge derivation</name>
        <t>Two types of randomness are needed for a sigma protocol:</t>
        <ol spacing="normal" type="1"><li>
            <t>A nonce seeding the randomness used to produce the commitment of the first round of the protocol</t>
          </li>
          <li>
            <t>A challenge representing the verifier's public random coin.</t>
          </li>
        </ol>
        <t>The challenge of a Schnorr proof is derived with</t>
        <artwork><![CDATA[
challenge = sho.init(iv).absorb_group_elt(commitment).squeeze_scalar(1)
]]></artwork>
        <t>This can be generated with:</t>
        <artwork><![CDATA[
nonce = sho.init(iv)
           .absorb_bytes(random)
           .ratchet()
           .absorb_scalars(witness)
           .squeeze_scalars(cs.num_scalars)
]]></artwork>
        <t>The <tt>iv</tt>, which must properly separate the application and the statement being proved, is described below.</t>
        <section anchor="statement-generation">
          <name>Statement generation</name>
          <t>Let <tt>H</tt> be a hash object. The statement is encoded in a stateful hash object as follows.</t>
          <artwork><![CDATA[
hasher = H.new(domain_separator)
hasher.update_usize([cs.num_statements, cs.num_scalars])
for equation in cs.equations:
  hasher.update_usize([equation.lhs, equation.rhs[0], equation.rhs[1]])
hasher.update(generators)
iv = hasher.digest()
]]></artwork>
          <t>In simpler terms, without stateful hash objects, this should correspond to the following:</t>
          <artwork><![CDATA[
bin_challenge = SHAKE128(iv).update(commitment).digest(scalar_bytes)
challenge = int(bin_challenge) % p
]]></artwork>
          <t>and the nonce is produced as:</t>
          <artwork><![CDATA[
bin_nonce = SHAKE128(iv)
            .update(random)
            .update(pad)
            .update(cs.scalars)
            .digest(cs.num_scalars * scalar_bytes)
nonces = [int(bin_nonce[i*scalar_bytes: i*(scalar_bytes+1)]) % p
          for i in range(cs.num_scalars-1)]
]]></artwork>
          <t>Where:
    - <tt>pad</tt> is a (padding) zero string of length <tt>168 - len(random)</tt>.
    - <tt>scalar_bytes</tt> is the number of bytes required to produce a uniformly random group element
    - <tt>random</tt> is a random seed obtained from the operating system memory</t>
        </section>
      </section>
    </section>
    <section anchor="ciphersuites">
      <name>Ciphersuites</name>
      <section anchor="p-384">
        <name>P-384</name>
        <t>This ciphersuite uses P-384 <xref target="NISTCurves"/> for the Group.</t>
        <section anchor="elliptic-curve-group-of-p-384-secp384r1-nistcurves">
          <name>Elliptic curve group of P-384 (secp384r1) <xref target="NISTCurves"/></name>
          <ul spacing="normal">
            <li>
              <t><tt>order()</tt>: Return 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973.</t>
            </li>
            <li>
              <t><tt>serialize([A])</tt>: Implemented using the compressed Elliptic-Curve-Point-to-Octet-String method according to <xref target="SEC1"/>; <tt>Ng = 49</tt>.</t>
            </li>
            <li>
              <t><tt>deserialize(buf)</tt>: Implemented by attempting to read <tt>buf</tt> into chunks of 49-byte arrays and convert them using the compressed Octet-String-to-Elliptic-Curve-Point method according to <xref target="SEC1"/>, and then performs partial public-key validation as defined in section 5.6.2.3.4 of <xref target="KEYAGREEMENT"/>. This includes checking that the coordinates of the resulting point are in the correct range, that the point is on the curve, and that the point is not the point at infinity.</t>
            </li>
          </ul>
        </section>
        <section anchor="scalar-field-of-p-384-secp384r1">
          <name>Scalar Field of P-384 (secp384r1)</name>
          <ul spacing="normal">
            <li>
              <t><tt>serialize(s)</tt>: Relies on the Field-Element-to-Octet-String conversion according to <xref target="SEC1"/>; <tt>Ns = 48</tt>.</t>
            </li>
            <li>
              <t><tt>deserialize(buf)</tt>: Reads the byte array <tt>buf</tt> in chunks of 48 bytes using Octet-String-to-Field-Element from <xref target="SEC1"/>. This function can fail if the input does not represent a Scalar in the range [0, G.Order() - 1].</t>
            </li>
          </ul>
        </section>
      </section>
    </section>
    <section anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Jan Bobolz, Stephan Krenn, Mary Maller, Ivan Visconti, Yuwen Zhang.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="KEYAGREEMENT">
          <front>
            <title>Recommendation for pair-wise key-establishment schemes using discrete logarithm cryptography</title>
            <author fullname="Elaine Barker" initials="E." surname="Barker">
              <organization/>
            </author>
            <author fullname="Lily Chen" initials="L." surname="Chen">
              <organization/>
            </author>
            <author fullname="Allen Roginsky" initials="A." surname="Roginsky">
              <organization/>
            </author>
            <author fullname="Apostol Vassilev" initials="A." surname="Vassilev">
              <organization/>
            </author>
            <author fullname="Richard Davis" initials="R." surname="Davis">
              <organization/>
            </author>
            <date month="April" year="2018"/>
          </front>
          <seriesInfo name="DOI" value="10.6028/nist.sp.800-56ar3"/>
          <refcontent>National Institute of Standards and Technology</refcontent>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="NISTCurves">
          <front>
            <title>Digital signature standard (DSS)</title>
            <author>
              <organization/>
            </author>
            <date year="2013"/>
          </front>
          <seriesInfo name="DOI" value="10.6028/nist.fips.186-4"/>
          <refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
        </reference>
        <reference anchor="SEC1" target="https://www.secg.org/sec1-v2.pdf">
          <front>
            <title>SEC 1: Elliptic Curve Cryptography</title>
            <author initials="" surname="Standards for Efficient Cryptography Group (SECG)">
              <organization/>
            </author>
            <date/>
          </front>
        </reference>
      </references>
    </references>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
