Voter faces threats of bribery and/or coercion.
Allow a voter to secretly notify an election admin their vote was corrupted, so the admin can anonymously cancel it from the election total. Admin then publishes a Zero-knowledge Proof of Votes-Secretly-Cancelled. This proves that the relevant voters consented, but not which voters.
This allows would-be victims of bribery or coercion to trick their would-be compromiser, so that compromisers can't trust whether their attempt was successful or not. This is similar to current In-person voter privacy to defend against coercion or vote-buying attempts, based on similar uncertainty for compromisers.
SIV's proposed Anti-Vote-Selling Bounty Reward system, called The Vote Seller's Dilemma, is already intended to make it very difficult for would-be sellers to trust would-be buyers, and remains recommended as well.
This new Secretly Cancellable Vote feature is meant for the reverse: to make it very difficult for would-be compromisers — whether through bribes or threats — to verify whether their attempt was successful.
It requires in-person voting infrastructure available alongside SIV.
The goal of this framework is to give SIV votes a similar level of defense against voter coercion as in-person voting currently holds.
- The coercer should not be able to learn if the vote was cancelled.
- The election admin must not be able to abuse this power, to secretly suppress votes.
- Malware on voters' devices must not be able to abuse this power, to secretly suppress votes.
- If a voter wants their vote Secretly Cancelled, they visit an in-person polling location.
- They tell the Official Poll Workers they'd like to Secretly Cancel their SIV Vote, because it was corrupted by a 3rd-party.
- The voter can but does not need to Cancel their entire ballot, and can selectively choose just the individual selections (columns) that are relevant.
- The Poll Worker authenticates the voter, e.g using a government-issued photo ID, to ensure the secret canceller's identity.
- The voter re-opens their SIV Voter Interface. They need to retrieve private vote values that went into encrypting their vote, to provide them to the Poll Worker. (SIV will make this easy— just scanning a QR code. The details can also be printed out ahead of time or exported via email).
- These were generated by voter's device. Admins do not get them otherwise.
- They are not assumed to be unknown to would-be compromisers. The ZK design keeps their use secret, even if compromisers know the values.
- Once received by the admin, they allow the admin to construct a ZK Proof for the total votes cancelled.
Voters — who wish to secretly cancel their (coerced) votes, so they can cast new paper replacements — provide their private vote data in-person to the election admin.
The original published SIV vote totals remain unchanged. This new sum of secretly-cancelled votes is also published, and its numbers can be subtracted from the SIV total, for the "uncorrupted" total.
Admin can then create zero-knowledge proofs for each of the cancelled votes, to prove each cancellation was authorized by the individual voters' themselves, but without revealing to 3rd-party coercers or bribers which votes were cancelled.
Fundamentally, the admin is proving in zero-knowledge that:
They were provided:
- the private encryption data for a normally accepted vote submissions — this serves as authorization from voter
- the anonymized content of the cancelled vote— unique verification number removed
Each cancellation serves as a "-1" for the originally cast vote, cancelling each other out.
For the full working circuit, see circuits/_SecretlyCancelVote.circom.
circom function Secretly_Cancel_Vote(
// Public Inputs
public root_hash_of_all_encrypted_votes, // Root hash of merkle tree with all submitted votes
public election_public_key, // RistrettoPoint
// Private Inputs
private admin_secret_salt, // bigint. Admin re-uses for all cancellations to prove anonymized votes' uniqueness
private encoded_vote_to_secretly_cancel, // RistrettoPoint of embedded string, eg: '4444-4444-4444:washington'
private votes_secret_randomizer, // bigint
private merkle_path_of_cancelled_vote, // integer[]
) {
// 1. First, prove the encrypted vote was
// in the known set of public submitted votes
// 1a) Recalculate the encrypted vote within circuit, using secret randomizer
encrypted_vote_to_cancel <== EncryptVote(election_public_key, encoded_vote_to_secretly_cancel, votes_secret_randomizer)
// 1b) Then use the merkle path to prove it's in the set of all encrypted votes
assert true === MembershipProof(encrypted_vote_to_cancel, merkle_path_of_cancelled_vote, root_hash_of_all_encrypted_votes)
//
// --- Public outputs ---
//
// 2) Prove the cancelled vote content
// - The vote that should get a -1.
public output vote_selection_to_cancel <== ExtractSelectionFromVote(encoded_vote_to_secretly_cancel) // Sliced string, like 'washington' (charCode[])
// 3) Prove the cancelled vote is unique
// - This hash can be confirmed unique outside the circuit
public output uniqueness_proof <== PoseidonHash(encoded_vote_to_secretly_cancel, admin_secret_salt)
// 3b) Prove the admin's secret salt stays consistent across all cancelled votes
// - This hash can be confirmed consistent outside the circuit
public output admin_key_consistency_hash <== PoseidonHash(admin_secret_salt)
}snarkjs r1cs info