def send_response_json(request, response, destination): print("--->" + str(destination)) print("\t" + SC.MSG_TITLE + ": " + str(response[SC.MSG_TITLE])) #print("\t" + SC.MSG_BODY + ": " + str(response[SC.MSG_BODY])) global data_transferred_size data_transferred_size += get_size(response) serialized_response = bytes(sv.dumps(response), SC.ENCODING_TYPE) request.sendall(serialized_response) if SC.DEBUG_FLAG: print("data_transferred_size", data_transferred_size)
def hash_sbb(self, public): """ Return a (tweaked) hash of the sbb contents. """ board = self.board # next is commented out since we have no no-public posting # in the current code. if False: if public: board = [item for item in board if item[0][0] != "("] board_str = sv.dumps(board) sbb_trunc = [] for item in board: sbb_trunc.append(item) board_str2 = sv.dumps(sbb_trunc) #sv.dump([item for item in sbb_trunc if item[0]=='proof:output_commitments'], 'proof_output_commitments_SBBVERSION.txt') assert board_str2 == board_str, "board_str2: " + board_str2 + " board_str: " + board_str hash_tweak = "hash_sbb" return sv.secure_hash( board_str, hash_tweak, iterate=False ) # make iterate=True to slow down adversarial attacks change in sv_verifier.py as well
def hash_sbb(self, public): """ Return a (tweaked) hash of the sbb contents. """ board = self.board # next is commented out since we have no no-public posting # in the current code. if False: if public: board = [item for item in board if item[0][0] != "("] board_str = sv.dumps(board) hash_tweak = "hash_sbb" return sv.secure_hash(board_str, hash_tweak, iterate=True)
def check_opened_output_commitments(sbb_dict, db): """ Check that opened output commitments open correctly. """ coms = \ sbb_dict['proof:outcome_check']\ ['opened_output_commitments'] assert isdict(coms, db['race_ids']) for race_id in db['race_ids']: assert isdict(coms[race_id], db['opl']), "sv.dumps(coms[race_id]): " + sv.dumps( coms[race_id]) + " db['opl']: " + sv.dumps(db['opl']) for k in db['opl']: assert isdict(coms[race_id][k], db['p_list']) for p in db['p_list']: assert isdict(coms[race_id][k][p], db['row_list']) for i in db['row_list']: assert isdict(coms[race_id][k][p][i], ['ru', 'rv', 'u', 'v', 'y']) ru = coms[race_id][k][p][i]['ru'] assert isinstance(ru, str) rv = coms[race_id][k][p][i]['rv'] assert isinstance(rv, str) u = coms[race_id][k][p][i]['u'] assert isinstance(u, int) and \ 0 <= u < db['races'][race_id]['race_modulus'] v = coms[race_id][k][p][i]['v'] assert isinstance(v, int) and \ 0 <= v < db['races'][race_id]['race_modulus'] y = coms[race_id][k][p][i]['y'] assert isinstance(y, int) and \ 0 <= y < db['races'][race_id]['race_modulus'] assert y == (u + v) % db['races'][race_id]['race_modulus'] cu = sbb_dict['proof:output_commitments']\ ['commitments'][race_id][k][p][i]['cu'] cv = sbb_dict['proof:output_commitments']\ ['commitments'][race_id][k][p][i]['cv'] assert cu == sv.com(u, ru) assert cv == sv.com(v, rv) print('check_opened_output_commitments: passed.')
def hash_sbb(sbb, stop_before_header): """ Return a (tweaked) hash of the sbb contents, including all items up to (but not including) the item with header equal to stop_before_header. (Copied from sv_prover.py) """ sbb_trunc = [] for item in sbb: if item[0] == stop_before_header: break else: sbb_trunc.append(item) sbb_trunc_str = sv.dumps(sbb_trunc) hash_tweak = "hash_sbb" # use iterated hashing to slow down adversarial attack return sv.secure_hash(sbb_trunc_str, hash_tweak, iterate=True)
def hash_sbb(sbb, stop_before_header): """ Return a (tweaked) hash of the sbb contents, including all items up to (but not including) the item with header equal to stop_before_header. (Copied from sv_prover.py) """ sbb_trunc = [] for item in sbb: if item[0] == stop_before_header: break else: sbb_trunc.append(item) sbb_trunc_str = sv.dumps(sbb_trunc) #sv.dump([item for item in sbb_trunc if item[0]=='proof:output_commitments'], 'proof_output_commitments_VERIFIERVERSION.txt') hash_tweak = "hash_sbb" # use iterated hashing to slow down adversarial attack - change in sv_sbb.py as well return sv.secure_hash(sbb_trunc_str, hash_tweak, iterate=False)
def check_receipts(sbb_dict, db): """ Check that receipts are consistent with cast vote commitments. """ receipt_ballot_ids = set(db['receipts'].keys()) cast_vote_dict = sbb_dict['casting:votes']['cast_vote_dict'] for race_id in cast_vote_dict: for p in cast_vote_dict[race_id]: d = dict() for i in cast_vote_dict[race_id][p]: ballot_id = cast_vote_dict[race_id][p][i]['ballot_id'] cu = cast_vote_dict[race_id][p][i]['cu'] cv = cast_vote_dict[race_id][p][i]['cv'] d[i] = {'cu': cu, 'cv': cv} cv_receipt_data = [ballot_id, d] cv_receipt_data_str = sv.dumps(cv_receipt_data) cv_hash = sv.bytes2base64(sv.secure_hash(cv_receipt_data_str)) assert cv_hash == db['receipts'][ballot_id]['hash'] receipt_ballot_ids.remove(ballot_id) assert len(receipt_ballot_ids) == 0 print("check_receipts: passed.")
def json_client(ip, port, title, origin, body="empty body", auth="empty auth"): message = { SC.MSG_TITLE: title, SC.MSG_BODY: body, SC.MSG_ORIGIN: origin, SC.MSG_AUTH: auth } global data_transferred_size data_transferred_size += get_size(message) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if ip == "": ip = "127.0.0.1" destination_str = str([ip, port]) print("--->" + destination_str) print("\t" + SC.MSG_TITLE + ": " + str(message[SC.MSG_TITLE])) #print("\t" + SC.MSG_BODY + ": " + str(message[SC.MSG_BODY])) while True: if s.connect_ex((ip, port)): print("Connection Refused Error, trying again") time.sleep(0.001) else: break s.send(bytes(sv.dumps(message), SC.ENCODING_TYPE)) raw_response_string = recv_timeout(s) # raw_response_string = s.recv(SC.MSG_BUFFER_SIZE).decode(SC.ENCODING_TYPE) #print("raw_response_string: ", raw_response_string) try: response = sv.loads(raw_response_string) except Exception as e: print("Exception while loading serialized response: ", e) f = open('raw_response_string.txt', 'w') f.write(raw_response_string) f.close() data_transferred_size += get_size(response) print("<---" + destination_str) print("\t" + SC.MSG_TITLE + ": " + str(response[SC.MSG_TITLE])) #print("\t" + SC.MSG_BODY + ": " + str(response[SC.MSG_BODY])) s.close() if SC.DEBUG_FLAG: print("data_transferred_size", data_transferred_size) return response
def print_sdb(self, filters = []): d = self.sdb for f in filters: d = d[f] print("print_sdb filters:"+str(filters)+"\n"+sv.dumps(d))
def run_election(self): """ Run a (simulated) election. """ time_performance = {} pretty_start_time = time.strftime("%Y-%m-%dT%H:%M:%S%z") start_time = time.time() time_performance["0 Election begins"] = time.time() - start_time # 0B. Start Controller Server # Create the server, binding to 127.0.0.1 server = ControllerServer((SC.CONTROLLER_HOST, SC.CONTROLLER_PORT), ControllerHandler) #or use a ThreadedTCPServer to handle each request in a different thread. # Activate the server; this will keep running until you interrupt the program with Ctrl+C server_thread = threading.Thread(target=server.serve_forever, daemon = True) #daemon threads allow us to finish the program execution, even though some threads may be running server_thread.start() time_performance["0.B Start Controller Server"] = time.time() - start_time # 1. Start Generic Servers, and have them ping the controller. Wait for enough servers num_servers_per_role = self.get_num_servers() # Waiting to get enough servers server.wait_for_servers(num_servers_per_role) time_performance["1 Ping Controller"] = time.time() - start_time # 2. Controller Initializes each server # assigning and communicating individually initialization_params_per_role = self.get_initialization_params_per_role() server.assign_server_roles(num_servers_per_role, initialization_params_per_role) server.test_assigned_server_roles() self.setup_keys() # TODO actually do key setup # 2.1 Posting setup info to SBB self.post_setup_info_to_sbb(server) time_performance["2 Assign Roles"] = time.time() - start_time # 3. Controller broadcast Network Info server.broadcast_network() time_performance["3 Broadcast all roles"] = time.time() - start_time # 4. Produce Votes server.ask_to_produce_votes(self.election_id) # Before returning Voter asks SBB to post voter receipts # (in practice SBB does need to post it, voters would get it # and they could compute hash from commitments in SBB) time_performance["4 Produce votes"] = time.time() - start_time # 5. Distribute Votes server.ask_voters_to_distribute_votes() # Before returning Voter asks SBB to post voter commitments. # This posting to SBB can be transferred to the 1st column of Mix Servers, # to handle other adversarial models time_performance["5 Distribute votes"] = time.time() - start_time # 6. Mix Votes server.ask_mixservers_to_mix() time_performance["6 Mix"] = time.time() - start_time # 7. Prove server.ask_mixservers_for_proofs() # TODO modify prover so that posts come from each server based on the info they have, # if they don't have info keep {} so that update_nested_dict does not mess it up time_performance["7 Prove"] = time.time() - start_time # 8. Tally server.ask_mixservers_for_tally() time_performance["8 Tally"] = time.time() - start_time # 9. Stop election and close sbb server.ask_sbb_to_post("election:done.", {"election_id": self.election_id}) server.ask_sbb_to_close() print("election finished.") print() # -1. Verify sbb_filename = self.election_id + ".sbb.txt" server.ask_sbb_to_print(public=True, sbb_filename=sbb_filename) print("beginning verification...") server.ask_sbb_to_verify(sbb_filename) print("done. (", self.election_id, ")") time_performance["9 Verify SBB"] = time.time() - start_time # -2. Get performance stats and save it to disk if SC.DEBUG_FLAG: performance_stats = {} print("Start time for simulation:", pretty_start_time) performance_stats["Start time for simulation:"] = pretty_start_time print("Network Information:", sv.dumps(server.servers_alive)) performance_stats["Network Information:"] = server.servers_alive print("time_performance:", sv.dumps(time_performance)) performance_stats["time_performance"] = time_performance print("Election Parameters:", sv.dumps(self.election_parameters)) performance_stats["Election Parameters:"] = self.election_parameters print("Data transferred:", ServerController.data_transferred_size) performance_stats["Data transferred by Controller:"] = ServerController.data_transferred_size print("Performance stats written to " + self.election_id +".performance_stats.txt") sv.dump(performance_stats, self.election_id+".performance_stats.txt") # write performance stats to disk # include network information and date (to describe test) # include data transferred for each server # include overall time to run election, time_performance stop = input("Stop?") server.shutdown() sys.exit()
def cast_vote(self, race): """ Cast random vote for this voter for this race in simulated election. Of course, in a real election, choices come from voter via tablet. """ election = self.election cvs = election.cast_votes race_id = race.race_id race_modulus = race.race_modulus rand_name = self.rand_name px = self.px # cast random vote (for this simulation, it's random) choice_str = race.random_choice() # returns a string choice_int = race.choice_str2int(choice_str) # convert to integer # ballot_id is random hex string of desired length ballot_id_len = election.ballot_id_len ballot_id = sv.bytes2hex(sv.get_random_from_source(rand_name)) ballot_id = ballot_id[:ballot_id_len] assert len(ballot_id) == election.ballot_id_len # secret-share choice n = election.server.rows t = election.server.threshold share_list = sv.share(choice_int, n, t, rand_name, race_modulus) # double-check that shares reconstruct to desired choice assert choice_int == sv.lagrange(share_list, n, t, race_modulus) # double-check that shares are have indices 1, 2, ..., n assert all([share_list[i][0] == i + 1 for i in range(n)]) # then strip off indices, since they are equal to row number + 1 share_list = [share[1] for share in share_list] # save ballots on election data structure for row, x in enumerate(share_list): (u, v) = sv.get_sv_pair(x, rand_name, race_modulus) ru = sv.bytes2base64(sv.get_random_from_source(rand_name)) rv = sv.bytes2base64(sv.get_random_from_source(rand_name)) cu = sv.com(u, ru) cv = sv.com(v, rv) i = election.server.row_list[row] vote = { "ballot_id": ballot_id, "x": x, "u": u, "v": v, "ru": ru, "rv": rv, "cu": cu, "cv": cv } cvs[race_id][px][i] = vote # compute voter receipt as hash of her ballot_id and commitments # note that voter gets a receipt for each race she votes in receipt_data = [ballot_id] d = dict() for i in election.server.row_list: cu = cvs[race_id][px][i]['cu'] cv = cvs[race_id][px][i]['cv'] d[i] = {'cu': cu, 'cv': cv} receipt_data.append(d) receipt_data_str = sv.dumps(receipt_data) receipt_hash = sv.bytes2base64(sv.secure_hash(receipt_data_str)) self.receipts[ballot_id] = {'race_id': race_id, 'hash': receipt_hash}
def get_size(msg): return len(sv.dumps(msg))