def step_2_encrypt_votes(self) -> None:
        """
        Using the `CiphertextElectionContext` encrypt ballots for the election
        """

        # Configure the Encryption Device
        self.device = ElectionFactory.get_encryption_device()
        self.encrypter = EncryptionMediator(self.internal_manifest,
                                            self.context, self.device)
        self._assert_message(
            EncryptionDevice.__qualname__,
            f"Ready to encrypt at location: {self.device.location}",
        )

        # Load some Ballots
        self.plaintext_ballots = BallotFactory().get_simple_ballots_from_file()
        self._assert_message(
            PlaintextBallot.__qualname__,
            f"Loaded ballots: {len(self.plaintext_ballots)}",
            len(self.plaintext_ballots) > 0,
        )

        # Encrypt the Ballots
        for plaintext_ballot in self.plaintext_ballots:
            encrypted_ballot = self.encrypter.encrypt(plaintext_ballot)
            self._assert_message(
                EncryptionMediator.encrypt.__qualname__,
                f"Ballot Id: {plaintext_ballot.object_id}",
                encrypted_ballot is not None,
            )
            self.ciphertext_ballots.append(get_optional(encrypted_ballot))
Пример #2
0
    def test_tally_cast_ballots_accumulates_valid_tally(
            self, everything: ELECTIONS_AND_BALLOTS_TUPLE_TYPE):
        # Arrange
        (
            _election_description,
            internal_manifest,
            ballots,
            secret_key,
            context,
        ) = everything
        # Tally the plaintext ballots for comparison later
        plaintext_tallies = accumulate_plaintext_ballots(ballots)

        # encrypt each ballot
        store = DataStore()
        encryption_seed = ElectionFactory.get_encryption_device().get_hash()
        for ballot in ballots:
            encrypted_ballot = encrypt_ballot(ballot, internal_manifest,
                                              context, encryption_seed)
            encryption_seed = encrypted_ballot.code
            self.assertIsNotNone(encrypted_ballot)
            # add to the ballot store
            store.set(
                encrypted_ballot.object_id,
                from_ciphertext_ballot(encrypted_ballot, BallotBoxState.CAST),
            )

        # act
        result = tally_ballots(store, internal_manifest, context)
        self.assertIsNotNone(result)

        # Assert
        decrypted_tallies = self._decrypt_with_secret(result, secret_key)
        self.assertEqual(plaintext_tallies, decrypted_tallies)
Пример #3
0
    def test_rotate_ballot_code(self):
        # Arrange
        device = ElectionFactory.get_encryption_device()
        ballot_hash_1 = ONE_MOD_Q
        ballot_hash_2 = TWO_MOD_Q
        timestamp_1 = 1000
        timestamp_2 = 2000

        # Act
        device_hash = get_hash_for_device(device.uuid, device.session_id,
                                          device.launch_code, device.location)
        ballot_code_1 = get_ballot_code(device_hash, timestamp_1,
                                        ballot_hash_1)
        ballot_code_2 = get_ballot_code(device_hash, timestamp_2,
                                        ballot_hash_2)

        # Assert
        self.assertIsNotNone(device_hash)
        self.assertIsNotNone(ballot_code_1)
        self.assertIsNotNone(ballot_code_2)

        self.assertNotEqual(device_hash, ZERO_MOD_Q)
        self.assertNotEqual(ballot_code_1, device_hash)
        self.assertNotEqual(ballot_code_2, device_hash)
        self.assertNotEqual(ballot_code_1, ballot_code_2)
Пример #4
0
    def setUp(self) -> None:
        # Election setup
        election_factory = ElectionFactory()
        keypair = elgamal_keypair_from_secret(int_to_q(2))
        manifest = election_factory.get_fake_manifest()
        (
            self.internal_manifest,
            self.context,
        ) = election_factory.get_fake_ciphertext_election(
            manifest, keypair.public_key)
        device_hash = ElectionFactory.get_encryption_device().get_hash()

        # Arrange ballots
        self.plaintext_ballot = election_factory.get_fake_ballot(
            self.internal_manifest)
        ciphertext_ballot = encrypt_ballot(self.plaintext_ballot,
                                           self.internal_manifest,
                                           self.context, device_hash)
        self.ballot_nonce = ciphertext_ballot.nonce
        self.submitted_ballot = from_ciphertext_ballot(ciphertext_ballot,
                                                       BallotBoxState.CAST)
Пример #5
0
    def test_tally_ballot_invalid_input_fails(
            self, everything: ELECTIONS_AND_BALLOTS_TUPLE_TYPE):

        # Arrange
        (
            _election_description,
            internal_manifest,
            ballots,
            _secret_key,
            context,
        ) = everything

        # encrypt each ballot
        store = DataStore()
        encryption_seed = ElectionFactory.get_encryption_device().get_hash()
        for ballot in ballots:
            encrypted_ballot = encrypt_ballot(ballot, internal_manifest,
                                              context, encryption_seed)
            encryption_seed = encrypted_ballot.code
            self.assertIsNotNone(encrypted_ballot)
            # add to the ballot store
            store.set(
                encrypted_ballot.object_id,
                from_ciphertext_ballot(encrypted_ballot, BallotBoxState.CAST),
            )

        tally = CiphertextTally("my-tally", internal_manifest, context)

        # act
        cached_ballots = store.all()
        first_ballot = cached_ballots[0]
        first_ballot.state = BallotBoxState.UNKNOWN

        # verify an UNKNOWN state ballot fails
        self.assertIsNone(tally_ballot(first_ballot, tally))
        self.assertFalse(tally.append(first_ballot))

        # cast a ballot
        first_ballot.state = BallotBoxState.CAST
        self.assertTrue(tally.append(first_ballot))

        # try to append a spoiled ballot
        first_ballot.state = BallotBoxState.SPOILED
        self.assertFalse(tally.append(first_ballot))

        # Verify accumulation fails if the selection collection is empty
        if first_ballot.state == BallotBoxState.CAST:
            self.assertFalse(
                tally.contests[first_ballot.object_id].accumulate_contest([]))

        # pylint: disable=protected-access
        # pop the cast ballot
        tally._cast_ballot_ids.pop()

        # reset to cast
        first_ballot.state = BallotBoxState.CAST

        self.assertTrue(
            self._cannot_erroneously_mutate_state(tally, first_ballot,
                                                  BallotBoxState.CAST))

        self.assertTrue(
            self._cannot_erroneously_mutate_state(tally, first_ballot,
                                                  BallotBoxState.SPOILED))

        self.assertTrue(
            self._cannot_erroneously_mutate_state(tally, first_ballot,
                                                  BallotBoxState.UNKNOWN))

        # verify a cast ballot cannot be added twice
        first_ballot.state = BallotBoxState.CAST
        self.assertTrue(tally.append(first_ballot))
        self.assertFalse(tally.append(first_ballot))

        # verify an already submitted ballot cannot be changed or readded
        first_ballot.state = BallotBoxState.SPOILED
        self.assertFalse(tally.append(first_ballot))
from electionguard.decrypt_with_secrets import decrypt_ballot_with_secret
from electionguard.elgamal import ElGamalCiphertext, elgamal_encrypt, elgamal_add
from electionguard.encrypt import encrypt_ballot
from electionguard.group import ElementModQ
from electionguard.manifest import Manifest
from electionguard.nonces import Nonces
from electionguardtest.election import (
    election_descriptions,
    elections_and_ballots,
    ELECTIONS_AND_BALLOTS_TUPLE_TYPE,
)
from electionguardtest.election_factory import ElectionFactory
from electionguardtest.group import elements_mod_q
from electionguardtest.tally import accumulate_plaintext_ballots

SEED = ElectionFactory.get_encryption_device().get_hash()


class TestElections(unittest.TestCase):
    """Election hypothesis encryption tests"""
    @settings(
        deadline=timedelta(milliseconds=2000),
        suppress_health_check=[HealthCheck.too_slow],
        max_examples=10,
    )
    @given(election_descriptions())
    def test_generators_yield_valid_output(self, manifest: Manifest):
        """
        Tests that our Hypothesis election strategies generate "valid" output, also exercises the full stack
        of `is_valid` methods.
        """