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_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_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 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 convert_tracker_to_words(request: TrackerWordsRequest = Body(...)) -> Any:
    """
    Convert tracker from hash to human readable / friendly words
    """

    tracker_hash = read_json_object(request.tracker_hash, ElementModQ)
    tracker_words = tracker_hash_to_words(tracker_hash, request.seperator)
    return TrackerWords(tracker_words=tracker_words)
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 convert_guardian(
        api_guardian: Guardian) -> electionguard.guardian.Guardian:
    """
    Convert an API Guardian model to a fully-hydrated SDK Guardian model.
    """

    guardian = electionguard.guardian.Guardian(
        api_guardian.id,
        api_guardian.sequence_order,
        api_guardian.number_of_guardians,
        api_guardian.quorum,
    )

    guardian._auxiliary_keys = electionguard.key_ceremony.AuxiliaryKeyPair(
        api_guardian.auxiliary_key_pair.public_key,
        api_guardian.auxiliary_key_pair.secret_key,
    )

    election_public_key = read_json_object(
        api_guardian.election_key_pair.public_key,
        electionguard.group.ElementModP)
    election_secret_key = read_json_object(
        api_guardian.election_key_pair.secret_key,
        electionguard.group.ElementModQ)
    guardian._election_keys = electionguard.key_ceremony.ElectionKeyPair(
        electionguard.elgamal.ElGamalKeyPair(election_secret_key,
                                             election_public_key),
        read_json_object(api_guardian.election_key_pair.proof,
                         electionguard.schnorr.SchnorrProof),
        read_json_object(
            api_guardian.election_key_pair.polynomial,
            electionguard.election_polynomial.ElectionPolynomial,
        ),
    )

    return guardian
Beispiel #9
0
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)
Beispiel #10
0
def convert_tally(
    encrypted_tally: PublishedCiphertextTally,
    description: electionguard.election.InternalElectionDescription,
    context: electionguard.election.CiphertextElectionContext,
) -> electionguard.tally.CiphertextTally:
    """
    Convert to an SDK CiphertextTally model
    """

    published_tally = read_json_object(
        encrypted_tally, electionguard.tally.PublishedCiphertextTally
    )
    tally = electionguard.tally.CiphertextTally(
        published_tally.object_id, description, context
    )
    tally.cast = published_tally.cast

    return tally
Beispiel #11
0
def decrypt_tally(request: DecryptTallyRequest = Body(...)) -> Any:
    """
    Decrypt a tally from a collection of decrypted guardian shares
    """
    description = InternalElectionDescription(
        ElectionDescription.from_json_object(request.description))
    context = CiphertextElectionContext.from_json_object(request.context)
    tally = convert_tally(request.encrypted_tally, description, context)

    shares = {
        guardian_id: read_json_object(share, TallyDecryptionShare)
        for guardian_id, share in request.shares.items()
    }

    full_plaintext_tally = decrypt(tally, shares, context)
    if not full_plaintext_tally:
        raise HTTPException(
            status_code=500,
            detail="Unable to decrypt tally",
        )
    published_plaintext_tally = publish_plaintext_tally(full_plaintext_tally)

    return published_plaintext_tally.to_json_object()
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)
Beispiel #13
0
def deserialize_key(obj):
    return read_json_object(obj, ElementModP)
Beispiel #14
0
def deserialize(obj, type):
    return read_json_object(obj, type)