def encrypt_ballots(request: EncryptBallotsRequest = Body(...)) -> Any: """ Encrypt one or more ballots """ ballots = [ PlaintextBallot.from_json_object(ballot) for ballot in request.ballots ] description = InternalElectionDescription( ElectionDescription.from_json_object(request.description)) context = CiphertextElectionContext.from_json_object(request.context) seed_hash = read_json_object(request.seed_hash, ElementModQ) nonce: Optional[ElementModQ] = (read_json_object( request.nonce, ElementModQ) if request.nonce else None) encrypted_ballots = [] current_hash = seed_hash for ballot in ballots: encrypted_ballot = encrypt_ballot(ballot, description, context, current_hash, nonce) if not encrypted_ballot: raise HTTPException(status_code=500, detail="Ballot failed to encrypt") encrypted_ballots.append(encrypted_ballot) current_hash = get_optional(encrypted_ballot.tracking_hash) response = EncryptBallotsResponse( encrypted_ballots=[ ballot.to_json_object() for ballot in encrypted_ballots ], next_seed_hash=write_json_object(current_hash), ) return response
def create_guardian_backup(request: GuardianBackupRequest) -> GuardianBackup: """ Generate all election partial key backups based on existing public keys :param request: Guardian backup request :return: Guardian backup """ encrypt = identity if request.override_rsa else rsa_encrypt backups: List[Any] = [] for auxiliary_public_key in request.auxiliary_public_keys: backup = generate_election_partial_key_backup( request.guardian_id, read_json_object(request.election_polynomial, ElectionPolynomial), AuxiliaryPublicKey( auxiliary_public_key.owner_id, auxiliary_public_key.sequence_order, auxiliary_public_key.key, ), encrypt, ) if not backup: raise HTTPException(status_code=500, detail="Backup failed to be generated") backups.append(write_json_object(backup)) return GuardianBackup( id=request.guardian_id, election_partial_key_backups=backups, )
def combine_election_keys(request: CombineElectionKeysRequest) -> ElectionJointKey: """ Combine public election keys into a final one :return: Combine Election key """ public_keys = [] for key in request.election_public_keys: public_keys.append(int_to_p_unchecked(key)) joint_key = elgamal_combine_public_keys(public_keys) return ElectionJointKey(joint_key=write_json_object(joint_key))
def create_backup_challenge(request: BackupChallengeRequest) -> Any: challenge = generate_election_partial_key_challenge( read_json_object(request.election_partial_key_backup, ElectionPartialKeyBackup), read_json_object(request.election_polynomial, ElectionPolynomial), ) if not challenge: raise HTTPException( status_code=500, detail="Backup challenge generation failed" ) return write_json_object(challenge)
def verify_challenge(request: ChallengeVerificationRequest) -> Any: verification = verify_election_partial_key_challenge( request.verifier_id, read_json_object( request.election_partial_key_challenge, ElectionPartialKeyChallenge ), ) if not verification: raise HTTPException( status_code=500, detail="Challenge verification process failed" ) return write_json_object(verification)
def test_read_and_write_json_object(self) -> None: # Act json_object = write_json_object(JSON_DATA) # Assert self.assertEqual(json_object, EXPECTED_JSON_OBJECT) # Act read_json_data = read_json_object(json_object, DataModel) # Assert self.assertEqual(read_json_data, JSON_DATA)
def verify_backup(request: BackupVerificationRequest) -> Any: decrypt = identity if request.override_rsa else rsa_decrypt verification = verify_election_partial_key_backup( request.verifier_id, read_json_object(request.election_partial_key_backup, ElectionPartialKeyBackup), read_json_object(request.auxiliary_key_pair, AuxiliaryKeyPair), decrypt, ) if not verification: raise HTTPException( status_code=500, detail="Backup verification process failed" ) return write_json_object(verification)
def generate_election_keys(request: ElectionKeyPairRequest) -> ElectionKeyPair: """ Generate election key pairs for use in election process :param request: Election key pair request :return: Election key pair """ keys = generate_election_key_pair( request.quorum, int_to_q_unchecked(request.nonce) if request.nonce is not None else None, ) if not keys: raise HTTPException( status_code=500, detail="Election keys failed to be generated", ) return ElectionKeyPair( public_key=str(keys.key_pair.public_key), secret_key=str(keys.key_pair.secret_key), proof=write_json_object(keys.proof), polynomial=write_json_object(keys.polynomial), )
def create_guardian(request: GuardianRequest) -> Guardian: """ Create a guardian for the election process with the associated keys """ election_keys = generate_election_key_pair( request.quorum, int_to_q_unchecked(request.nonce) if request.nonce is not None else None, ) if request.auxiliary_key_pair is None: auxiliary_keys = generate_rsa_auxiliary_key_pair() else: auxiliary_keys = request.auxiliary_key_pair if not election_keys: raise HTTPException( status_code=500, detail="Election keys failed to be generated", ) if not auxiliary_keys: raise HTTPException( status_code=500, detail="Auxiliary keys failed to be generated" ) return Guardian( id=request.id, sequence_order=request.sequence_order, number_of_guardians=request.number_of_guardians, quorum=request.quorum, election_key_pair=ElectionKeyPair( public_key=str(election_keys.key_pair.public_key), secret_key=str(election_keys.key_pair.secret_key), proof=write_json_object(election_keys.proof), polynomial=write_json_object(election_keys.polynomial), ), auxiliary_key_pair=AuxiliaryKeyPair( public_key=auxiliary_keys.public_key, secret_key=auxiliary_keys.secret_key ), )
def build_election_context(request: ElectionContextRequest = Body(...)) -> Any: """ Build a CiphertextElectionContext for a given election """ description: ElectionDescription = ElectionDescription.from_json_object( request.description) elgamal_public_key: ElementModP = read_json_object( request.elgamal_public_key, ElementModP) number_of_guardians = request.number_of_guardians quorum = request.quorum context = make_ciphertext_election_context(number_of_guardians, quorum, elgamal_public_key, description.crypto_hash()) return write_json_object(context)
def decrypt_share( request: DecryptTallyShareRequest = Body(...), scheduler: Scheduler = Depends(get_scheduler), ) -> Any: """ Decrypt a single guardian's share of a tally """ description = InternalElectionDescription( ElectionDescription.from_json_object(request.description) ) context = CiphertextElectionContext.from_json_object(request.context) guardian = convert_guardian(request.guardian) tally = convert_tally(request.encrypted_tally, description, context) share = compute_decryption_share(guardian, tally, context, scheduler) return write_json_object(share)
def decrypt_ballots(request: DecryptBallotsRequest = Body(...)) -> Any: ballots = [ CiphertextAcceptedBallot.from_json_object(ballot) for ballot in request.encrypted_ballots ] context: CiphertextElectionContext = CiphertextElectionContext.from_json_object( request.context) all_shares: List[BallotDecryptionShare] = [ read_json_object(share, BallotDecryptionShare) for shares in request.shares.values() for share in shares ] shares_by_ballot = index_shares_by_ballot(all_shares) extended_base_hash = context.crypto_extended_base_hash decrypted_ballots = { ballot.object_id: decrypt_ballot(ballot, shares_by_ballot[ballot.object_id], extended_base_hash) for ballot in ballots } return write_json_object(decrypted_ballots)
def decrypt_ballot_shares( request: DecryptBallotSharesRequest = Body(...), scheduler: Scheduler = Depends(get_scheduler), ) -> Any: """ Decrypt this guardian's share of one or more ballots """ ballots = [ CiphertextAcceptedBallot.from_json_object(ballot) for ballot in request.encrypted_ballots ] context = CiphertextElectionContext.from_json_object(request.context) guardian = convert_guardian(request.guardian) shares = [ compute_decryption_share_for_ballot(guardian, ballot, context, scheduler) for ballot in ballots ] response = DecryptBallotSharesResponse( shares=[write_json_object(share) for share in shares] ) return response
def serialize_as_dict(obj, include_private: bool = False) -> object: return write_json_object(obj, not include_private)
def serialize(obj, include_private: bool = False): return write_json_object(obj, not include_private)