Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
def test_signature_non_interactive_proof():
    mG = BilinearGroupPair()
    keypair = BBSPlusKeypair.generate(mG, 9)
    messages = [Bn(30), Bn(31), Bn(32)]

    pk, sk = keypair.pk, keypair.sk
    generators, h0 = keypair.generators, keypair.h0

    creator = BBSPlusSignatureCreator(pk)
    lhs = creator.commit(messages)
    presignature = sk.sign(lhs.com_message)
    signature = creator.obtain_signature(presignature)
    e, s, m1, m2, m3 = (Secret() for _ in range(5))
    secret_dict = {
        e: signature.e,
        s: signature.s,
        m1: messages[0],
        m2: messages[1],
        m3: messages[2],
    }

    p1 = BBSPlusSignatureStmt([e, s, m1, m2, m3], pk, signature)
    tr = p1.prove(secret_dict)
    p1 = BBSPlusSignatureStmt([Secret() for _ in range(5)], pk)
    assert p1.verify(tr)
Exemplo n.º 4
0
def test_signature_proof():
    mG = BilinearGroupPair()
    keypair = BBSPlusKeypair.generate(mG, 9)
    messages = [Bn(30), Bn(31), Bn(32)]

    pk, sk = keypair.pk, keypair.sk
    generators, h0 = keypair.generators, keypair.h0

    creator = BBSPlusSignatureCreator(pk)
    lhs = creator.commit(messages)
    presignature = sk.sign(lhs.com_message)
    signature = creator.obtain_signature(presignature)
    e, s, m1, m2, m3 = (Secret() for _ in range(5))
    secret_dict = {
        e: signature.e,
        s: signature.s,
        m1: messages[0],
        m2: messages[1],
        m3: messages[2],
    }

    p1 = BBSPlusSignatureStmt([e, s, m1, m2, m3], pk, signature)
    prover = p1.get_prover(secret_dict)
    p2 = BBSPlusSignatureStmt([Secret() for _ in range(5)], pk)
    verifier = p2.get_verifier()
    pc = prover.precommit()
    verifier.process_precommitment(pc)
    com = prover.commit()
    chal = verifier.send_challenge(com)
    resp = prover.compute_response(chal)
    assert verifier.verify(resp)
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)
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
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_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)
Exemplo n.º 9
0
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()
Exemplo n.º 10
0
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)
Exemplo n.º 11
0
def test_dlne_non_interactive_2(group):
    g = group.generator()
    x = Secret(value=3)
    y = 3 * g
    y2 = 397474 * g
    g2 = 1397 * g

    p1 = DLNotEqual([y, g], [y2, g2], x, bind=True)
    tr = p1.prove()
    p2 = DLNotEqual([y, g], [y2, g2], Secret(), bind=True)
    assert p2.verify(tr)
Exemplo n.º 12
0
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)
Exemplo n.º 13
0
def test_dlrep_wrong_secrets(group):
    g = group.generator()
    g1 = 2 * g
    g2 = 5 * g
    x1 = Secret()
    x2 = Secret()
    p = DLRep(g, x1 * g1 + x2 * g2)
    prover = p.get_prover({x1: 10, x2: 15})
    verifier = p.get_verifier()

    protocol = SigmaProtocol(verifier, prover)
    assert not protocol.verify()
Exemplo n.º 14
0
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()
Exemplo n.º 15
0
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_and_proof_with_complex_expression(group):
    g = group.generator()
    g1 = 2 * g
    g2 = 5 * g
    g3 = 10 * g
    x1 = Secret()
    x2 = Secret()
    x3 = Secret()
    proof = DLRep(10 * g1 + 15 * g2, x1 * g1 + x2 * g2) & DLRep(
        15 * g1 + 35 * g3, x2 * g1 + x3 * g3)
    prover = proof.get_prover({x1: 10, x2: 15, x3: 35})
    verifier = proof.get_verifier()
    assert verify(verifier, prover)
Exemplo n.º 17
0
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)
Exemplo n.º 18
0
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)
Exemplo n.º 19
0
def test_signature_and_dlrne_fails_on_wrong_secret():
    """
    We manually modify a secret in the DLNE member, i.e we wrongfully claim to use the same "s" i the
    signature and in the DLNE.
    Should be detected and raise an Exception.
    """
    mG = BilinearGroupPair()
    keypair = BBSPlusKeypair.generate(mG, 9)
    messages = [Bn(30), Bn(31), Bn(32)]
    pk, sk = keypair.pk, keypair.sk
    generators, h0 = keypair.generators, keypair.h0

    creator = BBSPlusSignatureCreator(pk)
    lhs = creator.commit(messages)
    presignature = sk.sign(lhs.com_message)
    signature = creator.obtain_signature(presignature)
    e, s, m1, m2, m3 = (Secret() for _ in range(5))
    secret_dict = {
        e: signature.e,
        s: signature.s,
        m1: messages[0],
        m2: messages[1],
        m3: messages[2],
    }

    sigproof = BBSPlusSignatureStmt([e, s, m1, m2, m3], pk, signature)

    g1 = mG.G1.generator()
    pg1 = signature.s * g1
    pg2, g2 = mG.G1.order().random() * g1, mG.G1.order().random() * g1
    dneq = DLNotEqual((pg1, g1), (pg2, g2), s, bind=True)

    secrets = [Secret() for _ in range(5)]
    sigproof1 = BBSPlusSignatureStmt(secrets, pk, signature)
    dneq1 = DLNotEqual((pg1, g1), (pg2, g2), secrets[1], bind=True)

    andp = sigproof & dneq
    andp1 = sigproof1 & dneq1
    prov = andp.get_prover(secret_dict)

    prov.subs[1].secret_values[s] = signature.s + 1
    ver = andp1.get_verifier()

    ver.process_precommitment(prov.precommit())

    commitment = prov.commit()

    challenge = ver.send_challenge(commitment)
    responses = prov.compute_response(challenge)
    with pytest.raises(ValidationError):
        ver.verify(responses)
Exemplo n.º 20
0
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)
Exemplo n.º 21
0
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)
Exemplo n.º 22
0
def test_signature_and_dlrne_does_not_fail_on_wrong_secret_when_non_binding():
    """
    Manually modify a secret in the DLNE member, i.e we wrongfully claim to use the same "s" i the
    signature and in the DLNE.  Should not be detected since bindings in the DLNE are False.
    """

    mG = BilinearGroupPair()
    keypair = BBSPlusKeypair.generate(mG, 9)
    messages = [Bn(30), Bn(31), Bn(32)]
    pk, sk = keypair.pk, keypair.sk
    generators, h0 = keypair.generators, keypair.h0

    creator = BBSPlusSignatureCreator(pk)
    lhs = creator.commit(messages)
    presignature = sk.sign(lhs.com_message)
    signature = creator.obtain_signature(presignature)
    e, s, m1, m2, m3 = (Secret() for _ in range(5))
    secret_dict = {
        e: signature.e,
        s: signature.s,
        m1: messages[0],
        m2: messages[1],
        m3: messages[2],
    }
    sigproof = BBSPlusSignatureStmt([e, s, m1, m2, m3], pk, signature)

    g1 = mG.G1.generator()
    pg1 = signature.s * g1 + g1
    pg2, g2 = mG.G1.order().random() * g1, mG.G1.order().random() * g1
    splus = Secret(signature.s + 1)
    dneq = DLNotEqual((pg1, g1), (pg2, g2), splus, bind=False)

    secrets = [Secret() for _ in range(5)]
    sigproof1 = BBSPlusSignatureStmt(secrets, pk, signature)
    # Note difference: dneq above uses an independent secret for dneq,
    # here it is bound to the secret s (secrets[1]) from the signature proof
    dneq1 = DLNotEqual((pg1, g1), (pg2, g2), secrets[1])

    andp = sigproof & dneq
    andp1 = sigproof1 & dneq1
    prov = andp.get_prover(secret_dict)

    ver = andp1.get_verifier()
    ver.process_precommitment(prov.precommit())
    commitment = prov.commit()

    challenge = ver.send_challenge(commitment)
    responses = prov.compute_response(challenge)
    assert ver.verify(responses)
Exemplo n.º 23
0
    def blind_commit(self, raw_values, blindness_rand=None, h_rand=None):
        """"a blind commitment to values.

        Arguments blindness_rand and h_rand enable ACL compatability. 

        Args:
            raw_values (Bn mod q/string/bytes []): committed values.
            blindness_rand (Bn mod q): forces the blinding's randomness. (optional)
            h_rand (Bn): fix the randomness for H. (optional)
        Raises:
            Error: bad value encoding. values can only be Bn, bytes, or string.
            Error: blindness generator is unknown

        Returns:
            BlPedersenCommitment: commitment
            BlPedersenPrivate: commitment's values and randomness
        """

        values = [self.process_raw_value(raw) for raw in raw_values]

        if len(values) > len(self.HS):
            self.expand_params_len(len(values))

        rand = self.q.random()
        rand_2 = self.q.random()
        if h_rand is not None:
            rand = h_rand
        if blindness_rand is None:
            blindness_rand = self.q.random()

        C = rand * self.H + rand_2 * self.H_2
        C += self.group.wsum(values, self.HS[:len(values)])

        bl_commit = blindness_rand * C
        bl_z = blindness_rand * self.Z

        bcommit = BlPedersenCommitment(bl_z=bl_z, bl_commit=bl_commit)
        bpriv = BlPedersenPrivate(
            param=self,
            raw_values=raw_values,
            values=[
                Secret(val, name=f"val_{i}") for (i, val) in enumerate(values)
            ],
            rand=Secret(rand, name="rand"),
            rand_2=Secret(rand_2, name="rand_2"),
            blindness_rand=Secret(blindness_rand, name="blindness_rand"),
        )

        return (bcommit, bpriv)
Exemplo n.º 24
0
    def verify_proof(self, bc_param, bproof):
        """Verify a PedersenProof for this commitment.
        Important: besides verifying the proof, you should verify the parameters.

        Args:
            bc_param (BlPedersenParam): commitment parameters
            bproof (BlPedersenProof): a nizk proof for self
        Returns:
            boolean: pass/fail
        """

        if bc_param.get_param_num() < len(bproof.bl_hi):
            bc_param.expand_params_len(len(bproof.bl_hi))
        bl_rand_sec = Secret(name="blindness_rand")

        # randomness
        expr_bl_z = bl_rand_sec * bc_param.Z
        expr_bl_h = bl_rand_sec * bc_param.H
        expr_bl_h2 = bl_rand_sec * bc_param.H_2
        stmt = (DLRep(self.bl_z, expr_bl_z) & DLRep(bproof.bl_h, expr_bl_h)
                & DLRep(bproof.bl_h2, expr_bl_h2))

        # attributes
        for i in range(len(bproof.bl_hi)):
            expr = bl_rand_sec * bc_param.HS[i]
            stmt = stmt & DLRep(bproof.bl_hi[i], expr)

        # proof
        revealed_acc = bc_param.group.infinite()
        expr_bl_commit = Secret(name="rand") * bproof.bl_h + Secret(
            name="rand_2") * bproof.bl_h2
        for i in range(len(bproof.bl_hi)):
            if bproof.revealed_values[i] is None:
                expr_bl_commit += Secret(name=f"val_{i}") * bproof.bl_hi[i]
            else:
                val = bc_param.process_raw_value(bproof.revealed_values[i])
                revealed_acc += val * bproof.bl_hi[i]
        stmt = stmt & DLRep(self.bl_commit - revealed_acc, expr_bl_commit)

        # Having an invalid revealed secret leads to different
        # {commit-revealed_acc} value between prover and verifier. Since this
        # value is a zksk.statement constant, the mismatch results in a
        # StatementMismatch exception. verify_proof checks for this exception
        # and convert it to False
        try:
            is_valid = stmt.verify(bproof.nizk_proof)
        except StatementMismatch:
            return False
        return is_valid
Exemplo n.º 25
0
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()
Exemplo n.º 26
0
def test_range_stmt_non_interactive_start_at_nonzero(group):
    x = Secret(value=14)
    randomizer = Secret(value=group.order().random())

    g, h = make_generators(2, group)
    lo = 6
    hi = 16

    com = x * g + randomizer * h

    stmt1 = RangeStmt(com.eval(), g, h, lo, hi, x, randomizer)
    tr = stmt1.prove()

    stmt2 = RangeStmt(com.eval(), g, h, lo, hi, Secret(), Secret())
    assert stmt2.verify(tr)
Exemplo n.º 27
0
def test_dlrep_interactive_3(group):
    """Emulate actual workflow with independent provers and verifiers."""
    sk, g = group.order().random(), group.generator()
    pk = sk * g

    x = Secret()
    p1 = DLRep(pk, x * g)
    prover = p1.get_prover({x: sk})

    x = Secret()
    p2 = DLRep(pk, x * g)
    verifier = p2.get_verifier()

    protocol = SigmaProtocol(verifier, prover)
    assert protocol.verify()
Exemplo n.º 28
0
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()
Exemplo n.º 29
0
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()
Exemplo n.º 30
0
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()