def verify(output_stream): # check that there are as many ballots in the P table as claimed assert len(p_table.rows) == election.num_ballots, "P Table has the wrong number of ballots, should be %s " % election.num_ballots num_d_tables = None # loop through partitions for p_id, partition in partitions.iteritems(): this_num_d_tables = len(partition.values()) # check that it's the same number of D tables if num_d_tables: assert this_num_d_tables == num_d_tables else: num_d_tables = this_num_d_tables # loop through d tables for that partition for d_table_id, d_table in partition.iteritems(): # check that it has the right number of ballots assert len(d_table.rows) == election.num_ballots, "D Table %s in partition %s has the wrong number of ballots, should be %s" % (d_table_id, p_id, election.num_ballots) output_stream.write("""Election ID: %s Meeting 1 Successful %s Ballots Partitions: %s %s D-Tables %s """ % (election.spec.id, election.num_ballots, partitions.keys(), num_d_tables, base.fingerprint_report()))
def verify(output_stream, codes_output_stream=None): if codes_output_stream: codes_output_stream.write('Serial #,P-table ID') for q_id in sorted(contested_ballots.values()[0].questions.keys()): codes_output_stream.write(",question %s"%q_id) codes_output_stream.write("\n") # for each contested ballot: for contested_ballot in contested_ballots.values(): # is it a cast ballot? assert cast_ballots.has_key(contested_ballot.pid) # does it verify against the original ballots assert ballots[contested_ballot.pid].verify_code_openings(contested_ballot, election.constant) if codes_output_stream: codes_output_stream.write('%s,%s' % (contested_ballot.webSerial, contested_ballot.pid)) for q_id in sorted(contested_ballot.questions.keys()): codes_output_stream.write(',"%s"' % ",".join([q['code'] for q in contested_ballot.questions[q_id].values()])) codes_output_stream.write("\n") # go through the contested ballots output_stream.write("""Election ID: %s Contested Ballots Audit Successful %s ballots contested and opened successfully %s """ % (election.spec.id, len(contested_ballots.keys()), base.fingerprint_report()))
def verify(output_stream, codes_output_stream=None): # make sure none of the actual votes use ballots that were audited in Meeting2: assert set(p_table_votes.rows.keys()).isdisjoint(set(meeting2.challenge_row_ids)) if codes_output_stream: BALLOTS = {} def new_code(webSerial, pid, q_id, s_id, confirmation_code): if not BALLOTS.has_key(webSerial): BALLOTS[webSerial] = {'pid': pid, 'questions': {}} if not BALLOTS[webSerial]['questions'].has_key(q_id): BALLOTS[webSerial]['questions'][q_id] = [] BALLOTS[webSerial]['questions'][q_id].append(confirmation_code) else: new_code = None # check the openings for ballot_open in ballots_with_codes.values(): ballot = ballots[ballot_open.pid] assert ballot.verify_code_openings(ballot_open, election.constant, code_callback_func = new_code) # check that the coded votes correspond to the confirmation code openings assert ballot_open.verify_encodings(election, p_table_votes) # we get the half-decrypted votes, but there's nothing to verify yet # we write out the codes if new_code: codes_output_stream.write('Serial #,P-table ID') for q_id in sorted(BALLOTS.values()[0]['questions'].keys()): codes_output_stream.write(",question %s"%q_id) codes_output_stream.write("\n") for serial in sorted(BALLOTS.keys()): codes_output_stream.write('%s,%s' % (serial, BALLOTS[serial]['pid'])) for q_id in sorted(BALLOTS[serial]['questions'].keys()): codes_output_stream.write(',"%s"' % ",".join(BALLOTS[serial]['questions'][q_id])) codes_output_stream.write("\n") # we get the R table, and that can be tallied based on the type of question # however, just to separate the cryptographic verification from the actual # counting, which should be a lot simpler, the counting of the R table is done # in the tally.py program. output_stream.write("""Election ID: %s Meeting 3 Successful %s ballots cast The tally can now be computed, not fully verified yet, using tally.py %s """ % (election.spec.id, len(ballots_with_codes), base.fingerprint_report()))
def verify(output_stream, codes_output_stream=None): if codes_output_stream: BALLOTS = {} def new_code(webSerial, pid, q_id, s_id, confirmation_code): if not BALLOTS.has_key(webSerial): BALLOTS[webSerial] = {'pid': pid, 'questions': {}} if not BALLOTS[webSerial]['questions'].has_key(q_id): BALLOTS[webSerial]['questions'][q_id] = [] BALLOTS[webSerial]['questions'][q_id].append(confirmation_code) else: new_code = None # check codes for spoiled_ballot in spoiled_ballots.values(): # does it verify against the original ballots assert ballots[spoiled_ballot.pid].verify_code_openings(spoiled_ballot, election.constant, code_callback_func = new_code) # we just verify that the D and P tables are opened properly # same as meeting2, only without a specific challenge set assert meeting2.verify_open_p_and_d_tables(election, meeting1.p_table, meeting1.partitions, spoiled_p_table, spoiled_partitions), "bad reveal of P and D tables" # we write out the codes if new_code: codes_output_stream.write('Serial #,P-table ID') for q_id in sorted(BALLOTS.values()[0]['questions'].keys()): codes_output_stream.write(",question %s"%q_id) codes_output_stream.write("\n") for serial in sorted(BALLOTS.keys()): codes_output_stream.write('%s,%s' % (serial, BALLOTS[serial]['pid'])) for q_id in sorted(BALLOTS[serial]['questions'].keys()): codes_output_stream.write(',"%s"' % ",".join(BALLOTS[serial]['questions'][q_id])) codes_output_stream.write("\n") # go through the contested ballots output_stream.write("""Election ID: %s Spoiled Ballots Audit Successful %s ballots spoiled and opened successfully %s """ % (election.spec.id, len(spoiled_ballots.keys()), base.fingerprint_report()))
def verify(output_stream): p_table_permutations = {} # check the generation of the challenge rows # we assume that the length of the challenge list is the right one challenge_row_ids_ints = set([int(c) for c in challenge_row_ids]) challenges_match_randomness = False seed = meeting_two_random_data + election.constant if challenge_row_ids_ints == set(base.generate_random_int_list(seed, election.num_ballots, len(challenge_row_ids))): challenges_match_randomness = True else: import pdb; pdb.set_trace() # check that the open P table rows match the challenge assert sorted(challenge_row_ids) == sorted([r['id'] for r in response_p_table.rows.values()]), "challenges don't match revealed row IDs in P table" # check that the P and D tables are properly revealed assert verify_open_p_and_d_tables(election, p_table, partitions, response_p_table, response_partitions), "bad reveal of P and D tables" print """Election ID: %s Meeting 2 Successful %s ballots challenged and answered successfully. Challenges Match Randomness? %s %s """ % (election.spec.id, len(challenge_row_ids), str(challenges_match_randomness).upper(), base.fingerprint_report())
def verify(output_stream): # verify that challenges are appropriately generated challenges_match_randomness = True # we assume that one D table always opens on the same side # we do a bit of an odd thing here to keep the partitions and d tables in order # because that's how counter is decided counter = 0 # a dictionary of partition_ids, with values a dictionary of d_table ID expected_challenge_sides = {} seed = meeting_four_random_data + election.constant for p_id in sorted(cast_ballot_partitions.keys()): partition = cast_ballot_partitions[p_id] expected_challenge_sides[p_id] = {} # get the D tables ordered by their integer ID for d_table in data.sort_by_id(partition.values()): instance_id = d_table.id # which side is this d table opened on? expected_challenge_sides[p_id][instance_id] = ("LEFT","RIGHT")[base.prng(seed,counter,2)] counter += 1 partition_map = election.partition_map partition_map_choices = election.partition_map_choices # go through the challenges and verify the corresponding commitments for p_id, partition in d_table_challenges.iteritems(): for instance_id, d_table_challenge in partition.iteritems(): d_table = d_table_commitments[p_id][instance_id] d_table_response = d_table_responses[p_id][instance_id] # check that the open rows now are disjoint from the open rows before assert set(d_table_challenge.rows.keys()).isdisjoint(set(already_open_d_tables[p_id][instance_id].rows.keys())), 'some challenges repeat the challenges from meeting2' # check opening of the new challenges for row in d_table_challenge.rows.values(): # does it match the randomness? if row['side'] != expected_challenge_sides[p_id][instance_id]: import pdb; pdb.set_trace() challenges_match_randomness = False # response row response_row = d_table_response.rows[row['id']] # partially decrypted choices, d3 out of d2,d3,d4, so index 1. try: d_choices = cast_ballot_partitions[p_id][instance_id].get_permutations_by_row_id(row['id'], partition_map_choices[p_id])[1] except: import pdb; pdb.set_trace() print "oy" # check the appropriate side if row['side'] == 'LEFT': # check proper reveal assert d_table.check_cl(p_id, instance_id, response_row, election.constant) d_left_perm = [data.Permutation(p) for p in d_table_response.get_permutations_by_row_id(row['id'], partition_map[p_id])[0]] # get the corresponding P3 permutation (index 2, then partition) p_choices = p_table_votes.get_permutations_by_row_id(response_row['pid'], partition_map_choices)[2][p_id] for q_num, p_choice in enumerate(p_choices): assert d_left_perm[q_num].permute_list(p_choice) == d_choices[q_num] else: # check reveal assert d_table.check_cr(p_id, instance_id, response_row, election.constant) # check right-hand permutation d_right_perm = [data.Permutation(p) for p in d_table_response.get_permutations_by_row_id(row['id'], partition_map[p_id])[2]] # get the corresponding R-table permutation (partition, then index 0) r_choices = r_tables_by_partition[p_id].get_permutations_by_row_id(response_row['rid'], partition_map_choices[p_id])[0] for q_num, r_choice in enumerate(r_choices): assert d_right_perm[q_num].permute_list(d_choices[q_num]) == r_choice output_stream.write("""Election ID: %s Meeting 4 Successful Challenges Match Randomness? %s %s """ % (election.spec.id, challenges_match_randomness, base.fingerprint_report()))