def test_publish_election_backup_challenge(self): # Arrange guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) recipient_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM, ) guardian.save_auxiliary_public_key( recipient_guardian.share_auxiliary_public_key() ) guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) # Act challenge = guardian.publish_election_backup_challenge(RECIPIENT_GUARDIAN_ID) # Assert self.assertIsNotNone(challenge) self.assertIsNotNone(challenge.value) self.assertEqual(challenge.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(challenge.designated_id, RECIPIENT_GUARDIAN_ID) self.assertEqual(len(challenge.coefficient_commitments), QUORUM) self.assertEqual(len(challenge.coefficient_proofs), QUORUM) for proof in challenge.coefficient_proofs: proof.is_valid()
def test_verify_election_partial_key_backup(self): # Arrange # Round 1 guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) other_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) guardian.save_guardian_public_keys(other_guardian.share_public_keys()) other_guardian.save_guardian_public_keys(guardian.share_public_keys()) # Round 2 guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) key_backup = guardian.share_election_partial_key_backup(RECIPIENT_GUARDIAN_ID) other_guardian.save_election_partial_key_backup(key_backup) # Act verification = other_guardian.verify_election_partial_key_backup( SENDER_GUARDIAN_ID, identity_auxiliary_decrypt ) # Assert self.assertIsNotNone(verification) self.assertEqual(verification.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(verification.designated_id, RECIPIENT_GUARDIAN_ID) self.assertEqual(verification.verifier_id, RECIPIENT_GUARDIAN_ID) self.assertTrue(verification.verified)
def test_verify_election_partial_key_challenge(self): # Arrange guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) recipient_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM, ) alternate_guardian = Guardian( ALTERNATE_VERIFIER_GUARDIAN_ID, ALTERNATE_VERIFIER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM, ) guardian.save_auxiliary_public_key( recipient_guardian.share_auxiliary_public_key() ) guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) challenge = guardian.publish_election_backup_challenge(RECIPIENT_GUARDIAN_ID) # Act verification = alternate_guardian.verify_election_partial_key_challenge( challenge ) # Assert self.assertIsNotNone(verification) self.assertEqual(verification.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(verification.designated_id, RECIPIENT_GUARDIAN_ID) self.assertEqual(verification.verifier_id, ALTERNATE_VERIFIER_GUARDIAN_ID) self.assertTrue(verification.verified)
def test_generate_election_partial_key_backups(self): # Arrange guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) other_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) # Act empty_key_backup = guardian.share_election_partial_key_backup( RECIPIENT_GUARDIAN_ID ) # Assert self.assertIsNone(empty_key_backup) # Act guardian.save_auxiliary_public_key(other_guardian.share_auxiliary_public_key()) guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) key_backup = guardian.share_election_partial_key_backup(RECIPIENT_GUARDIAN_ID) # Assert self.assertIsNotNone(key_backup) self.assertIsNotNone(key_backup.encrypted_value) self.assertEqual(key_backup.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(key_backup.designated_id, RECIPIENT_GUARDIAN_ID) self.assertEqual(len(key_backup.coefficient_commitments), QUORUM) self.assertEqual(len(key_backup.coefficient_proofs), QUORUM) for proof in key_backup.coefficient_proofs: proof.is_valid()
def test_all_election_partial_key_backups_verified(self): # Arrange # Round 1 guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) other_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) guardian.save_guardian_public_keys(other_guardian.share_public_keys()) other_guardian.save_guardian_public_keys(guardian.share_public_keys()) # Round 2 guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) key_backup = guardian.share_election_partial_key_backup(RECIPIENT_GUARDIAN_ID) other_guardian.save_election_partial_key_backup(key_backup) verification = other_guardian.verify_election_partial_key_backup( SENDER_GUARDIAN_ID, identity_auxiliary_decrypt ) guardian.save_election_partial_key_verification(verification) # Act all_saved = guardian.all_election_partial_key_backups_verified() # Assert self.assertTrue(all_saved)
def test_save_election_public_key(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) other_guardian = Guardian(RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) public_key = other_guardian.share_election_public_key() # Act guardian.save_election_public_key(public_key) # Assert self.assertTrue(guardian.all_election_public_keys_received())
def test_all_public_keys_received(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) other_guardian = Guardian(RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) public_keys = other_guardian.share_public_keys() # Act self.assertFalse(guardian.all_public_keys_received()) guardian.save_guardian_public_keys(public_keys) # Assert self.assertTrue(guardian.all_public_keys_received())
def test_all_election_partial_key_backups_received(self): # Arrange guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) other_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) guardian.save_auxiliary_public_key(other_guardian.share_auxiliary_public_key()) guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) key_backup = guardian.share_election_partial_key_backup(RECIPIENT_GUARDIAN_ID) # Assert self.assertFalse(other_guardian.all_election_partial_key_backups_received()) other_guardian.save_election_partial_key_backup(key_backup) self.assertTrue(other_guardian.all_election_partial_key_backups_received())
def create_guardians(ceremony_details: CeremonyDetails) -> List[Guardian]: return [ Guardian( "guardian_" + str(i + 1), i + 1, ceremony_details.number_of_guardians, ceremony_details.quorum, ) for i in range(ceremony_details.number_of_guardians) ]
def test_share_election_partial_key_backup(self): # Arrange guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) other_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) # Act guardian.save_auxiliary_public_key(other_guardian.share_auxiliary_public_key()) guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) key_backup = guardian.share_election_partial_key_backup(RECIPIENT_GUARDIAN_ID) # Assert self.assertIsNotNone(key_backup) self.assertIsNotNone(key_backup.encrypted_value) self.assertEqual(key_backup.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(key_backup.designated_id, RECIPIENT_GUARDIAN_ID)
def test_save_election_partial_key_verification(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) other_guardian = Guardian(RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) guardian.save_auxiliary_public_key( other_guardian.share_auxiliary_public_key()) guardian.generate_election_partial_key_backups() key_backup = guardian.share_election_partial_key_backup( RECIPIENT_GUARDIAN_ID) other_guardian.save_election_partial_key_backup(key_backup) verification = other_guardian.verify_election_partial_key_backup( SENDER_GUARDIAN_ID) # Act guardian.save_election_partial_key_verification(verification) # Assert self.assertTrue(guardian.all_election_partial_key_backups_verified)
def test_publish_joint_key(self): # Arrange # Round 1 guardian = Guardian( SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) other_guardian = Guardian( RECIPIENT_GUARDIAN_ID, RECIPIENT_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM ) guardian.save_guardian_public_keys(other_guardian.share_public_keys()) other_guardian.save_guardian_public_keys(guardian.share_public_keys()) # Round 2 guardian.generate_election_partial_key_backups(identity_auxiliary_encrypt) key_backup = guardian.share_election_partial_key_backup(RECIPIENT_GUARDIAN_ID) other_guardian.save_election_partial_key_backup(key_backup) verification = other_guardian.verify_election_partial_key_backup( SENDER_GUARDIAN_ID, identity_auxiliary_decrypt ) # Act joint_key = guardian.publish_joint_key() # Assert self.assertIsNone(joint_key) # Act guardian.save_election_public_key(other_guardian.share_election_public_key()) joint_key = guardian.publish_joint_key() # Assert self.assertIsNone(joint_key) # Act guardian.save_election_partial_key_verification(verification) joint_key = guardian.publish_joint_key() # Assert self.assertIsNotNone(joint_key) self.assertNotEqual(joint_key, guardian.share_election_public_key().key)
def test_reset(self): guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) expected_number_of_guardians = 10 expected_quorum = 4 # Act guardian.reset(expected_number_of_guardians, expected_quorum) # Assert self.assertEqual(expected_number_of_guardians, guardian.ceremony_details.number_of_guardians) self.assertEqual(expected_quorum, guardian.ceremony_details.quorum)
def process_message(self, message_type: str, message: dict, context: Context): context.build_election(message) guardian_ids = [trustee['name'] for trustee in message['trustees']] context.guardian_ids = set(guardian_ids) order = guardian_ids.index(context.guardian_id) context.guardian = Guardian(context.guardian_id, order, context.number_of_guardians, context.quorum) self.next_step = ProcessTrusteeElectionKeys() return serialize(context.guardian.share_public_keys())
def test_share_election_public_key(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) # Act public_key = guardian.share_election_public_key() # Assert self.assertIsNotNone(public_key) self.assertIsNotNone(public_key.key) self.assertEqual(public_key.owner_id, SENDER_GUARDIAN_ID) self.assertTrue(public_key.proof.is_valid())
def test_share_auxiliary_public_key(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) # Act public_key = guardian.share_auxiliary_public_key() # Assert self.assertIsNotNone(public_key) self.assertIsNotNone(public_key.key) self.assertEqual(public_key.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(public_key.sequence_order, SENDER_SEQUENCE_ORDER)
def test_generate_auxiliary_key_pair(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) first_public_key = guardian.share_auxiliary_public_key() # Act guardian.generate_auxiliary_key_pair() second_public_key = guardian.share_auxiliary_public_key() # Assert self.assertIsNotNone(second_public_key) self.assertIsNotNone(second_public_key.key) self.assertNotEqual(first_public_key.key, second_public_key.key)
def test_share_public_keys(self): # Arrange guardian = Guardian(SENDER_GUARDIAN_ID, SENDER_SEQUENCE_ORDER, NUMBER_OF_GUARDIANS, QUORUM) # Act public_keys = guardian.share_public_keys() # Assert self.assertIsNotNone(public_keys) self.assertIsNotNone(public_keys.auxiliary_public_key) self.assertIsNotNone(public_keys.election_public_key) self.assertEqual(public_keys.owner_id, SENDER_GUARDIAN_ID) self.assertEqual(public_keys.sequence_order, SENDER_SEQUENCE_ORDER) self.assertTrue(public_keys.election_public_key_proof.is_valid())
def setupGuardians(self): # Setup Guardians for i in range(self.NUMBER_OF_GUARDIANS): sequence = i + 2 self.guardians.append( Guardian( "guardian_" + str(sequence), sequence, self.NUMBER_OF_GUARDIANS, self.QUORUM, )) # Attendance (Public Key Share) for guardian in self.guardians: self.key_ceremony_mediator.announce(guardian)
def test_publish_private_data(self) -> None: # Arrange plaintext_ballots = [PlaintextBallot("", "", [])] encrypted_ballots = [CiphertextBallot("", "", "", "", [])] guardians = [Guardian("", 1, 1, 1)] # Act publish_private_data( plaintext_ballots, encrypted_ballots, guardians, ) # Assert self.assertTrue(path.exists(RESULTS_DIR)) # Cleanup rmtree(RESULTS_DIR)
def get_hamilton_election_with_encryption_context( self, ) -> Tuple[AllPublicElectionData, AllPrivateElectionData]: guardians: List[Guardian] = [] coefficient_validation_sets: List[CoefficientValidationSet] = [] # Configure the election builder description = self.get_hamilton_election_from_file() builder = ElectionBuilder(NUMBER_OF_GUARDIANS, QUORUM, description) # Setup Guardians for i in range(NUMBER_OF_GUARDIANS): guardians.append( Guardian( "hamilton-county-canvass-board-member-" + str(i), i, NUMBER_OF_GUARDIANS, QUORUM, )) # Run the key ceremony mediator = KeyCeremonyMediator(guardians[0].ceremony_details) for guardian in guardians: mediator.announce(guardian) mediator.orchestrate() mediator.verify() # Joint Key joint_key = mediator.publish_joint_key() # Save Validation Keys for guardian in guardians: coefficient_validation_sets.append( guardian.share_coefficient_validation_set()) builder.set_public_key(get_optional(joint_key).joint_public_key) builder.set_commitment_hash(get_optional(joint_key).commitment_hash) metadata, context = get_optional(builder.build()) constants = ElectionConstants() return ( AllPublicElectionData(description, metadata, context, constants, coefficient_validation_sets), AllPrivateElectionData(guardians), )
def process_message( self, message_type: Literal["create_election"], message: dict, context: TrusteeContext, ) -> Tuple[List[Content], ElectionStep]: context.build_election(message) guardian_ids: List[GUARDIAN_ID] = [ trustee["slug"] for trustee in message["trustees"] ] context.guardian_ids = guardian_ids context.guardian = Guardian( context.guardian_id, guardian_ids.index(context.guardian_id) + 1, context.number_of_guardians, context.quorum, ) return [], ProcessStartKeyCeremony()
def setUp(self): self.key_ceremony = KeyCeremonyMediator(self.CEREMONY_DETAILS) self.guardians: List[Guardian] = [] # Setup Guardians for i in range(self.NUMBER_OF_GUARDIANS): sequence = i + 2 self.guardians.append( Guardian( "guardian_" + str(sequence), sequence, self.NUMBER_OF_GUARDIANS, self.QUORUM, )) # Attendance (Public Key Share) for guardian in self.guardians: self.key_ceremony.announce(guardian) self.key_ceremony.orchestrate(identity_auxiliary_encrypt) self.key_ceremony.verify(identity_auxiliary_decrypt) self.joint_public_key = self.key_ceremony.publish_joint_key() self.assertIsNotNone(self.joint_public_key) # setup the election self.election = election_factory.get_fake_election() builder = ElectionBuilder(self.NUMBER_OF_GUARDIANS, self.QUORUM, self.election) self.assertIsNone( builder.build()) # Can't build without the public key builder.set_public_key(self.joint_public_key) self.metadata, self.context = get_optional(builder.build()) self.encryption_device = EncryptionDevice("location") self.ballot_marking_device = EncryptionMediator( self.metadata, self.context, self.encryption_device) # get some fake ballots self.fake_cast_ballot = ballot_factory.get_fake_ballot( self.metadata, "some-unique-ballot-id-cast") self.more_fake_ballots = [] for i in range(10): self.more_fake_ballots.append( ballot_factory.get_fake_ballot( self.metadata, f"some-unique-ballot-id-cast{i}")) self.fake_spoiled_ballot = ballot_factory.get_fake_ballot( self.metadata, "some-unique-ballot-id-spoiled") self.assertTrue( self.fake_cast_ballot.is_valid( self.metadata.ballot_styles[0].object_id)) self.assertTrue( self.fake_spoiled_ballot.is_valid( self.metadata.ballot_styles[0].object_id)) self.expected_plaintext_tally = accumulate_plaintext_ballots( [self.fake_cast_ballot] + self.more_fake_ballots) # Fill in the expected values with any missing selections # that were not made on any ballots selection_ids = set([ selection.object_id for contest in self.metadata.contests for selection in contest.ballot_selections ]) missing_selection_ids = selection_ids.difference( set(self.expected_plaintext_tally)) for id in missing_selection_ids: self.expected_plaintext_tally[id] = 0 # Encrypt encrypted_fake_cast_ballot = self.ballot_marking_device.encrypt( self.fake_cast_ballot) encrypted_fake_spoiled_ballot = self.ballot_marking_device.encrypt( self.fake_spoiled_ballot) self.assertIsNotNone(encrypted_fake_cast_ballot) self.assertIsNotNone(encrypted_fake_spoiled_ballot) self.assertTrue( encrypted_fake_cast_ballot.is_valid_encryption( self.context.crypto_extended_base_hash, self.joint_public_key)) # encrypt some more fake ballots self.more_fake_encrypted_ballots = [] for fake_ballot in self.more_fake_ballots: self.more_fake_encrypted_ballots.append( self.ballot_marking_device.encrypt(fake_ballot)) # configure the ballot box ballot_store = BallotStore() ballot_box = BallotBox(self.metadata, self.context, ballot_store) ballot_box.cast(encrypted_fake_cast_ballot) ballot_box.spoil(encrypted_fake_spoiled_ballot) # Cast some more fake ballots for fake_ballot in self.more_fake_encrypted_ballots: ballot_box.cast(fake_ballot) # generate encrypted tally self.ciphertext_tally = tally_ballots(ballot_store, self.metadata, self.context)
CeremonyDetails, ElectionPartialKeyVerification, GuardianPair, ) from electionguard.key_ceremony_mediator import KeyCeremonyMediator identity_auxiliary_decrypt = lambda message, public_key: message identity_auxiliary_encrypt = lambda message, private_key: message NUMBER_OF_GUARDIANS = 2 QUORUM = 2 CEREMONY_DETAILS = CeremonyDetails(NUMBER_OF_GUARDIANS, QUORUM) GUARDIAN_1_ID = "Guardian 1" GUARDIAN_2_ID = "Guardian 2" VERIFIER_ID = "Guardian 3" GUARDIAN_1 = Guardian(GUARDIAN_1_ID, 1, NUMBER_OF_GUARDIANS, QUORUM) GUARDIAN_2 = Guardian(GUARDIAN_2_ID, 2, NUMBER_OF_GUARDIANS, QUORUM) VERIFIER = Guardian(VERIFIER_ID, 3, NUMBER_OF_GUARDIANS, QUORUM) GUARDIAN_1.save_guardian_public_keys(GUARDIAN_2.share_public_keys()) GUARDIAN_2.save_guardian_public_keys(GUARDIAN_1.share_public_keys()) VERIFIER.save_guardian_public_keys(GUARDIAN_2.share_public_keys()) GUARDIAN_1.generate_election_partial_key_backups(identity_auxiliary_encrypt) GUARDIAN_2.generate_election_partial_key_backups(identity_auxiliary_encrypt) class TestKeyCeremonyMediator(TestCase): def test_reset(self): # Arrange mediator = KeyCeremonyMediator(CEREMONY_DETAILS) new_ceremony_details = CeremonyDetails(3, 3)
def step_1_key_ceremony(self) -> None: """ Using the NUMBER_OF_GUARDIANS, generate public-private keypairs and share representations of those keys with QUORUM of other Guardians. Then, combine the public election keys to make a joint election key that is used to encrypt ballots """ # Setup Guardians for i in range(self.NUMBER_OF_GUARDIANS): self.guardians.append( Guardian( "guardian_" + str(i + 1), i + 1, self.NUMBER_OF_GUARDIANS, self.QUORUM, )) # Setup Mediator self.mediator = KeyCeremonyMediator("mediator_1", self.guardians[0].ceremony_details) # ROUND 1: Public Key Sharing # Announce for guardian in self.guardians: self.mediator.announce(guardian.share_public_keys()) # Share Keys for guardian in self.guardians: announced_keys = self.mediator.share_announced() for key_set in announced_keys: if guardian.id is not key_set.election.owner_id: guardian.save_guardian_public_keys(key_set) self._assert_message( KeyCeremonyMediator.all_guardians_announced.__qualname__, "Confirms all guardians have shared their public keys", self.mediator.all_guardians_announced(), ) # ROUND 2: Election Partial Key Backup Sharing # Share Backups for sending_guardian in self.guardians: sending_guardian.generate_election_partial_key_backups( identity_auxiliary_encrypt) backups = [] for designated_guardian in self.guardians: if designated_guardian.id != sending_guardian.id: backups.append( sending_guardian.share_election_partial_key_backup( designated_guardian.id)) self.mediator.receive_backups(backups) self._assert_message( KeyCeremonyMediator.receive_backups.__qualname__, "Receive election partial key backups from key owning guardian", len(backups) == NUMBER_OF_GUARDIANS - 1, ) self._assert_message( KeyCeremonyMediator.all_backups_available.__qualname__, "Confirm all guardians have shared their election partial key backups", self.mediator.all_backups_available(), ) # Receive Backups for designated_guardian in self.guardians: backups = self.mediator.share_backups(designated_guardian.id) self._assert_message( KeyCeremonyMediator.share_backups.__qualname__, "Share election partial key backups for the designated guardian", len(backups) == NUMBER_OF_GUARDIANS - 1, ) for backup in backups: designated_guardian.save_election_partial_key_backup(backup) # ROUND 3: Verification of Backups # Verify Backups for designated_guardian in self.guardians: verifications = [] for backup_owner in self.guardians: if designated_guardian.id is not backup_owner.id: verification = ( designated_guardian.verify_election_partial_key_backup( backup_owner.id, identity_auxiliary_encrypt)) verifications.append(verification) self.mediator.receive_backup_verifications(verifications) self._assert_message( KeyCeremonyMediator.all_backups_verified.__qualname__, "Confirms all guardians have verified the backups of all other guardians", self.mediator.all_backups_verified(), ) # FINAL: Publish Joint Key joint_key = self.mediator.publish_joint_key() self._assert_message( KeyCeremonyMediator.publish_joint_key.__qualname__, "Publishes the Joint Election Key", joint_key is not None, ) # Build the Election self.election_builder.set_public_key( get_optional(joint_key).joint_public_key) self.election_builder.set_commitment_hash( get_optional(joint_key).commitment_hash) self.internal_manifest, self.context = get_optional( self.election_builder.build()) self.constants = ElectionConstants()
def step_1_key_ceremony(self) -> None: """ Using the NUMBER_OF_GUARDIANS, generate public-private keypairs and share representations of those keys with QUORUM of other Guardians. Then, combine the public election keys to make a joint election key that is used to encrypt ballots """ # Setup Guardians for i in range(self.NUMBER_OF_GUARDIANS): self.guardians.append( Guardian("guardian_" + str(i), i, self.NUMBER_OF_GUARDIANS, self.QUORUM)) # Setup Mediator self.mediator = KeyCeremonyMediator(self.guardians[0].ceremony_details) # Attendance (Public Key Share) for guardian in self.guardians: self.mediator.announce(guardian) self._assert_message( KeyCeremonyMediator.all_guardians_in_attendance.__qualname__, "Confirms all guardians have shared their public keys", self.mediator.all_guardians_in_attendance(), ) # Run the Key Ceremony process, # Which shares the keys among the guardians orchestrated = self.mediator.orchestrate() self._assert_message( KeyCeremonyMediator.orchestrate.__qualname__, "Executes the key exchange between guardians", orchestrated is not None, ) self._assert_message( KeyCeremonyMediator.all_election_partial_key_backups_available. __qualname__, "Confirm sall guardians have shared their partial key backups", self.mediator.all_election_partial_key_backups_available(), ) # Verification verified = self.mediator.verify() self._assert_message( KeyCeremonyMediator.verify.__qualname__, "Confirms all guardians truthfully executed the ceremony", verified, ) self._assert_message( KeyCeremonyMediator. all_election_partial_key_verifications_received.__qualname__, "Confirms all guardians have submitted a verification of the backups of all other guardians", self.mediator.all_election_partial_key_verifications_received(), ) self._assert_message( KeyCeremonyMediator.all_election_partial_key_backups_verified. __qualname__, "Confirms all guardians have verified the backups of all other guardians", self.mediator.all_election_partial_key_backups_verified(), ) # Joint Key joint_key = self.mediator.publish_joint_key() self._assert_message( KeyCeremonyMediator.publish_joint_key.__qualname__, "Publishes the Joint Election Key", joint_key is not None, ) # Save Validation Keys for guardian in self.guardians: self.coefficient_validation_sets.append( guardian.share_coefficient_validation_set()) # Build the Election self.election_builder.set_public_key(get_optional(joint_key)) self.metadata, self.context = get_optional( self.election_builder.build()) self.constants = ElectionConstants()
from electionguard.guardian import Guardian from electionguard.key_ceremony import ( CeremonyDetails, ElectionPartialKeyVerification, ) from electionguard.key_ceremony_mediator import KeyCeremonyMediator, GuardianPair from electionguardtest.key_ceremony_helper import KeyCeremonyHelper from electionguardtest.identity_encrypt import identity_auxiliary_decrypt NUMBER_OF_GUARDIANS = 2 QUORUM = 2 CEREMONY_DETAILS = CeremonyDetails(NUMBER_OF_GUARDIANS, QUORUM) GUARDIAN_1_ID = "Guardian 1" GUARDIAN_2_ID = "Guardian 2" GUARDIAN_1 = Guardian(GUARDIAN_1_ID, 1, NUMBER_OF_GUARDIANS, QUORUM) GUARDIAN_2 = Guardian(GUARDIAN_2_ID, 2, NUMBER_OF_GUARDIANS, QUORUM) GUARDIANS = [GUARDIAN_1, GUARDIAN_2] class TestKeyCeremonyMediator(TestCase): """Key ceremony mediator tests""" def test_reset(self): # Arrange mediator = KeyCeremonyMediator("mediator_reset", CEREMONY_DETAILS) new_ceremony_details = CeremonyDetails(3, 3) mediator.reset(new_ceremony_details) self.assertEqual(mediator.ceremony_details, new_ceremony_details) def test_take_attendance(self):