Encrypt Ballots

The primary function of ElectionGuard is to encrypt ballots. Ballots are encrypted on a uniquely identified device within the context of a specific election. The election public key is used to encrypt ballots. A master nonce value is generated for each ballot and the nonce is used to derive other nonce values for encrypting the selection on each ballot.


  • Plaintext Ballot - The plaintext representation of a voter's selections
  • Ciphertext Ballot - The encrypted representation of a voter's selections
  • Master Nonce - A random number used to derive encryptions in a CiphertextBallot
  • Tracking Code - A unique hash value generated by an Encryption Device to anonymously identify a ballot
  • Encryption Device The device that is doing the encryption


  1. Verify the ballot is well-formed against the Election Metadata (InternalElectionDescription)
  2. Generate a random master nonce value to use as a secret when encrypting the ballot
  3. Using the metadata of the election and the master nonce, encrypt each selection on the ballot
  4. For each selection on the ballot, generate a disjunctive Non-Interactive Zero-Knowledge Proof that the encryption is either an encryption of zero or one
  5. For each contest on the ballot, generate a Non-Interactive Zero-Knowledge Proof that the sum of all encrypted ballots is equal to the selection limit on the contest
  6. Generate a tracking code for the ballot

Usage Example

metadata: InternalElectionDescription
context: CiphertextElectionContext
ballot: PlaintextBallot

# Configure an encryption device
device = EncryptionDevice("polling-place-one")
encrypter = EncryptionMediator(metadata, context, device)

# Encrypt the ballot
encrypted_ballot: CiphertextBallot = encrypter.encrypt(ballot)

Implementation Considerations

When encrypting a ballot, a new ballot object is created that is associated with the plaintext ballot. The encrypted representation includes all of the encryptions, hash values, nonce values, and proofs generated at each step. For the primary end-to-end election workflow, consumers of this API should separate the nonce values from the CiphertextBallot prior to publishing the encrypted ballot representation.