22"""
33Verify your ballot hash (local check)
44
5- Copy the values from your voting receipt into the variables below. This script
5+ Copy the values from your vote receipt email into the variables below. This script
66re-computes the ballot hash and compares it to the hash shown on your receipt.
77A match means the receipt details you entered produce the same hash the system recorded.
88
@@ -40,10 +40,10 @@ def compute_ballot_hash(
4040 return hashlib .sha256 (data ).hexdigest ()
4141
4242# ===== YOUR BALLOT DETAILS =====
43- # Copy/paste these values from your voting receipt and the "Verify ballot receipt" page.
43+ # Copy/paste these values from your vote receipt and the "Verify ballot receipt" page.
4444
4545election_id = 1
46- credential_public_id = "your-credential-id-here"
46+ voting_credential = "your-credential-id-here"
4747
4848# Candidate IDs are what the system hashes, but voters usually think in usernames.
4949# The verify page provides a complete username -> ID mapping for the election.
@@ -53,26 +53,31 @@ def compute_ballot_hash(
5353 "carol" : 3 ,
5454}
5555
56- # Your vote choices are secret. You must fill your own ranking locally.
56+ # Your vote choices are secret. You must fill your own ranking locally
57+ # as a comma-separated list of candidate usernames in your preferred order.
5758# Example: if you ranked alice then bob, use:
58- # ranking = [candidate_ids_by_username[ "alice"], candidate_ids_by_username[" bob"]]
59- ranking = [ candidate_ids_by_username [ "alice" ]]
59+ # ranking = "alice, bob"
60+ ranking = "alice"
6061
61- weight = 1 # Usually 1 (check your receipt if different)
62- nonce = "your-nonce-from-receipt-email"
62+ weight = 1 # The weight value from your vote receipt email
63+ submission_nonce = "your-nonce-from-receipt-email"
6364expected_ballot_hash = "your-ballot-hash-from-receipt-email"
6465
66+ # ===== END OF USER INPUT =====
67+
68+ ranking = [candidate_ids_by_username [x .strip ()] for x in ranking .split (',' )]
69+
6570if __name__ == "__main__" :
6671 if not isinstance (election_id , int ) or election_id <= 0 :
6772 raise SystemExit ("election_id must be a positive integer" )
68- if not str (credential_public_id or "" ).strip ():
69- raise SystemExit ("credential_public_id must be set" )
73+ if not str (voting_credential or "" ).strip ():
74+ raise SystemExit ("voting_credential must be set" )
7075 if not isinstance (ranking , list ) or not all (isinstance (cid , int ) for cid in ranking ):
7176 raise SystemExit ("ranking must be a list of candidate IDs (integers)" )
7277 if not isinstance (weight , int ) or weight <= 0 :
7378 raise SystemExit ("weight must be a positive integer" )
74- if not str (nonce or "" ).strip ():
75- raise SystemExit ("nonce must be set" )
79+ if not str (submission_nonce or "" ).strip ():
80+ raise SystemExit ("submission_nonce must be set" )
7681
7782 expected = str (expected_ballot_hash or "" )
7883 if len (expected ) != 64 :
@@ -86,18 +91,18 @@ def compute_ballot_hash(
8691
8792 computed_hash = compute_ballot_hash (
8893 election_id = election_id ,
89- credential_public_id = credential_public_id ,
94+ credential_public_id = voting_credential ,
9095 ranking = ranking ,
9196 weight = weight ,
92- nonce = nonce ,
97+ nonce = submission_nonce ,
9398 )
9499
95100 print ("Ballot Hash Verification" )
96101 print ("=" * 60 )
97102 print (f"Election ID: { election_id } " )
98103 print (f"Your ranking: { ranking } " )
99104 print (f"Weight: { weight } " )
100- print (f"Nonce: { nonce } " )
105+ print (f"Nonce: { submission_nonce } " )
101106 print ()
102107 print (f"Computed hash: { computed_hash } " )
103108 print (f"Expected hash: { expected_ballot_hash } " )
0 commit comments