def test_and_proof_same_environment(params): p1, p2, secrets_dict = params and_proof = AndProofStmt(p1, p2) prover = and_proof.get_prover(secrets_dict) verifier = and_proof.get_verifier() assert verify(verifier, prover)
def test_and_proof_different_environments(params): x, y = Secret(), Secret() p1, p2, secrets_dict = params and_proof = AndProofStmt(p1, p2) prover = and_proof.get_prover(secrets_dict) verifier = and_proof.get_verifier() assert verify(verifier, prover)
def construct_stmt(self, precommitment): r""" Proof of knowledge of a signature. This is an implementation of a proof :math:`\Pi_5` detailed on page 7 of the `Constant-Size Dynamick-TAA` paper. """ self.A1, self.A2 = precommitment["A1"], precommitment["A2"] g0, g1, g2 = self.bases[0], self.bases[1], self.bases[2] dl1 = DLRep(self.A1, self.r1 * g1 + self.r2 * g2) dl2 = DLRep( g0.group.infinite(), self.delta1 * g1 + self.delta2 * g2 + self.secret_vars[0] * (-1 * self.A1), ) self.pair_lhs = self.A2.pair(self.pk.w) + (-1 * self.pk.gen_pairs[0]) bases = [ -1 * (self.A2.pair(self.pk.h0)), self.bases[2].pair(self.pk.w), self.pk.gen_pairs[2], ] bases.extend(self.pk.gen_pairs[1 : len(self.bases)]) # Build secret names [e, r1, delta1, s, m_i] new_secret_vars = ( self.secret_vars[:1] + [self.r1, self.delta1] + self.secret_vars[1:] ) pairings_stmt = DLRep(self.pair_lhs, wsum_secrets(new_secret_vars, bases)) constructed_stmt = AndProofStmt(dl1, dl2, pairings_stmt) constructed_stmt.lhs = [p.lhs for p in constructed_stmt.subproofs] return constructed_stmt
def test_and_proof_fails_when_secret_is_wrong(params, group): p1, p2, secrets_dict = params and_proof = AndProofStmt(p1, p2) sec = secrets_dict.copy() u = list(sec.keys()) sec[u[0]] = group.order().random() prover = and_proof.get_prover(sec) verifier = and_proof.get_verifier() assert not verify(verifier, prover)
def test_and_proof_non_interactive_fails_when_wrong_secrets(params, group): p1, p2, secrets = params andp = AndProofStmt(p1, p2) bad_secrets = secrets.copy() u = list(bad_secrets.keys()) bad_secrets[u[0]] = group.order().random() message = "whatever" tr = andp.prove(bad_secrets, message=message) assert not andp.verify(tr, message=message)
def test_and_proof_simulation_2(group): n = 3 secret_values = [Bn(i) for i in range(n)] secrets = [Secret() for _ in range(n)] generators = make_generators(n, group) lhs = group.wsum(secret_values, generators) subproof1 = DLRep(lhs, wsum_secrets(secrets, generators)) subproof2 = DLRep(lhs, wsum_secrets(secrets, generators)) andp = AndProofStmt(subproof1, subproof2) tr = andp.simulate() assert andp.verify_simulation_consistency(tr) assert not andp.verify(tr)
def test_compose_and_proofs_2(params): p1, p2, secrets_dict = params p3 = AndProofStmt(p1, p2) p = AndProofStmt(AndProofStmt(p1, AndProofStmt(p3, AndProofStmt(p1, p2))), p2) prover = p.get_prover(secrets_dict) verifier = p.get_verifier() assert verify(verifier, prover)
def test_and_proof_simulation_1(group): n = 3 secret_values = [Bn(i) for i in range(n)] secrets = [Secret() for _ in range(n)] generators = make_generators(n, group) lhs = group.wsum(secret_values, generators) subproof1 = DLRep(lhs, wsum_secrets(secrets, generators)) subproof2 = DLRep(lhs, wsum_secrets(secrets, generators)) andp = AndProofStmt(subproof1, subproof2) andv = andp.get_verifier() tr = andp.simulate_proof() tr.stmt_hash = andp.prehash_statement().digest() assert not andv.verify_nizk(tr)
def test_or_and_dlrne(): secrets, secret_values, secret_dict = get_secrets(4) generators = make_generators(4) lhs_values = [x * g for x, g in zip(secret_values, generators)] y3 = secret_values[2] * generators[3] p1 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=True, ) p2 = DLNotEqual([lhs_values[1], generators[1]], [y3, generators[3]], secrets[1], bind=True) andp_nested = AndProofStmt(p1, p2) orp = OrProofStmt(andp_nested, p1, p2) prov = orp.get_prover(secret_dict) ver = orp.get_verifier() precom = prov.precommit() ver.process_precommitment(precom) com = prov.commit() chal = ver.send_challenge(com) resp = prov.compute_response(chal) assert ver.verify(resp)
def construct_stmt(self, precommitment): """ Construct the internal proof statement. """ if self.is_prover: # Indicators that tell us which or-clause is true actual_value = ensure_bn(self.x.value) value_as_bits = decompose_into_n_bits(actual_value, self.num_bits) zero_simulated = [b == 1 for b in value_as_bits] one_simulated = [b == 0 for b in value_as_bits] bit_proofs = [] for i in range(self.num_bits): p0 = DLRep(precommitment["Cs"][i], self.randomizers[i] * self.h) p1 = DLRep(precommitment["Cs"][i] - self.g, self.randomizers[i] * self.h) # When we are a prover, mark which disjunct is true if self.is_prover: p0.set_simulated(zero_simulated[i]) p1.set_simulated(one_simulated[i]) bit_proofs.append(p0 | p1) return AndProofStmt(*bit_proofs)
def test_and_proof_fails_when_bases_belong_to_different_groups(group): """ An alien EcPt is inserted in the generators """ g1 = group.generator() other_group = EcGroup(706) assert group != other_group g2 = other_group.generator() x = Secret(value=Bn(42)) y1 = group.wsum([x.value], [g1]) y2 = other_group.wsum([x.value], [g2]) p1 = DLRep(y1, wsum_secrets([x], [g1])) p2 = DLRep(y2, wsum_secrets([x], [g2])) and_proof = AndProofStmt(p1, p2) prover = and_proof.get_prover() verifier = and_proof.get_verifier() # An exception should be raised because of a shared secrets linked to two different groups with pytest.raises(GroupMismatchError): verify(verifier, prover)
def test_malicious_and_proofs(): x0 = Secret() x2 = Secret() x1 = Secret() generators = make_generators(3) g1 = generators[0] g2 = generators[1] g3 = generators[2] secret_dict = {x0: 3, x2: 50, x1: 12} mal_secret_dict = {x0: 3, x2: 51} andp = AndProofStmt( DLRep(12 * g1 + 50 * g2, x1 * g1 + x2 * g2), DLRep(3 * g3 + 51 * g2, x0 * g1 + x2 * g2), ) prov = andp.get_prover(secret_dict) prov.subs[1].secret_values = mal_secret_dict verif = andp.get_verifier() com = prov.commit() chal = verif.send_challenge(com) resp = prov.compute_response(chal) with pytest.raises(ValidationError): verif.verify(resp)
def test_or_and_proof_composition(params): p1, p2, secrets = params andp = AndProofStmt(p1, p2) g1 = 7 * p1.bases[0] g2 = 8 * p1.bases[0] xb = Secret(name="xb") xa = Secret(name="xa") p0 = DLRep(7 * g1 + 18 * g2, xb * g1 + xa * g2) secrets[xa] = 7 secrets[Secret(name="xc")] = 18 orproof = OrProofStmt(p0, andp) prover = orproof.get_prover(secrets) verifier = orproof.get_verifier() assert verify(verifier, prover)
def construct_stmt(self, precommitment): """ Build the internal proof statement. See the formula in Protocol 1 of the `Thinking Inside the BLAC Box: Smarter Protocols for Faster Anonymous Blacklisting` paper. """ infty = self.g.group.infinite() p1 = DLRep(infty, self.alpha * self.g + self.beta * self.lhs[0]) p2 = DLRep(precommitment, self.alpha * self.h + self.beta * self.lhs[1]) statements = [p1, p2] if self.bind: # If the binding parameter is set, we add a DLRep member repeating # the first member without randomizing the secret. statements.append(DLRep(self.lhs[0], self.x * self.g)) return AndProofStmt(*statements)
def test_and_or_proof_composition(params): p1, p2, secrets = params g1 = 7 * p1.bases[0] g2 = 8 * p1.bases[0] xb = Secret(name="xb") xa = Secret(name="xa") p0 = DLRep(7 * g1 + 18 * g2, xb * g1 + xa * g2) secrets[xb] = 7 secrets[xa] = 18 orproof = OrProofStmt(p1, p2) andp = AndProofStmt(orproof, p0) andp = AndProofStmt(andp, DLRep(15 * p1.bases[0], Secret(value=15) * p1.bases[0])) prover = andp.get_prover(secrets) verifier = andp.get_verifier() assert verify(verifier, prover)
# Set up the proof statement. # First, compute the values, "left-hand side". y1 = 4 * g0 + 5 * g1 y2 = 4 * g2 + 7 * g3 # Next, create the proof statement. stmt = DLRep(y1, x0 * g0 + x1 * g1) \ & DLRep(y2, x0 * g2 + x2 * g3) # This is an equivalent way to create the proof statement above. stmt_1 = DLRep(y1, x0 * g0 + x1 * g1) stmt_2 = DLRep(y2, x0 * g2 + x2 * g3) equivalent_stmt = AndProofStmt(stmt_1, stmt_2) assert stmt.get_proof_id() == equivalent_stmt.get_proof_id() # Simulate the prover and verifier interacting. prover = stmt.get_prover({x0: 4, x1: 5, x2: 7}) verifier = stmt.get_verifier() commitment = prover.commit() challenge = verifier.send_challenge(commitment) response = prover.compute_response(challenge) assert verifier.verify(response) # Composition takes into account re-occuring secrets.
def test_and_proof_non_interactive(params): p1, p2, secrets = params p = AndProofStmt(p1, p2) message = "whatever" tr = p.prove(secrets, message=message) assert p.verify(tr, message=message)
def test_multiple_and_proofs(params): p1, p2, secrets_dict = params and_proof = AndProofStmt(p1, p2, p2, p1, p1, p1, p2) prover = and_proof.get_prover(secrets_dict) verifier = and_proof.get_verifier() assert verify(verifier, prover)