def params(group): n1 = 3 n2 = 4 generators1 = make_generators(n1) generators2 = make_generators(n2) x0 = Secret() x1 = Secret() x2 = Secret() x3 = Secret() x4 = Secret() x5 = Secret() secrets = [x0, x1, x2, x3, x4, x5] secrets_dict = dict([ (x0, Bn(1)), (x1, Bn(2)), (x2, Bn(5)), (x3, Bn(100)), (x4, Bn(43)), (x5, Bn(10)), ]) sum_1 = group.wsum([secrets_dict[x0], secrets_dict[x1], secrets_dict[x2]], generators1) secrets_2 = [secrets_dict[x0]] for i in range(3, 6): secrets_2.append(secrets_dict[secrets[i]]) sum_2 = group.wsum(secrets_2, generators2) p1 = DLRep(sum_1, wsum_secrets([x0, x1, x2], generators1)) p2 = DLRep(sum_2, wsum_secrets([x0, x3, x4, x5], generators2)) return p1, p2, secrets_dict
def test_statement_zk_proof() -> None: vm = sy.VirtualMachine() client = vm.get_root_client() sy.load("zksk") # third party from zksk import DLRep from zksk import Secret from zksk import utils num = 2 seed = 42 num_sy = sy.lib.python.Int(num) seed_sy = sy.lib.python.Int(seed) # Setup: Peggy and Victor agree on two group generators. G, H = utils.make_generators(num=num, seed=seed) # Setup: generate a secret randomizer. r = Secret(utils.get_random_num(bits=128)) # This is Peggy's secret bit. top_secret_bit = 1 # A Pedersen commitment to the secret bit. C = top_secret_bit * G + r.value * H # Peggy's definition of the proof statement, and proof generation. # (The first or-clause corresponds to the secret value 0, and the second to the value 1. Because # the real value of the bit is 1, the clause that corresponds to zero is marked as simulated.) stmt = DLRep(C, r * H, simulated=True) | DLRep(C - G, r * H) zk_proof = stmt.prove() # send over the network and get back num_ptr = num_sy.send(client) seed_prt = seed_sy.send(client) c_ptr = C.send(client) zk_proof_ptr = zk_proof.send(client) num2 = num_ptr.get().upcast() seed2 = seed_prt.get().upcast() C2 = c_ptr.get() zk_proof2 = zk_proof_ptr.get() # Setup: get the agreed group generators. G, H = utils.make_generators(num=num2, seed=seed2) # Setup: define a randomizer with an unknown value. r = Secret() stmt = DLRep(C2, r * H) | DLRep(C2 - G, r * H) assert stmt.verify(zk_proof2)
def test_and_dlrne_binding_1(): secrets, secret_values, secret_dict = get_secrets(4) generators = make_generators(4) lhs_values = [x * g for x, g in zip(secret_values, generators)] p1 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=True, ) p2 = DLRep(lhs_values[0], secrets[0] * generators[0]) andp = p1 & p2 p1_prime = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=True, ) p2_prime = DLRep(lhs_values[0], Secret(name=secrets[0].name) * generators[0]) andp_prime = p1_prime & p2_prime protocol = SigmaProtocol(andp_prime.get_verifier(), andp.get_prover(secret_dict)) assert protocol.verify()
def test_and_dlrne_does_not_fail_on_same_dl_when_not_binding(): """ Prove (H0 = h0*x, H1 != h1*x), H2 = h2*x with same secret name x. Should not be detected as binding is off by default. """ 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] s0 = secrets[0] p1 = DLNotEqual([lhs_values[0], generators[0]], [lhs_values[1], generators[1]], s0) p2 = DLRep(lhs_values[2], s0 * generators[2]) andp = p1 & p2 s0_prime = Secret(name=secrets[0].name) p1_prime = DLNotEqual([lhs_values[0], generators[0]], [lhs_values[1], generators[1]], s0_prime) p2_prime = DLRep(lhs_values[2], s0_prime * generators[2]) andp_prime = p1_prime & p2_prime prov = andp.get_prover(secret_dict) prov.subs[1].secret_values[s0] = secret_values[2] protocol = SigmaProtocol(andp_prime.get_verifier(), prov) assert protocol.verify()
def test_and_dlrep_partial_binding(): """ Claim to use (H0 = h0*x, H1 != h1*x) , (H1 = h1*x, H3 != h3*x) with the same x (not only cheating, a contradiction). Should be undetected as binding is off in at least one proof """ secrets = get_secrets_new(4) generators = make_generators(4) lhs_values = [x.value * g for x, g in zip(secrets, generators)] y3 = secrets[2].value * generators[3] p1 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=False, ) p2 = DLNotEqual([lhs_values[1], generators[1]], [y3, generators[3]], secrets[1], bind=True) andp = p1 & p2 sprime = Secret() p1_prime = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], sprime, bind=False, ) p2_prime = DLNotEqual([lhs_values[1], generators[1]], [y3, generators[3]], sprime, bind=True) andp_prime = p1_prime & p2_prime protocol = SigmaProtocol(andp_prime.get_verifier(), andp.get_prover()) assert protocol.verify()
def test_bbsplus_and_range(): from zksk.primitives.rangeproof import RangeStmt from zksk.utils import make_generators mG = BilinearGroupPair() keypair = BBSPlusKeypair.generate(mG, 9) pk, sk = keypair.pk, keypair.sk generators, h0 = keypair.generators, keypair.h0 creator = BBSPlusSignatureCreator(pk) msg_val = Bn(30) lhs = creator.commit([msg_val]) presignature = sk.sign(lhs.com_message) signature = creator.obtain_signature(presignature) e, s, m = Secret(signature.e), Secret(signature.s), Secret(msg_val) p1 = BBSPlusSignatureStmt([e, s, m], pk, signature) g, h = make_generators(2, mG.G1) randomizer = Secret(value=mG.G1.order().random()) com = m * g + randomizer * h p2 = RangeStmt(com.eval(), g, h, 18, 9999, m, randomizer) stmt = p1 & p2 proof = stmt.prove() assert stmt.verify(proof)
def test_multiple_dlrne_simulation(): secrets, secret_values, secret_dict = get_secrets(4) generators = make_generators(4) lhs_values = [x * g for x, g in zip(secret_values, generators)] p1 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=False, ) p2 = DLRep(lhs_values[2], secrets[2] * generators[2]) p3 = DLNotEqual( [lhs_values[2], generators[2]], [lhs_values[1], generators[1]], secrets[2], bind=True, ) p4 = DLNotEqual( [lhs_values[1], generators[1]], [lhs_values[3], generators[3]], secrets[0], bind=True, ) andp = p1 & p2 & p3 & p4 tr = andp.simulate() assert andp.verify_simulation_consistency(tr) assert not andp.verify(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 test_dlrep_non_interactive_1(group): g, h = make_generators(2, group) expr = Secret(value=3) * g + Secret(value=4) * h p = DLRep(expr.eval(), expr) tr = p.prove() prover = p.get_prover() assert p.verify(tr)
def test_and_dlrne_fails_on_same_dl(): """ Second subproof is not correct as the two members have the same DL """ 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[1] * 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]) andp = p1 & p2 p1_prime = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=True, ) p2_prime = DLNotEqual([lhs_values[1], generators[1]], [y3, generators[3]], secrets[1]) andp_prime = p1_prime & p2_prime protocol = SigmaProtocol(andp_prime.get_verifier(), andp.get_prover(secret_dict)) with pytest.raises(ValidationError): protocol.verify()
def test_expr_repr(group, num): secrets = [Secret() for _ in range(num)] generators = make_generators(num, group) expr = wsum_secrets(secrets, generators) expected_repr = " + ".join("Expression({}, {})".format(x, g) for x, g in zip(secrets, generators)) assert expected_repr == repr(expr)
def test_dlrep_non_interactive_with_message(group): g, h = make_generators(2, group) expr = Secret(value=3) * g + Secret(value=4) * h p = DLRep(expr.eval(), expr) tr = p.prove(message="mymessage") assert DLRep(expr.eval(), expr).verify(tr, message="mymessage")
def test_dlrep_simulation(group): g, h = make_generators(2, group=group) x, y = Secret(value=3), Secret(value=4) expr = x * g + y * h p = DLRep(expr.eval(), expr) tr = p.simulate() assert (not p.verify(tr)) and p.verify_simulation_consistency(tr)
def test_multiple_and_dlrep_fails_on_bad_secret_when_binding(): secrets, secret_values, secret_dict = get_secrets(4) generators = make_generators(4) lhs_values = [x * g for x, g in zip(secret_values, generators)] p1 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=True, ) p2 = DLRep(lhs_values[0], secrets[0] * generators[0]) p3 = DLNotEqual( [lhs_values[2], generators[2]], [lhs_values[1], generators[1]], secrets[2], bind=True, ) p4 = DLNotEqual( [lhs_values[1], generators[1]], [lhs_values[3], generators[3]], secrets[0], bind=True, ) andp = p1 & p2 & p3 & p4 p11 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=True, ) p21 = DLRep(lhs_values[0], secrets[0] * generators[0]) p31 = DLNotEqual( [lhs_values[2], generators[2]], [lhs_values[1], generators[1]], secrets[2], bind=True, ) p41 = DLNotEqual( [lhs_values[1], generators[1]], [lhs_values[3], generators[3]], secrets[0], bind=True, ) andp1 = p11 & p21 & p31 & p41 prov = andp.get_prover(secret_dict) prov.subs[1].secret_values[secrets[0]] = secret_values[1] protocol = SigmaProtocol(andp1.get_verifier(), prov) with pytest.raises(ValidationError): protocol.verify()
def test_and_proof_partially_defined_secrets(): generators = make_generators(2) x = Secret(value=4) x2 = Secret() p1 = DLRep(4 * generators[0], x * generators[0]) p2 = DLRep(3 * generators[1], x2 * generators[1]) andp = p1 & p2 tr = andp.prove({x2: 3}) assert andp.verify(tr)
def test_dlrep_interactive_2(group): g, h = make_generators(2, group) x, y = Secret(), Secret() p = DLRep(10 * g + 15 * h, x * g + y * h) prover = p.get_prover({x: 10, y: 15}) verifier = p.get_verifier() protocol = SigmaProtocol(verifier, prover) assert protocol.verify()
def test_same_random_values_in_commitments(group): (g, ) = make_generators(1, group) generators = [g, g, g] pub = group.wsum([Bn(100), Bn(100), Bn(100)], generators) x = Secret() p = DLRep(pub, wsum_secrets([x, x, x], generators)) prover = p.get_prover({x: 100}) commitments = prover.commit()
def test_dlrep_bad_hash(group): g, h = make_generators(2, group=group) x, y = Secret(), Secret() secret_dict = {x: 2, y: 3} p1 = DLRep(2 * g + 3 * h, x * g + y * h) p2 = DLRep(2 * g + 3 * h, y * h + x * g) tr = p1.prove(secret_dict) assert p1.verify(tr) with pytest.raises(StatementMismatch): p2.verify(tr)
def test_range_stmt_non_interactive_outside_range(group): x = Secret(value=15) randomizer = Secret(value=group.order().random()) g, h = make_generators(2, group) lo = 7 hi = 15 com = x * g + randomizer * h with pytest.warns(UserWarning): stmt = RangeStmt(com.eval(), g, h, lo, hi, x, randomizer)
def test_get_many_different_provers(group, num): generators = make_generators(num, group) secrets = [Secret(name="secret_%i" % i) for i in range(num)] secrets_vals = [Bn(i) for i in range(num)] secret_dict = {secret: val for secret, val in zip(secrets, secrets_vals)} p = DLRep(group.wsum(secrets_vals, generators), wsum_secrets(secrets, generators)) prover = p.get_prover(secret_dict) _, commitment = prover.commit() assert isinstance(commitment, EcPt)
def test_dlrep_wrong_response_non_interactive(group): g, h = make_generators(2, group=group) x, y = Secret(value=3), Secret(value=4) expr = x * g + y * h p = DLRep(expr.eval(), expr) tr = p.prove(message="mymessage") # Turn one of the responses random tr.responses[1] = group.order().random() assert not p.verify(tr, message="mymessage")
def test_dlrep_wrong_public_elements(group): g, h = make_generators(2, group=group) x, y = Secret(value=3), Secret(value=4) expr = x * g + y * h public_wrong = get_random_point() p = DLRep(public_wrong, expr) prover = p.get_prover() verifier = p.get_verifier() protocol = SigmaProtocol(verifier, prover) assert not protocol.verify()
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_diff_groups_dlrep(group): g, h = make_generators(2, group) x, y = Secret(), Secret() # Precondition for the test. other_group = EcGroup(706) assert other_group != group, "Test assumption is broken." h = other_group.generator() expr = x * g + y * h z = get_random_point(group) with pytest.raises(InvalidExpression): p = DLRep(z, expr)
def test_invalid_or_composition(): r = Secret(10) g1, g2, g3 = make_generators(3) st1 = DLRep(10 * g1, r * g1) st21 = DLRep(10 * g2, r * g2) st22 = DLRep(12 * g3, r * g3) st22.set_simulated() st2 = st21 | st22 st = st1 & st2 with pytest.raises(InvalidSecretsError): st.prove()
def test_range_stmt_non_interactive_start_at_zero(group): x = Secret(value=3) randomizer = Secret(value=group.order().random()) g, h = make_generators(2, group) lo = 0 hi = 5 com = x * g + randomizer * h stmt = RangeStmt(com.eval(), g, h, lo, hi, x, randomizer) tr = stmt.prove() assert stmt.verify(tr)
def test_range_proof_outside(): group = EcGroup() x = Secret(value=15) randomizer = Secret(value=group.order().random()) g, h = make_generators(2, group) lo = 0 hi = 14 com = x * g + randomizer * h with pytest.raises(Exception): stmt = RangeStmt(com.eval(), g, h, lo, hi, x, randomizer) nizk = stmt.prove() stmt.verify(nizk)
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_multiple_and_dlrep_binding(): secrets = get_secrets_new(4) generators = make_generators(4) lhs_values = [x.value * g for x, g in zip(secrets, generators)] p1 = DLNotEqual( [lhs_values[0], generators[0]], [lhs_values[1], generators[1]], secrets[0], bind=False, ) p2 = DLRep(lhs_values[2], secrets[2] * generators[2]) p3 = DLNotEqual( [lhs_values[2], generators[2]], [lhs_values[1], generators[1]], secrets[2], bind=True, ) p4 = DLNotEqual( [lhs_values[1], generators[1]], [lhs_values[3], generators[3]], secrets[1], bind=True, ) andp = p1 & p2 & p3 & p4 s0 = Secret() s2 = Secret() p1prime = DLNotEqual([lhs_values[0], generators[0]], [lhs_values[1], generators[1]], s0, bind=False) p2prime = DLRep(lhs_values[2], s2 * generators[2]) p3prime = DLNotEqual([lhs_values[2], generators[2]], [lhs_values[1], generators[1]], s2, bind=True) # Note difference: p4prime binds s0 instead of secrets[1] in the original proof p4prime = DLNotEqual([lhs_values[1], generators[1]], [lhs_values[3], generators[3]], s0, bind=True) andp1 = p1prime & p2prime & p3prime & p4prime protocol = SigmaProtocol(andp1.get_verifier(), andp.get_prover()) assert protocol.verify()
def test_generators_sharing_a_secret(group, num): generators = make_generators(num, group) unique_secret = 4 x = Secret() secret_vals = [Bn(unique_secret) for _ in range(num)] lhs = group.wsum(secret_vals, generators) rhs = wsum_secrets([x] * num, generators) p = DLRep(lhs, rhs) prover = p.get_prover({x: unique_secret}) assert isinstance(prover, DLRepProver) _, commitment = prover.commit() assert isinstance(commitment, EcPt)