Core API

zksk.expr – DL Expressions

Tiny expression language suitable for expressing statements on discrete logarithm representations

>>> from petlib.ec import EcGroup
>>> group = EcGroup()
>>> g = group.hash_to_point(b"1")
>>> h = group.hash_to_point(b"2")
>>> a = Secret()
>>> b = Secret()
>>> expr = a * g + b * h
class zksk.expr.Expression(secret, base)

Arithmetic expression of secrets and group elements.

It is an abstraction for \(x_0 g_0 + x_1 g_2 + ... + x_n g_n\), where \(x_i\)-s are declared secrets.

Implementation-wise, parses the sum into an ordered list of Secrets and an ordered list of generators.

Parameters
  • secret (Secret) – Secret object.

  • base – Base point on an elliptic curve.

__add__(other)

Merge Expression objects along addition.

Parameters

other (Expression) – Another expression

Returns

New expression

Return type

Expression

eval()

Evaluate the expression, if all secret values are available.

class zksk.expr.Secret(value=None, name=None)

A secret value in a zero-knowledge proof.

Args

name: String to enforce as name of the Secret. Useful for debugging. value: Optional secret value.

__eq__(other)

Return self==value.

__hash__()

Return hash(self).

__mul__(base)

Construct an expression that represents this secrets multiplied by the base.

Parameters

base – Base point on an elliptic curve.

Returns

Expression that corresponds to \(x G\)

Return type

Expression

__rmul__(base)

Construct an expression that represents this secrets multiplied by the base.

Parameters

base – Base point on an elliptic curve.

Returns

Expression that corresponds to \(x G\)

Return type

Expression

zksk.expr.update_secret_values(secrets_dict)

Update values of secrets according to the given mapping.

>>> x, y = Secret(), Secret()
>>> secrets_dict = {x: 1, y: 2}
>>> update_secret_values(secrets_dict)
>>> x.value
1
>>> y.value
2
Parameters

secrets_dict – A mapping from Secret objects to their expected values.

zksk.expr.wsum_secrets(secrets, bases)

Build expression representing a dot product of given secrets and bases.

>>> from zksk.utils import make_generators
>>> x, y = Secret(), Secret()
>>> g, h = make_generators(2)
>>> expr = wsum_secrets([x, y], [g, h])
>>> expr.bases == (g, h)
True
>>> expr.secrets == (x, y)
True
Parameters
  • secretsSecret objects :math`x_i`

  • bases – Elliptic curve points \(G_i\)

Returns

Expression that corresponds to \(x_0 G_0 + x_1 G_1 + ... + x_n G_n\)

Return type

Expression

zksk.base – Base Classes

Common clases, including subclassable basic provers and verifiers.

class zksk.base.NIZK(challenge, responses, precommitment=None, stmt_hash=None)

Non-interactive zero-knowledge proof.

classmethod deserialize(nizk_raw)

Deserialize a non-interactive zero-knowledge proof.

serialize()

Serialize a non-interactive zero-knowledge proof.

class zksk.base.Prover(stmt, secret_values)

Abstract interface representing Prover used in sigma protocols.

Parameters
  • stmt – The Proof instance from which we draw the Prover.

  • secret_values – The values of the secrets as a dict.

commit(randomizers_dict=None)

Constuct the proof commitment.

Parameters

randomizers_dict – Optional dictionary of random values. Each random values is assigned to a secret.

abstract compute_response(challenge)

Computes the responses associated to each Secret object in the statement.

Returns a list of responses.

get_nizk_proof(message='')

Construct a non-interactive proof transcript using Fiat-Shamir heuristic.

The transcript contains only the challenge and the responses, as the commitment can be deterministically recomputed.

The challenge is a hash of the commitment, the stmt statement and all the bases in the statement (including the left-hand-side).

Parameters

message (str) – Optional message to make a signature stmt of knowledge.

precommit()

Generate a precommitment.

class zksk.base.SimulationTranscript(commitment, challenge, responses, precommitment=None, stmt_hash=None)

Simulated proof transcript.

class zksk.base.Verifier(stmt)

An abstract interface representing Prover used in sigma protocols

abstract check_responses_consistency(response, response_dict=None)

Verify that for two identical secrets, the responses are also the same.

process_precommitment(precommitment)

Receive a precommitment and process it.

send_challenge(commitment)

Store the received commitment and generate a challenge.

The challenge is chosen at random between 0 and CHALLENGE_LENGTH (excluded).

Parameters

commitment – A tuple containing a hash of the stmt statement, to be compared against the local statement, and the commmitment as a (potentially multi-level list of) base(s) of the group.

verify(response, *args, **kwargs)

Verify the responses of an interactive sigma protocol.

To do so, generates a pseudo-commitment based on the stored challenge and the received responses, and compares it against the stored commitment.

Parameters

response – The response given by the prover

Returns

True if verification succeeded, False otherwise.

Return type

bool

verify_nizk(nizk, message='', *args, **kwargs)

Verify a non-interactive proof.

Unpacks the attributes and checks their consistency by computing a pseudo-commitment and drawing from a pseudo-challenge. Compares the pseudo-challenge with the nizk challenge.

Parameters
  • nizk (NIZK) – Non-interactive proof

  • message – A message if a signature proof.

Returns

True of verification succeeded, False otherwise.

Return type

bool

zksk.base.build_fiat_shamir_challenge(stmt_prehash, *args, message='')

Generate a Fiat-Shamir challenge.

>>> prehash = sha256(b"statement id")
>>> commitment = 42 * EcGroup().generator()
>>> isinstance(build_fiat_shamir_challenge(prehash, commitment), Bn)
True
Parameters
  • prehash – Hash object seeded with the proof statement ID.

  • args – Items to hash (e.g., commitments)

  • message – Message to make it a signature PK.

zksk.composition – Compositions

Composable proof statements, provers, and verifiers.

class zksk.composition.AndProofStmt(*subproofs)
get_prover(secrets_dict=None)

Get the base.Prover for the current proof.

get_randomizers()

Create a dictionary of randomizers by querying the subproofs’ maps and merging them.

get_verifier()

Constructs a Verifier for the and-proof, based on a list of the Verifiers of each subproof.

prepare_simulate_proof()

Additional steps to prepare before simulating the proof. Override if needed.

recompute_commitment(challenge, responses)

Compute a pseudo-commitment.

A pseudo-commitment is the commitment a verifier should have received if the proof was correct. It should be compared to the actual commitment.

Re-occuring secrets yield identical responses.

Parameters
  • challenge – the challenge used in the proof

  • response – a list of responses, ordered as the list of secret names, i.e., with as many elements as there are secrets in the proof claim.

simulate_proof(responses_dict=None, challenge=None)

Simulate the And proof

To do so, draw a global challenge, a global dictionary of responses (for consistency) and simulate each subproof.

Gathers the commitments, and pack everything into a base.SimulationTranscript.

Parameters
  • responses_dict – A dictionary of responses to override (could come from an upper And Proof, for example). Draw randomly if None.

  • challenge – The challenge to use in the proof. Draw one if None.

validate_composition(*args, **kwargs)

Validate that composition is done correctly.

validate_secrets_reoccurence(forbidden_secrets=None)

Check re-occuring secrets both inside and outside an or-proof.

This method gets the list of all secrets in the tree and triggers a depth-first search for or-proofs

Parameters

forbidden_secrets – A list of all the secrets in the mother proof.

Raises

exceptions.InvalidSecretsError – If any secrets re-occur in an unsupported way.

class zksk.composition.AndProver(proof, subprovers)
compute_response(challenge)

Return a list of responses of each subprover.

internal_commit(randomizers_dict=None)

Compute the internal commitment.

Parameters

randomizers_dict – Mapping from secrets to randomizers.

precommit()

Computes the precommitment for an and-proof.

This precommitment is the list of precommitments of the subprovers.

If not applicable (no subprover outputs a precommitment), returns None.

class zksk.composition.AndVerifier(proof, subverifiers)
check_responses_consistency(responses, responses_dict=None)

Check that the responses are consistent for re-occurring secret names.

Iterates through the subverifiers, gives them the responses related to them and constructs a response dictionary. If an inconsistency if found during this build, returns False.

Parameters
  • responses – Rreceived list of responses for each subproof.

  • responses_dict – Dictionary to construct and use for comparison.

process_precommitment(precommitment)

Distribute the list of precommitments to the subverifiers.

send_challenge(commitment, ignore_statement_hash_checks=False)

Store the received commitment and generate a challenge.

Additionally checks the received hashed statement matches the one of the current proof. Only called at the highest level or in extended proofs.

Parameters
  • commitment – A tuple (statement, actual_commitment) with actual_commitment a list of commitments, one for each subproof.

  • ignore_statement_hash_checks – Optional parameter to deactivate the statement check. In this case, the commitment parameter is simply the actual commitment. Useful in 2-level proofs for which we don’t check the inner statements.

class zksk.composition.ComposableProofStmt

A composable sigma-protocol proof statement.

In the composed proof tree, these objects are the atoms/leafs.

__and__(other)

Make a conjuction of proof statements using AndProofStmt.

If called multiple times, subproofs are flattened so that only one AndProofStmt remains at the root.

__or__(other)

Make a disjunction of proof statements using OrProofStmt.

If called multiple times, subproofs are flattened so that only one OrProofStmt remains at the root.

check_statement(statement_hash)

Verify the current proof corresponds to the hash passed as a parameter.

Returns a pre-hash of the current proof, e.g., to be used to verify NIZK proofs.

full_validate(*args, **kwargs)

For or/and-proofs, perform recursive validation of subproofs.

get_bases()

Collect all base points in this subtree.

By default tries to get the bases attribute. Override if needed.

get_proof_id(secret_id_map=None)

Identifier for the proof statement.

This identifier is used to check the proof statements on the prover and verifier sides are consistent, and to generate a challenge in non-interactive proofs.

Parameters

secret_id_map – A map from secret names to consecutive identifiers.

Returns

Objects that can be used for hashing.

Return type

list

get_prover(secrets_dict=None)

Get the base.Prover for the current proof.

get_secret_vars()

Collect all secrets in this subtree.

By default tries to get the secret_vars attribute. Override if needed.

get_verifier()

Return the base.Verifier for the current proof.

prehash_statement()

Return a hash of the proof’s ID.

prepare_simulate_proof()

Additional steps to prepare before simulating the proof. Override if needed.

prove(secret_dict=None, message='')

Generate the transcript of a non-interactive proof.

recompute_commitment(challenge, response)

Compute a pseudo-commitment.

A pseudo-commitment is the commitment a verifier should have received if the proof was correct. It should be compared to the actual commitment.

Re-occuring secrets yield identical responses.

Parameters
  • challenge – the challenge used in the proof

  • response – a list of responses, ordered as the list of secret names, i.e., with as many elements as there are secrets in the proof claim.

set_simulated(value=True)

Designate this proof statement as simulated in an or-proof.

Parameters

value (bool) – Whether to simulate this proof.

simulate(challenge=None)

Generate the transcript of a simulated non-interactive proof.

property simulated

Tell if this proof is designated as to be simulated in an or-proof.

By default is False.

update_randomizers(randomizers_dict)

Construct a mapping of all secrets to randomizers.

Does so by copying the values of the passed randomizers_dict, and drawing the other values at random until all the secrets have a randomizer.

These are used as a part of proofs and also as responses in simulations.

Parameters

randomizers_dict – A dictionary to enforce

validate(*args, **kwargs)

Validation criteria to be checked. Override if needed.

For example, a primitives.DLNotEqual statement should not validate if its proof components are in fact equal.

Should raise an exceptions.ValidationError if does not validate.

validate_secrets_reoccurence(forbidden_secrets=None)

Check if a secret appears both inside an outside an or-proof.

Does nothing if not overriden.

verify(nizk, message='')

Verify a non-interactive proof.

verify_simulation_consistency(transcript)

Check if the fields of a transcript satisfy the verification equation.

Useful for debugging purposes.

Warning

This is NOT an alternative to the full proof verification, as this function accepts simulated proofs.

class zksk.composition.OrProofStmt(*subproofs)

An disjunction of several subproofs.

Parameters

suproofs – Proof statements.

Raise:

ValueError: If less than two subproofs given.

get_prover(secrets_dict=None)

Get the base.Prover for the current proof.

get_verifier()

Return the base.Verifier for the current proof.

prepare_simulate_proof()

Additional steps to prepare before simulating the proof. Override if needed.

recompute_commitment(challenge, responses)

Compute a pseudo-commitment.

A pseudo-commitment is the commitment a verifier should have received if the proof was correct. It should be compared to the actual commitment.

Re-occuring secrets yield identical responses.

Parameters
  • challenge – the challenge used in the proof

  • response – a list of responses, ordered as the list of secret names, i.e., with as many elements as there are secrets in the proof claim.

validate_composition()

Validate that composition is done correctly.

validate_secrets_reoccurence(forbidden_secrets=None)

Check for re-occurence of secrets both inside and outside an or-proof.

Method is called from AndProofStmt.validate_secrets_reoccurence().

Parameters

forbidden_secrets – A list of all the secrets in the mother proof.

Raises

exceptions.InvalidSecretsError – If any secrets re-occur in an unsupported way.

class zksk.composition.OrProver(stmt, subprover)

Prover for the or-proof.

This prover is built with only one subprover, and needs to have access to the index of the corresponding subproof in its mother proof. Runs all the simulations for the other proofs and stores them.

compute_response(challenge)

Compute complementary challenges and responses.

Computes the complementary challenge with respect to the received global challenge and the list of challenges used in the stored simulations. Computes the responses of the subprover using this auxiliary challenge, gathers the responses from the stored simulations. Returns both the complete list of subchallenges (including the auxiliary challenge) and the list of responses, both ordered.

Parameters

challenge – The global challenge to use. All subchallenges must add to this one.

internal_commit(randomizers_dict=None)

Gather the commitments from the stored simulations.

Parameters

randomizers_dict – A dictionary of randomizers to use for responses consistency. Not used in this proof. Parameter kept so all internal_commit methods have the same prototype.

precommit()

Generate a precommitment.

setup_simulations()

Run all the required simulations and stores them.

class zksk.composition.OrVerifier(stmt, subverifiers)

Verifier for the or-proof.

The verifier is built on a list of subverifiers, which will unpack the received attributes.

check_responses_consistency(responses, responses_dict=None)

Checks that for a same secret, response are actually the same.

Since every member is run with its own challenge, it is enough that one member is consistent within itself.

Parameters

responses – a tuple (subchallenges, actual_responses) from which we extract only the actual responses for each subverifier.

process_precommitment(precommitment)

Reads the received list of precommitments (or None if non applicable) and distributes them to the subverifiers so they can finalize their proof construction if necessary.

Parameters

precommitment – A list of all required precommitments, ordered.

zksk.extended – Extended Proofs

Extended proofs are proofs that deal with internal precommitments.

This is a convenient building block that is useful for defining complex primitives.

Precommitments are parameters that are not known at the proof instantiation time and are computed by the proving side. Therefore, they have to be sent explicitly in a preliminary round for interactive protocols, and as an additional attribute in non-interactive or simulated transcripts.

The protocol of an extended proof is as follows:

  1. A proof statement (ExtendedProofStmt) is instantiated and its attributes are set, but cannot run most methods.

  2. Upon processing of the precommitment (ExtendedProofProver.process_precommitment()), a separate and complete regular proof statement (zksk.base.ComposableProofStmt) is constructed inside the extended proof (:py:attr`ExtendedProofStmt.constructed_stmt`)

  3. ExtendedProofStmt.get_bases(), ExtendedProofStmt.get_secret_vars() delegate to the internal constructed_stmt. The ExtendedProver and ExtendedVerifier work in the same way, embedding a constructed_prover (resp., constructed_verifier).

class zksk.extended.ExtendedProofStmt

Proof that deals with precommitments.

abstract construct_stmt()

Build internal proof statement for this class

This function must be overridden. The function should return a constructed proof statement. It can use the values that were computed by internal_precommit to do so.

full_validate(*args, **kwargs)

For or/and-proofs, perform recursive validation of subproofs.

get_bases()

Collect all base points in this subtree.

By default tries to get the bases attribute. Override if needed.

get_proof_id(secret_id_map=None)

Identifier for the proof statement.

get_prover(secrets_dict=None)

Get a prover object.

Returns

Prover object if all secret values are known, None otherwise.

get_secret_vars()

Collect all secrets in this subtree.

By default tries to get the secret_vars attribute. Override if needed.

precommit()

Compute precommitments. Override if needed.

Override this function to compute precommitments and set corresponding secrets that must be computed before the ZK proof itself can be constructed and proven.

Returns

Precommitment

prepare_simulate_proof()

Additional steps to prepare before simulating the proof. Override if needed.

recompute_commitment(challenge, responses)

Compute a pseudo-commitment.

A pseudo-commitment is the commitment a verifier should have received if the proof was correct. It should be compared to the actual commitment.

Re-occuring secrets yield identical responses.

Parameters
  • challenge – the challenge used in the proof

  • response – a list of responses, ordered as the list of secret names, i.e., with as many elements as there are secrets in the proof claim.

simulate_precommit()

Simulate a precommitment. Override if needed.

Override this method to enable using this proof in or-proofs.

It should compute the same output as generated by precommit, but without relying on any secrets.

simulate_proof(responses_dict=None, challenge=None)

Simulate the proof.

Parameters
  • responses_dict – Mapping from secrets to responses

  • challenge – Challenge

validate(precommitment, *args, **kwargs)

Validate proof’s construction. Override if needed.

class zksk.extended.ExtendedProver(stmt, secret_values)

Prover dealing with precommitments.

This prover will create a constructed Prover object and delegate to its methods.

compute_response(challenge)

Wrap the response computation for the inner proof.

internal_commit(randomizers_dict=None)

Trigger the internal prover commit.

Transfers the randomizer_dict if passed. It might be used if the binding of the proof is set True.

precommit()

Generate a precommitment.

process_precommitment()

Trigger the inner-proof construction and extract a prover given the secrets.

class zksk.extended.ExtendedVerifier(stmt)

Verifier that deals with precommitments.

check_responses_consistency(responses, responses_dict)

Wrap the consistency check of the innter proof.

process_precommitment(precommitment)

Receive the precommitment and trigger the inner-verifier construction.

send_challenge(com)

Transfer the commitment to the inner proof, and compute the challenge.

zksk.pairings – Pairings

Wrapper around bplib points that ensures additive notation for all points.

class zksk.pairings.AdditivePoint(pt, bp)

A wrapper for GT points that uses additive notation.

Parameters
__add__(other)

Replace the multiplicative syntax between two points by an additive one.

__eq__(other)

Return self==value.

__mul__(nb)

Overrides the multiplicative syntax by an additive one.

Special case in 0 as the underlying bplib function is broken for this value.

__rmul__(nb)

Overrides the multiplicative syntax by an additive one.

Special case in 0 as the underlying bplib function is broken for this value.

class zksk.pairings.BilinearGroupPair(bp_group=None)

A bilinear group pair.

Contains two origin groups G1, G2 and the image group GT. The underlying bplib.bp.BpGroup object is also embedded.

groups()

Returns the three groups in the following order : G1, G2, GT.

class zksk.pairings.G1Group(bp)

Wrapper for G1 that behaves like normal petlib.ec.EcGroup.

Parameters

bp (BilinearGroupPair) – Group pair.

__eq__(other)

Return self==value.

class zksk.pairings.G1Point(pt, bp)

Wrapper for G1 points so they can be paired with a G2 point.

Parameters
__eq__(other)

Return self==value.

class zksk.pairings.G2Group(bp)

Wrapper for the G2 group.

Parameters

bp (BilinearGroupPair) – Group pair.

class zksk.pairings.G2Point(pt, bp)

Wrapper for G2 points.

Parameters
__eq__(other)

Return self==value.

class zksk.pairings.GTGroup(bp)

Wrapper for the GT group with additive points.

Allows to retrieve groups G1 and G2.

The group ID is set to 0 to allow comparisons between groups of different types to raise an explicit Exception.

Parameters

bp (BilinearGroupPair) – Group pair.

zksk.pairings.pt_dec(bptype, xtype)

Decoder for the wrapped points.

zksk.pairings.pt_enc(obj)

Encoder for the wrapped points.

zksk.exceptions – Built-in Exceptions

Common exception classes.

exception zksk.exceptions.GroupMismatchError

Generator groups mismatch.

exception zksk.exceptions.IncompleteValuesError

Cannot evaluate a proof as not all secret values are set.

exception zksk.exceptions.InconsistentChallengeError

Recomputed and global challenge values do not match.

exception zksk.exceptions.InvalidExpression
exception zksk.exceptions.InvalidSecretsError

Secrets re-occur in an unsupported manner.

exception zksk.exceptions.StatementMismatch

Proof statements mismatch, impossible to verify.

exception zksk.exceptions.StatementSpecError

Statement not fully specified.

exception zksk.exceptions.ValidationError

Error during validation.

exception zksk.exceptions.VerificationError

Error during verification.

zksk.utils – Utilities

zksk.utils.groups – Utils for Elliptic Curves and Big Numbers

zksk.utils.groups.ensure_bn(x)

Ensure that value is big number.

>>> isinstance(ensure_bn(42), Bn)
True
>>> isinstance(ensure_bn(Bn(42)), Bn)
True
zksk.utils.groups.get_random_num(bits)

Draw a random number of given bitlength.

>>> x = get_random_num(6)
>>> x < 2**6
True
zksk.utils.groups.get_random_point(group=None, random_bits=256, seed=None)

Generate some random group generators.

Parameters
  • num – Number of generators to generate.

  • group – Group

  • random_bits – Number of bits of a random string to create a point.

>>> from petlib.ec import EcPt
>>> a = get_random_point()
>>> b = get_random_point()
>>> isinstance(a, EcPt)
True
>>> isinstance(b, EcPt)
True
>>> a != b
True
>>> get_random_point(seed=1)
EcPt(037697679766c26bb7b76c65d2639fb983dea7c859c63b3047168dbc1b)
zksk.utils.groups.make_generators(num, group=None, random_bits=256, seed=42)

Create some random group generators.

Warning

There is a negligible chance that some generators will be the same.

Parameters
  • num – Number of generators to generate.

  • group – Group

  • random_bits – Number of bits of a random number used to create a generator.

>>> from petlib.ec import EcPt
>>> generators = make_generators(3)
>>> len(generators) == 3
True
>>> isinstance(generators[0], EcPt)
True
zksk.utils.groups.sum_bn_array(arr, modulus)

Sum an array of big numbers under a modulus.

>>> a = [Bn(5), Bn(7)]
>>> m = 10
>>> sum_bn_array(a, m)
2

zksk.utils.misc – Miscellany

zksk.utils.misc.get_default_attr(obj, attr, default_value=None)

Get attribute by name. If does not exist, set it.

>>> class Klass: pass
>>> a = Klass()
>>> hasattr(a, "answer")
False
>>> get_default_attr(a, "answer", 42)
42
>>> a.answer
42