Crypto Forum M. OrrĂ¹ Internet-Draft CNRS Intended status: Informational C. Yun Expires: 3 October 2026 Apple, Inc. 1 April 2026 Interactive Sigma Proofs draft-irtf-cfrg-sigma-protocols-latest Abstract A Sigma Protocol is an interactive zero-knowledge proof of knowledge that allows a prover to convince a verifier of the validity of a statement. It satisfies the properties of completeness, soundness, and zero-knowledge, as described in Section 3. This document describes Sigma Protocols for proving knowledge of pre- images of linear maps in prime-order elliptic curve groups. Examples include zero-knowledge proofs for discrete logarithm relations, ElGamal encryptions, Pedersen commitments, and range proofs. About This Document This note is to be removed before publishing as an RFC. The latest revision of this draft can be found at https://mmaker.github.io/draft-irtf-cfrg-sigma-protocols/draft-irtf- cfrg-sigma-protocols.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-irtf-cfrg-sigma- protocols/. Discussion of this document takes place on the Crypto Forum Research Group mailing list (mailto:cfrg@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/cfrg. Subscribe at https://www.ietf.org/mailman/listinfo/cfrg/. Source for this draft and an issue tracker can be found at https://github.com/mmaker/draft-irtf-cfrg-sigma-protocols. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 3 October 2026. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Table of Contents 1. Introduction 1.1. Core interface 1.1.1. Randomized algorithms 2. Sigma Protocols over prime-order groups 2.1. Group abstraction 2.1.1. Group 2.1.2. Scalar 2.2. Proofs of preimage of a linear map 2.2.1. Witness representation 2.2.2. Linear map 2.2.3. Statements for linear relations 2.2.4. Core protocol 2.2.5. Prover procedures 2.2.6. Verifier 2.2.7. Example: Schnorr proofs 2.2.8. Example: DLEQ proofs 2.2.9. Example: Pedersen commitments 2.3. Ciphersuites 2.3.1. P-256 (secp256r1) 3. Security Considerations 3.1. Privacy Considerations 3.2. Constant-Time Requirements 4. Post-Quantum Security Considerations 4.1. Privacy Considerations 4.2. Soundness Considerations 5. Generation of the protocol identifier 6. Generation of the instance identifier Acknowledgments References Normative References Informative References Appendix A. Test Vectors A.1. Seeded PRNG A.2. sigma-proofs(P-256, SHAKE128) A.3. discrete_logarithm A.4. dleq A.5. pedersen_commitment A.6. pedersen_commitment_dleq A.7. bbs_blind_commitment_computation A.8. sigma-proofs(BLS12-381, SHAKE128) A.9. discrete_logarithm A.10. dleq A.11. pedersen_commitment A.12. pedersen_commitment_dleq A.13. bbs_blind_commitment_computation Authors' Addresses 1. Introduction Any Sigma Protocol must define a _commitment_ (computed by the prover), a _challenge_ (randomly sampled from a specific distribution), and a _response_ (computed by the prover). One of the advantages of Sigma Protocols is their composability, which enables the construction of more complex protocols. A classic example is the OR composition [CramerDS94]. Given a Sigma Protocol for N relations, it is possible to prove knowledge of one of N witnesses for those relations . The composed sigma protocols can be made non-interactive using the Fiat-Shamir transformation [Cramer97]. However, such compositions must be handled carefully to preserve security properties as discussed in Section 3. 1.1. Core interface The public functions are obtained relying on an internal structure containing the definition of a Sigma Protocol. class SigmaProtocol: def new(instance) -> SigmaProtocol def prover_commit(self, witness, rng) -> (commitment, prover_state) def prover_response(self, prover_state, challenge) -> response def verifier(self, commitment, challenge, response) -> bool def serialize_commitment(self, commitment) -> bytes def serialize_response(self, response) -> bytes def deserialize_commitment(self, data: bytes) -> commitment def deserialize_response(self, data: bytes) -> response # optional def simulate_response(self, rng) -> response # optional def simulate_commitment(self, response, challenge) -> commitment Where: * new(instance) -> SigmaProtocol, denoting the initialization function. This function takes as input an instance generated via a LinearRelation, the public information shared between prover and verifier. * prover_commit(self, witness: Witness, rng) -> (commitment, prover_state), denoting the *commitment phase*, 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, the statement to be proven, and a random number generator rng as defined in Section 1.1.1. This step generally requires access to a high-quality entropy source to perform the commitment. Leakage of even just a few bits of the commitment could allow for the complete recovery of the witness. The commitment is meant to be shared, while prover_state must be kept secret. * prover_response(self, prover_state, challenge) -> response, denoting the *response phase*, 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 prover_state. The return value response is a public value and is transmitted to the verifier. * verifier(self, commitment, challenge, response) -> bool, denoting the *verifier algorithm*. This method checks that the protocol transcript is valid for the given statement. The verifier algorithm outputs true if verification succeeds, or false if verification fails. * serialize_commitment(self, commitment) -> bytes, serializes the commitment into a canonical byte representation. * serialize_response(self, response) -> bytes, serializes the response into a canonical byte representation. * deserialize_commitment(self, data: bytes) -> commitment, deserializes a byte array into a commitment. This function can raise a DeserializeError if deserialization fails. * deserialize_response(self, data: bytes) -> response, deserializes a byte array into a response. This function can raise a DeserializeError if deserialization fails. The final two algorithms describe the *zero-knowledge simulator*. In particular, they may be used for proof composition (e.g. OR- composition). The function simulate_commitment is also used when verifying short proofs. We have: * simulate_response(self, rng) -> response, denoting the first stage of the simulator. * simulate_commitment(self, response, challenge) -> commitment, returning a simulated commitment -- the second phase of the zero- knowledge simulator. The simulated transcript (commitment, challenge, response) must be indistinguishable from the one generated using the prover algorithms. The abstraction SigmaProtocol allows implementing different types of statements and combiners of those, such as OR statements, validity of t-out-of-n statements, and more. 1.1.1. Randomized algorithms The generation of proofs involves randomized algorithms that take as input a source of randomness, denoted as rng. The functionality required in this document is a secure way to sample non-zero scalars uniformly at random. Algorithms access this functionality through the following interface. class CSRNG(ABC): def getrandom(self, length: int) -> bytes: pass def random_scalar(self) -> groups.Scalar: pass Implementations MUST use a cryptographically secure pseudorandom number generator (CSPRNG) to sample non-zero scalars either by using rejection sampling methods or reducing a large bitstring modulo the group order. Refer to Section A.4 of [FIPS.186-5] for guidance about these methods. 2. Sigma Protocols over prime-order groups The following sub-section presents concrete instantiations of Sigma Protocols over prime-order elliptic curve groups. It relies on a prime-order elliptic-curve group as described in Section 2.1. Valid choices of elliptic curves can be found in Section 2.3. Traditionally, Sigma Protocols are defined in Camenisch-Stadler [CS97] notation as (for example): 1. DLEQ(G, H, X, Y) = PoK{ 2. (x): // Secret variables 3. X = x * G, Y = x * H // Predicates to satisfy 4. } In the above, line 1 declares that the proof name is "DLEQ", the public information (the *instance*) consists of the group elements (G, X, H, Y) denoted in upper-case. Line 2 states that the private information (the *witness*) consists of the scalar x. Finally, line 3 states that the linear relation that needs to be proven is x * G = X and x * H = Y. 2.1. Group abstraction 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 detail the functions that can be invoked on these objects. Example choices can be found in Section 2.3. 2.1.1. Group * identity(), returns the neutral element in the group. * generator(), returns the generator of the prime-order elliptic- curve subgroup used for cryptographic operations. * order(): returns the order of the group p. * serialize(elements: [Group; N]), serializes a list of group elements and returns a canonical byte array buf of fixed length Ne * N. * deserialize(buffer), attempts to map a byte array buffer of size Ne * N into [Group; N], fails if the input is not the valid canonical byte representation of an array of elements of the group. This function can raise a DeserializeError if deserialization fails. * add(element: Group), implements elliptic curve addition for the two group elements. * equal(element: Group), returns true if the two elements are the same and false otherwise. * scalar_mul(scalar: Scalar), implements scalar multiplication for a group element by an element in its respective scalar field. In this spec, instead of add we will use + with infix notation; instead of equal we will use ==, and instead of scalar_mul we will use *. A similar behavior can be achieved using operator overloading. 2.1.2. Scalar * identity(): outputs the (additive) identity element in the scalar field. * add(scalar: Scalar): implements field addition for the elements in the field. * mul(scalar: Scalar), implements field multiplication. * random(rng): samples a scalar from the RNG. Securely decoding random bytes into a random scalar is described in Section 9.1.4 of [fiat-shamir]. * serialize(scalars: list[Scalar; N]): serializes a list of scalars and returns their canonical representation of fixed length Ns * N. * deserialize(buffer), attempts to map a byte array buffer of size Ns * N into [Scalar; N], and fails if the input is not the valid canonical byte representation of an array of elements of the scalar field. This function can raise a DeserializeError if deserialization fails. In this spec, instead of add we will use + with infix notation; instead of equal we will use ==, and instead of mul we will use *. A similar behavior can be achieved using operator overloading. 2.2. Proofs of preimage of a linear map 2.2.1. Witness representation A witness is an array of scalar elements. The length of the array is denoted num_scalars. Witness = [Scalar; num_scalars] 2.2.2. Linear map A _linear map_ takes a Witness (an array of num_scalars in the scalar field) and maps it to an array of group elements. The length of the image is denoted num_elements. Linear maps can be represented as matrix-vector multiplications, where the multiplication is the elliptic curve scalar multiplication defined in Section 2.1. Since the matrix is oftentimes sparse, it is stored in Yale sparse matrix format. Here is an example: class LinearCombination: scalar_indices: list[int] element_indices: list[int] The linear map can then be presented as: class LinearMap: Group: groups.Group linear_combinations: list[LinearCombination] group_elements: list[Group] num_scalars: int num_elements: int def map(self, scalars: list[Group.ScalarField; num_scalars]) -> list[Group; num_elements] 2.2.2.1. Initialization The linear map LinearMap is initialized with linear_combinations = [] group_elements = [] num_scalars = 0 num_elements = 0 2.2.2.2. Linear map evaluation A witness can be mapped to a vector of group elements via: map(self, scalars: [Scalar; num_scalars]) -> list[Group; num_elements] Inputs: - self, the current state of the constraint system - witness, 1. image = [] 2. for linear_combination in self.linear_combinations: 3. coefficients = [scalars[i] for i in linear_combination.scalar_indices] 4. elements = [self.group_elements[i] for i in linear_combination.element_indices] 5. image.append(self.Group.msm(coefficients, elements)) 6. return image 2.2.3. Statements for linear relations A LinearRelation encodes a proof statement of the form linear_map(witness) = image, and is used to prove knowledge of a witness that produces image under linear map. It internally stores linear_map (cf. Section 2.2.2) and an image (an array of num_elements Group elements). class LinearRelation: Domain = group.ScalarField Image = group.Group linear_map = LinearMap image = list[group.Group] def allocate_scalars(self, n: int) -> list[int] def allocate_elements(self, n: int) -> list[int] def append_equation(self, lhs: int, rhs: list[(int, int)]) -> None def set_elements(self, elements: list[(int, Group)]) -> None 2.2.3.1. Element and scalar variables allocation Two functions allow to allocate the new scalars (the witness) and group elements (the instance). allocate_scalars(self, n) Inputs: - self, the current state of the LinearRelation - 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 and below the allocation of group elements allocate_elements(self, n) Inputs: - self, the current state of the LinearRelation - n, the number of elements to allocate Outputs: - indices, a list of integers each pointing to the new allocated elements Procedure: 1. indices = range(self.num_elements, self.num_elements + n) 2. self.num_elements += n 3. return indices Group elements, being part of the instance, can later be set using the function set_elements set_elements(self, elements) Inputs: - self, the current state of the LinearRelation - elements, a list of pairs of indices and group elements to be set Procedure: 1. for index, element in elements: 2. self.linear_map.group_elements[index] = element 2.2.3.2. Constraint enforcing 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. linear_combination = LinearMap.LinearCombination(scalar_indices=[x[0] for x in rhs], element_indices=[x[1] for x in rhs]) 2. self.linear_map.append(linear_combination) 3. self._image.append(lhs) 2.2.4. Core protocol This defines the object SchnorrProof. The initialization function takes as input the statement, and pre-processes it. 2.2.5. Prover procedures The prover of a Sigma Protocol is stateful and will send two messages, a "commitment" and a "response" message, described below. 2.2.5.1. Prover commitment prover_commit(self, witness, rng) Inputs: - witness, an array of scalars - rng, a cryptographically secure random number generator Outputs: - A (private) prover state, holding the information of the interactive prover necessary for producing the protocol response - A (public) commitment message, an element of the linear map image, that is, a vector of group elements. Procedure: 1. nonces = [rng.random_scalar() for _ in range(self.instance.linear_map.num_scalars)] 2. prover_state = self.ProverState(witness, nonces) 3. commitment = self.instance.linear_map(nonces) 4. return (prover_state, commitment) 2.2.5.2. Prover response prover_response(self, prover_state, challenge) Inputs: - prover_state, the current state of the prover - challenge, the verifier challenge scalar Outputs: - An array of scalar elements composing the response Procedure: 1. witness, nonces = prover_state 2. return [nonces[i] + witness[i] * challenge for i in range(self.instance.linear_map.num_scalars)] 2.2.6. Verifier 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. assert len(commitment) == self.instance.linear_map.num_constraints and len(response) == self.instance.linear_map.num_scalars 2. expected = self.instance.linear_map(response) 3. got = [commitment[i] + self.instance.image[i] * challenge for i in range(self.instance.linear_map.num_constraints)] 4. return got == expected 2.2.7. Example: Schnorr proofs The statement represented in Section 2 can be written as: statement = LinearRelation(group) [var_x] = statement.allocate_scalars(1) [var_G, var_X] = statement.allocate_elements(2) statement.append_equation(var_X, [(var_x, var_G)]) At which point it is possible to set var_G and var_X whenever the group elements are at disposal. G = group.generator() statement.set_elements([(var_G, G), (var_X, X)]) It is worth noting that in the above example, [X] == statement.linear_map.map([x]). 2.2.8. Example: DLEQ proofs A DLEQ proof proves a statement: DLEQ(G, H, X, Y) = PoK{(x): X = x * G, Y = x * H} Given group elements G, H and X, Y such that x * G = X and x * H = Y, then the statement is generated as: 1. statement = LinearRelation() 2. [var_x] = statement.allocate_scalars(1) 3. [var_G, var_X, var_H, var_Y] = statement.allocate_elements(4) 4. statement.set_elements([(var_G, G), (var_H, H), (var_X, X), (var_Y, Y)]) 5. statement.append_equation(X, [(var_x, G)]) 6. statement.append_equation(Y, [(var_x, H)]) 2.2.9. Example: Pedersen commitments A representation proof proves a statement REPR(G, H, C) = PoK{(x, r): C = x * G + r * H} Given group elements G, H such that C = x * G + r * H, then the statement is generated as: 1. statement = LinearRelation() 2. var_x, var_r = statement.allocate_scalars(2) 3. [var_G, var_H, var_C] = statement.allocate_elements(3) 4. statement.set_elements([(var_G, G), (var_H, H), (var_C, C)]) 5. statement.append_equation(C, [(var_x, G), (var_r, H)]) 2.3. Ciphersuites We consider ciphersuites of prime-order elliptic curve groups. 2.3.1. P-256 (secp256r1) This ciphersuite uses P-256 [SP800] for the Group. 2.3.1.1. Elliptic curve group of P-256 (secp256r1) [SP800] * order(): Return the integer 115792089210356248762697446949407573529996955224135760342422259061068512044369. * serialize([A]): Implemented using the compressed Elliptic-Curve- Point-to-Octet-String method according to [SEC1]; Ne = 33. * deserialize(buf): Implemented by attempting to read buf into chunks of 33-byte arrays and convert them using the compressed Octet-String-to-Elliptic-Curve-Point method according to [SEC1], and then performs partial public-key validation as defined in section 5.6.2.3.4 of [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. 2.3.1.2. Scalar Field of P-256 * serialize(s): Relies on the Field-Element-to-Octet-String conversion according to [SEC1]; Ns = 32. * deserialize(buf): Reads the byte array buf in chunks of 32 bytes using Octet-String-to-Field-Element from [SEC1]. This function can fail if the input does not represent a Scalar in the range [0, G.Order() - 1]. 3. Security Considerations Interactive Sigma Protocols have the following properties: * *Knowledge soundness*: If the proof is valid, the prover must have knowledge of a secret witness satisfying the proof statement. This property ensures that valid proofs cannot be generated without possession of the corresponding witness. * *Honest verifier zero-knowledge*: The proof string produced by the prove function does not reveal any information beyond what can be directly inferred from the statement itself. This ensures that honest verifiers gain no knowledge about the witness. * *Completeness*: If the statement being proved is true, an honest verifier can be convinced of this fact by an honest prover via the proof. * *Deniable*: Because Interactive Sigma Protocols don't have transferable message authenticity, a third party (not the prover or verifier) cannot be convinced that the prover made the proof. This means that the Sigma Protocol interaction is not transferable as evidence to a third party. 3.1. Privacy Considerations Sigma Protocols are insecure against malicious verifiers and should not be used. The non-interactive Fiat-Shamir transformation leads to publicly verifiable (transferable) proofs that are statistically zero-knowledge. 3.2. Constant-Time Requirements The prover's control flow and memory access patterns are typically influenced by the witness. To prevent side-channel leakage of witness information, which may reveal private values, it is important that the implementation of underlying group and field operations are constant-time. Operations such as modular reduction, scalar multiplication, random value generation, and all other group and field operations are required to be constant-time especially when working with inputs which are private to prevent side-channel attacks which may reveal their values. In some cases, such as keyed- verification credentials, also the verifier must be constant-time. Implementations MUST securely delete prover state as soon as it is no longer needed, and SHOULD minimize the lifetime of sensitive material (witness and instance), explicitly zeroize temporary buffers after proof generation, use secure de-allocation mechanisms when available, and reduce exposure in crash dumps, swap/page files, and diagnostic logging. 4. Post-Quantum Security Considerations The zero-knowledge proofs described in this document provide statistical zero-knowledge and statistical soundness properties when modeled in the random oracle model. 4.1. Privacy Considerations These proofs offer zero-knowledge guarantees, meaning they do not leak any information about the prover's witness beyond what can be inferred from the proven statement itself. This property holds even against quantum adversaries with unbounded computational power. Specifically, these proofs can be used to protect privacy against post-quantum adversaries, in applications demanding: * Post-quantum anonymity * Post-quantum unlinkability * Post-quantum blindness * Protection against "harvest now, decrypt later" attacks. 4.2. Soundness Considerations While the proofs themselves offer privacy protections against quantum adversaries, the hardness of the relation being proven depends (at best) on the hardness of the discrete logarithm problem over the elliptic curves specified in Section 2.3. Since this problem is known to be efficiently solvable by quantum computers using Shor's algorithm, these proofs MUST NOT be relied upon for post-quantum soundness guarantees. Implementations requiring post-quantum soundness SHOULD transition to alternative proof systems such as: * MPC-in-the-Head approaches as described in [GiacomelliMO16] * Lattice-based approaches as described in [AttemaCK21] * Code-based approaches as described in [Stern93] Implementations should consider the timeline for quantum computing advances when planning migration to post-quantum sound alternatives. Implementers MAY adopt a hybrid approach during migration to post- quantum security by using AND composition of proofs. This approach enables gradual migration while maintaining security against classical adversaries. This composition retains soundness if *both* problems remain hard. AND composition of proofs is NOT described in this specification, but examples may be found in the proof-of-concept implementation and in [BonehS23]. 5. Generation of the protocol identifier As of now, it is responsibility of the user to pick a unique protocol identifier that identifies the proof system. This will be expanded in future versions of this specification. 6. Generation of the instance identifier As of now, it is responsibility of the user to pick a unique instance identifier that identifies the statement being proven. Acknowledgments The authors thank Jan Bobolz, Vishruti Ganesh, Stephan Krenn, Mary Maller, Ivan Visconti, Yuwen Zhang for reviewing a previous edition of this specification. References Normative References [KEYAGREEMENT] Barker, E., Chen, L., Roginsky, A., Vassilev, A., and R. Davis, "Recommendation for pair-wise key-establishment schemes using discrete logarithm cryptography", National Institute of Standards and Technology, DOI 10.6028/nist.sp.800-56ar3, April 2018, . Informative References [AttemaCK21] Attema, T., Cramer, R., and L. Kohl, "A Compressed Sigma- Protocol Theory for Lattices", . [BonehS23] Boneh, D. and V. Shoup, "A Graduate Course in Applied Cryptography", n.d., . [Cramer97] Cramer, R., "Modular Design of Secure yet Practical Cryptographic Protocols", 1997, . [CramerDS94] Cramer, R., Damgaard, I., and B. Schoenmakers, "Proofs of Partial Knowledge and Simplified Design of Witness Hiding Protocols", 1994, . [CS97] Camenisch, J. and M. Stadler, "Proof Systems for General Statements about Discrete Logarithms", n.d., . [fiat-shamir] "draft-irtf-cfrg-fiat-shamir", . [FIPS-202] "SHA-3 standard :: permutation-based hash and extendable- output functions", National Institute of Standards and Technology (U.S.), DOI 10.6028/nist.fips.202, 2015, . [FIPS.186-5] "Digital Signature Standard (DSS)", National Institute of Standards and Technology (U.S.), DOI 10.6028/nist.fips.186-5, February 2023, . [GiacomelliMO16] Giacomelli, I., Madsen, J., and C. Orlandi, "ZKBoo: Faster Zero-Knowledge for Boolean Circuits", . [SEC1] Standards for Efficient Cryptography Group (SECG), "SEC 1: Elliptic Curve Cryptography", . [SP800] "Recommendations for Discrete Logarithm-based Cryptography", n.d., . [Stern93] Stern, J., "A New Identification Scheme Based on Syndrome Decoding", 1993, . Appendix A. Test Vectors A.1. Seeded PRNG For interoperability, the random number generator used for test vectors is implemented using the duplex sponge SHAKE128 instantiation in Section 8.1 of [fiat-shamir], absorbing a seed of 32 bytes. The Seeded PRNG is for reproducible test vectors; production implementations MUST use a CSPRNG. Random scalars are generated squeezing Ns + 32 bytes, seen as a big- endian positive integer and reduced modulo p, as in Section 9.1.4 of [fiat-shamir]. class SeededPRNG: def __init__(self, seed: bytes, order: int): assert(len(seed) == 32) self.order = order self.hash_state = SHAKE128(b"sigma-proofs/TestDRNG/SHAKE128".ljust(64, b"\x00")) self.hash_state.absorb(seed) def random_scalar(self) -> Scalar: Ns = (self.order.bit_length() + 7) // 8 random_integer = OS2IP(self.hash_state.squeeze(Ns + 32)) return Scalar(random_integer % self.order) The following sections contain test vectors for the Sigma Protocols specified in this document. The test vectors are grouped by ciphersuite. Each vector includes a Relation field naming the relation being proved and a Ciphersuite field identifying the non-interactive instantiation used to generate the proof bytes. A.2. sigma-proofs(P-256, SHAKE128) This section contains vectors for the ciphersuite identified as sigma-proofs_Shake128_P256. A.3. discrete_logarithm Relation = discrete_logarithm Ciphersuite = sigma-proofs_Shake128_P256 SessionId = 64697363726574655f6c6f6761726974686d Statement = 0100000001000000010000000000000000000000036b17d1f2e12c42 47f8bce6e563a440f277037d812deb33a0f4a13945d898c29602d135e66a8b8d656f a8e892501d931895ec031701a72aa550039742a8f6325336 Witness = daca1508279cce9abb7fdefc540ec4b9bcf1b689bbcf74ea3123dbd3f5 b611b0 Proof = d08bc0386f6ef8b3a431d490a1b30c0ab58341043aa76e59b74493417e65 a46ee9488aaa9b728b9ccd5231f1d99daae697e454d67d83522e5bc8de52324f06bd Batchable Proof = 031af107806a9d4f14c569d5a255904f682a7e1cc289ca70f5 306d690609bf8f7231ffdce808d01c2ee9354c49c3dcbe6361cce35b81c304abd3a8 13909ec3c16a A.4. dleq Relation = dleq Ciphersuite = sigma-proofs_Shake128_P256 SessionId = 646c6571 Statement = 02000000010000000100000000000000000000000300000001000000 0000000002000000036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4 a13945d898c29602e7747263366b618a771a284e6139947b17e9c3a96cb573d045db 511336fea2b502d135e66a8b8d656fa8e892501d931895ec031701a72aa550039742 a8f632533603c2170432aefa48cbbe91aa5be0da997e663528c96bd5652da0b71dbc 44b4a157 Witness = 92526b41ae23f4820a911c9ba1bdc6493f68ce123871c76a6e74ec43b8 5494c0 Proof = 8e9bd4ddb4c4cf342c4b29e9cb6447d1ed7268cbea7bd163408925c6058f 1e9a32b29cb837a982782e771e90665cceaae4c2051cd2f9de70a57b5661ae9b4cf4 Batchable Proof = 031af107806a9d4f14c569d5a255904f682a7e1cc289ca70f5 306d690609bf8f7202b9e055385e773efed02af727e2ac21b9dc411ede1789a3186a b779e32c3ebec3fa58b127a6ea224395244ee5a0fc4ed0e99b9e576a7d6bc132e052 47bcb658a0 A.5. pedersen_commitment Relation = pedersen_commitment Ciphersuite = sigma-proofs_Shake128_P256 SessionId = 706564657273656e5f636f6d6d69746d656e74 Statement = 01000000020000000200000000000000000000000100000001000000 036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29602 d135e66a8b8d656fa8e892501d931895ec031701a72aa550039742a8f6325336033f 5eec2203e5d6cf13564a3884637cba8d6a835edfe1e7127ed544efa734f33c Witness = 92526b41ae23f4820a911c9ba1bdc6493f68ce123871c76a6e74ec43b8 5494c0c93640008f20c1c7e267c16a7acef56ce53605f763e94cca43be52e7ad2607 64 Proof = 03c2fed5978acc3cf8aaa0ca27ba0f8c594f0f30d54fd480c984c7af1627 de1c15d44da987f02c4d9e0fa01f081efa719e8cc778338faa04134017481924f06d c3ee6f245c56bb20aaf97dea5380e09594b7d5d0dce38496e976d2d1a84893f5 Batchable Proof = 022b3a82ba319b6bb06e1c0df02639fabff6644f03737a6a31 29a080abbcbb994279dc23d43310f40de3d3e3a5567dfd74c5c87e7ecb8fae1e0617 2cfd9d4246eedadbce5fef61c99fc3cea903adfee9d8311943966a63ebc3abbe9556 6c2094f6 A.6. pedersen_commitment_dleq Relation = pedersen_commitment_dleq Ciphersuite = sigma-proofs_Shake128_P256 SessionId = 706564657273656e5f636f6d6d69746d656e745f646c6571 Statement = 02000000020000000200000000000000000000000100000001000000 05000000020000000000000003000000010000000400000002d135e66a8b8d656fa8 e892501d931895ec031701a72aa550039742a8f632533602e7747263366b618a771a 284e6139947b17e9c3a96cb573d045db511336fea2b503494cd0367a7478312233f9 a9645d2f3f9a68dcfe018d052325c4431b4dc4f78c032aaafb5d7a5a3dd1bad36f58 0cde19e8995a7a0c0cb79bc4f736b832de95320803dfcb42c94940e5ac6c5ffbabfb b9a8da0132e0db8f414d8bdd01f5ae8fa2143103052d1bd120487fa37744c6da3295 f56e76be9c61a4de8a0b0c6c5de177935482 Witness = 5be9cc0de93d47ccaf8637f1c5a9e26e92b5bc38f6265a96d64bd437ac 7d597ab6116295a8d23d4cd60fb53b1ddf7177f95aee639a59dacecf37334a914bde d6 Proof = 131348247c1d6c7b66402a0c5ed4a47af55e37b44c12b7ab0103c00440f9 773ddcf334188a910e111c0cf81a1ce25ac13ecdd7dbc8228a93d6f698a87af9d5f5 8d7b568fbb121a9f81fe2534d2f24a942a81e8daa08f48b09ea773befef5e8f0 Batchable Proof = 0384afaabfca8df99914b58ac83c1f16cc0871c95167c672b4 0f8b79eac10193ae021ebe92eec53b568bc65b0e6bddf3c9ca159fd493690dd28c60 a12fa672e163e205ef3af821437ddfd0eb080d0e1babdff75437c1004cc6273164f0 352850b73238701b45d0ee56d1be5359f5a25a81acf3f4942bb05f724a8f6713075c fe8b89 A.7. bbs_blind_commitment_computation Relation = bbs_blind_commitment_computation Ciphersuite = sigma-proofs_Shake128_P256 SessionId = 6262735f626c696e645f636f6d6d69746d656e745f636f6d70757461 74696f6e Statement = 01000000040000000400000000000000000000000100000001000000 0200000002000000030000000300000002d135e66a8b8d656fa8e892501d931895ec 031701a72aa550039742a8f632533602e7747263366b618a771a284e6139947b17e9 c3a96cb573d045db511336fea2b5032aaafb5d7a5a3dd1bad36f580cde19e8995a7a 0c0cb79bc4f736b832de95320803dfcb42c94940e5ac6c5ffbabfbb9a8da0132e0db 8f414d8bdd01f5ae8fa21431024a243b6f8a0030941fde57d57f1a4d418d01e7f398 962739fba3bbdb3adfb285 Witness = 895007d818e8c20774be15273e5b8733e345ba359205cbcd98a046f263 a7a0ce5be9cc0de93d47ccaf8637f1c5a9e26e92b5bc38f6265a96d64bd437ac7d59 7ab6116295a8d23d4cd60fb53b1ddf7177f95aee639a59dacecf37334a914bded6c6 038561954f5b4d4052c77d8c149a74767e1c478e09dc33e7cfc801f7dfb722 Proof = cc8e3072ee8c305b8409d01a25902d928692d4d29a56655e416afe30efbd 97f8b7a3141b009229ea5ebb3e15b8771bbc1317cf125feb902e151a7d29ce254e60 ad390b486329d18430e684ef46863524e8be301d21832b2a5dd070a6443070eeb292 e90a3808fae2e56417693f4023387e698b2cb2d41f2ffa2551d4124da40bbb343026 17a8bf67c7e0b6c73fce3697b15c1c2ef49f4991c27873f0b70a602d Batchable Proof = 038b7263580bb33a66bf5b1c1d4dcadce46e89fd58c6224df2 c495e4d8447ee24b3caa3feab0ebaa85847f3d2161dccbd22947cdf33ebf5ca0793e 31e193b024e1f672cf51e471b286e3161e1dd18f0448cd42d3d8f30e813a6c2f2ccb 6a5eb6ce4cb3bc0043639723e6aa48541a4172ab4ebd36e7f7a85aecbf1de4dcc649 ff84147c4041813146e03e18d6f916a5b54633a0f68cca2153bc6d7f91bed9c6e351 A.8. sigma-proofs(BLS12-381, SHAKE128) This section contains vectors for the ciphersuite identified as sigma-proofs_Shake128_BLS12381. A.9. discrete_logarithm Relation = discrete_logarithm Ciphersuite = sigma-proofs_Shake128_BLS12381 SessionId = 64697363726574655f6c6f6761726974686d Statement = 010000000100000001000000000000000000000097f1d3a73197d794 2695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3a f00adb22c6bb81f56ff90504e08e3af0211b8b60d8a834af3bd7a63eb6d3a1e1f974 4fdbf915697ecb8a6ebd7d4db0885bedc2e02c8b Witness = 722df275e5be8df73fe322083a661a5a02910bae74f5d3674b648af813 81cab0 Proof = 2d07db2a46daeb32ba019194b4e6f9319f9eae259c1e80c15f71f3db1d9c 4c5f25d92eb0743a8f3cd004b59cead8f325563c8d23d265cc2d35f596ea86a32816 Batchable Proof = 876bd688db9e4d0c1501d5f80ceb865958d1699998cd226a42 22a6826370702cceb6c966d61f1d80e3f8b7faef5b158b152c7865932f0b73c2f002 c299dbc778a3f587e34d9943410b2d46536a5b8bc7 A.10. dleq Relation = dleq Ciphersuite = sigma-proofs_Shake128_BLS12381 SessionId = 646c6571 Statement = 02000000010000000100000000000000000000000300000001000000 000000000200000097f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e 3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb8cc0db261e028e0d81676c78 5dfd7d71976753c7ec9fb9166abfb6b262aaa36cfbde771460b70b06d2b4ab2f4faf 878d81f56ff90504e08e3af0211b8b60d8a834af3bd7a63eb6d3a1e1f9744fdbf915 697ecb8a6ebd7d4db0885bedc2e02c8bac83f5e8bc97f38b92d976067b1532f89442 0a74c549bf25026bb9067a5b5ba43293b7ba272180ade19c81d451e76012 Witness = 301dc6e2a7f14746146a2c281e2922cacda7c5613e26c72b3d57e06fa6 7831e0 Proof = 2bc9e1e80d3b14e2214a2792e7bf30162763cffe655238bfdce1196f3906 81481d4148ec767e3ca5ddb1a05efaf377a82dca623e863aa45af5caf58091a2fd92 Batchable Proof = 876bd688db9e4d0c1501d5f80ceb865958d1699998cd226a42 22a6826370702cceb6c966d61f1d80e3f8b7faef5b158b824c14d32ad86a34761314 bf3f2f46ed9f993a86b48cf9adc076153a736da4b0670bfa7263ab81c435dee0186a 721f5d465ff84606c95efa8a22d01d24c64f179d31d044164e2c90ae2122e796a161 41 A.11. pedersen_commitment Relation = pedersen_commitment Ciphersuite = sigma-proofs_Shake128_BLS12381 SessionId = 706564657273656e5f636f6d6d69746d656e74 Statement = 01000000020000000200000000000000000000000100000001000000 97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55 e83ff97a1aeffb3af00adb22c6bb81f56ff90504e08e3af0211b8b60d8a834af3bd7 a63eb6d3a1e1f9744fdbf915697ecb8a6ebd7d4db0885bedc2e02c8bb29e444ccc3f 9ca21049e8188ccbaf50995c2b0b44c8ec93c742afc29b5ad90baff8a133baf318ee a626df9b29b05995 Witness = 301dc6e2a7f14746146a2c281e2922cacda7c5613e26c72b3d57e06fa6 7831e00e46ec1da3e35fc11a2b91b272794ea40c6e283930e5cc981c7bd61f661726 84 Proof = 237aa321c1827aad548ecdbdf4f8e7f14baf24f2ba8a53d7d2304bc9d804 25ee222da47223c980f9008467c12054795a8601b3ad4ec566c777463775cdfe8805 3d825e17a65875d352e3e68a2d8825ba4a31a60ea4e4a8e8e622e93afb0de9a9 Batchable Proof = a97bc242710165e97eb80d556d66ee25c239b3e4d55e4e5e7b 43963139b57dab95931f3dac353b486e2bd3a9b26a184c3faec15beca7733326c654 6122d6ca2465d01dc17ccf4f6fe2cc588bc5e201c734106878cb40e65c921322e877 e965dee872ca106b7187556a5c13a15dc1ea14 A.12. pedersen_commitment_dleq Relation = pedersen_commitment_dleq Ciphersuite = sigma-proofs_Shake128_BLS12381 SessionId = 706564657273656e5f636f6d6d69746d656e745f646c6571 Statement = 02000000020000000200000000000000000000000100000001000000 05000000020000000000000003000000010000000400000081f56ff90504e08e3af0 211b8b60d8a834af3bd7a63eb6d3a1e1f9744fdbf915697ecb8a6ebd7d4db0885bed c2e02c8b8cc0db261e028e0d81676c785dfd7d71976753c7ec9fb9166abfb6b262aa a36cfbde771460b70b06d2b4ab2f4faf878dae12bff9e60b2ba88bd9da69c55948d0 a6cdbffcce0379a3becbdd57c6aa17e858cf10f722f1c67c710541be9e1d2204a207 735523e9de213a4a84dde81c26e9291763c585e152b791f96f1d710dd0e981c6d7d9 d96a2bc42a057bd6bbaefd71aa75899f88793c24e526c90da736e3df71b358ac6d09 0a7fb10f421782eb062bf0400ea8ffacf3e0fff87130e8e9def594186d3501350830 da852e4ad460ec8ecb5868891df413d34972699f0b8005388c45c0d51de9b05b7be0 050f26c8e7fa Witness = 48b922ab24da7d352e8184ffce98dd1513eea0a7c175193769b0b30464 ca30ba3217d0a0a623bb652283dda5c6aada76d14dd2a7b1461105a6f67e31946b4b b6 Proof = 39e79064f980cfc9aeb953e5cd2ec2ac5a6abdbcb3ead98ece20becf7c32 75450e0b27a75216e4cb4a8975f5b8ab0492a9a98a9b6ebb79713ea8a7a277572b94 0a05027cb65354e5b92dd32d15d2b96fe89748a1a1149b7d979d3e5c645c67ff Batchable Proof = a3ccd50dcb1fea6b89c83bcd6add352ad3db4eda268236a906 b41f59e3edde60b7a69ba7501d91176fdf08f5a21caef88a8fa7f9f44caa78674efd 2660f0d3327195e1f39421bf57fa0dc2874ccfc68e220f2b3bc5bdf71ef144743725 68616f6709b5b7e02b88f9cf5ead9cb5969d496adeac334584300cc86258a8e205c8 d61e506c8bbf56ff7815149b61a6f5e892bf14befbb9e3bdf49d9d230edcdb146b A.13. bbs_blind_commitment_computation Relation = bbs_blind_commitment_computation Ciphersuite = sigma-proofs_Shake128_BLS12381 SessionId = 6262735f626c696e645f636f6d6d69746d656e745f636f6d70757461 74696f6e Statement = 01000000040000000400000000000000000000000100000001000000 0200000002000000030000000300000081f56ff90504e08e3af0211b8b60d8a834af 3bd7a63eb6d3a1e1f9744fdbf915697ecb8a6ebd7d4db0885bedc2e02c8b8cc0db26 1e028e0d81676c785dfd7d71976753c7ec9fb9166abfb6b262aaa36cfbde771460b7 0b06d2b4ab2f4faf878da207735523e9de213a4a84dde81c26e9291763c585e152b7 91f96f1d710dd0e981c6d7d9d96a2bc42a057bd6bbaefd71aa75899f88793c24e526 c90da736e3df71b358ac6d090a7fb10f421782eb062bf0400ea8ffacf3e0fff87130 e8e9def58494d8275db37296859ea24febe40bed9520bb30277e8356ab2fe9528708 3154cc5a191de3f2d4d90fe865265e782785 Witness = 0b77611f0ec1f6ed026d6d5cc02e1c8e0966b4fafb7796107174acb071 78b36e48b922ab24da7d352e8184ffce98dd1513eea0a7c175193769b0b30464ca30 ba3217d0a0a623bb652283dda5c6aada76d14dd2a7b1461105a6f67e31946b4bb63e fe086aa913df787d02e2852da1c6eb900166c3987a32b85d46dba8a9cc09d2 Proof = 2b07fb2441b85dba5410c1a549ea03e3761cfff54d1e50239ff35a1e165b 4fa45c9ab831dde8b3ef217f629bda0acdff0c8630ca6319734101c008752a6bd17e 4d96e5aaba6b85696aebcc8b0d0b374d933f13e8a911a26dbb238b1b8bf66e3a23b1 5bbf3b08a20df3aed9c2e49529048d89d8757dc1b8d9262589302e4f0498718453a1 b683616c84d753b90f3f58946c40198255829672115f17b704097ae6 Batchable Proof = 8cdacd8de18dde04c58140d873b590b0f8aeaac32889909d15 5fb0723f3859742f6cb39189186de355426704d42a6c314733d3fa2d439ff72bd2cc b9650efb8a62f61345f03a9ade2a8249a75fb816ec2d07797d80e4375c0ef748d22f f4f130f1eb623da121fb4a549621bd61ea8c0d415b884e537733abddbc93992da4e4 52017e388af29cdca8850d516aba4b5de5033cd8b8dab06a6d68c30191fec014daef a27a6aeecdc7024e7cedfe74ef74ff Authors' Addresses Michele OrrĂ¹ CNRS Email: m@orru.net Cathie Yun Apple, Inc. Email: cathieyun@gmail.com