示例#1
0
    def test_ccp_proof(
        self,
        keypair: ElGamalKeyPair,
        nonce: ElementModQ,
        seed: ElementModQ,
        constant: int,
        bad_constant: int,
    ):
        # assume() slows down the test-case generation
        # so assume(constant != bad_constant)
        if constant == bad_constant:
            bad_constant = constant + 1

        message = get_optional(elgamal_encrypt(constant, nonce, keypair.public_key))
        message_bad = get_optional(
            elgamal_encrypt(bad_constant, nonce, keypair.public_key)
        )

        proof = make_constant_chaum_pedersen(
            message, constant, nonce, keypair.public_key, seed
        )
        self.assertTrue(proof.is_valid(message, keypair.public_key))

        proof_bad1 = make_constant_chaum_pedersen(
            message_bad, constant, nonce, keypair.public_key, seed
        )
        self.assertFalse(proof_bad1.is_valid(message_bad, keypair.public_key))

        proof_bad2 = make_constant_chaum_pedersen(
            message, bad_constant, nonce, keypair.public_key, seed
        )
        self.assertFalse(proof_bad2.is_valid(message, keypair.public_key))

        proof_bad3 = proof._replace(constant=-1)
        self.assertFalse(proof_bad3.is_valid(message, keypair.public_key))
 def test_ccp_proofs_simple_encryption_of_one(self):
     keypair = elgamal_keypair_from_secret(TWO_MOD_Q)
     nonce = ONE_MOD_Q
     seed = TWO_MOD_Q
     message = get_optional(elgamal_encrypt(1, nonce, keypair.public_key))
     proof = make_constant_chaum_pedersen(message, 1, nonce,
                                          keypair.public_key, seed)
     bad_proof = make_constant_chaum_pedersen(message, 0, nonce,
                                              keypair.public_key, seed)
     self.assertTrue(proof.is_valid(message, keypair.public_key))
     self.assertFalse(bad_proof.is_valid(message, keypair.public_key))
    def test_encrypt_ballot_with_derivative_nonces_regenerates_valid_proofs(
            self, keypair: ElGamalKeyPair):
        """
        This test verifies that we can regenerate the contest and selection proofs from the cached nonce values
        """

        # TODO: Hypothesis test instead

        # Arrange
        election = election_factory.get_simple_election_from_file()
        metadata, context = election_factory.get_fake_ciphertext_election(
            election, keypair.public_key)

        data = ballot_factory.get_simple_ballot_from_file()
        self.assertTrue(data.is_valid(metadata.ballot_styles[0].object_id))

        device = EncryptionDevice("Location")
        subject = EncryptionMediator(metadata, context, device)

        # Act
        result = subject.encrypt(data)
        self.assertTrue(
            result.is_valid_encryption(context.crypto_extended_base_hash,
                                       keypair.public_key))

        # Assert
        for contest in result.contests:
            # Find the contest description
            contest_description = list(
                filter(lambda i: i.object_id == contest.object_id,
                       metadata.contests))[0]

            # Homomorpically accumulate the selection encryptions
            elgamal_accumulation = elgamal_add(
                *
                [selection.message for selection in contest.ballot_selections])
            # accumulate the selection nonce's
            aggregate_nonce = add_q(
                *[selection.nonce for selection in contest.ballot_selections])

            regenerated_constant = make_constant_chaum_pedersen(
                elgamal_accumulation,
                contest_description.number_elected,
                aggregate_nonce,
                keypair.public_key,
                add_q(contest.nonce, TWO_MOD_Q),
            )

            self.assertTrue(
                regenerated_constant.is_valid(elgamal_accumulation,
                                              keypair.public_key))

            for selection in contest.ballot_selections:
                # Since we know the nonce, we can decrypt the plaintext
                representation = selection.message.decrypt_known_nonce(
                    keypair.public_key, selection.nonce)

                # one could also decrypt with the secret key:
                # representation = selection.message.decrypt(keypair.secret_key)

                regenerated_disjuctive = make_disjunctive_chaum_pedersen(
                    selection.message,
                    selection.nonce,
                    keypair.public_key,
                    add_q(selection.nonce, TWO_MOD_Q),
                    representation,
                )

                self.assertTrue(
                    regenerated_disjuctive.is_valid(selection.message,
                                                    keypair.public_key))