def mix_phase_generate_permutations(self, row_index, col_index): assert row_index == 'a' election = self.election # generate permutations (and inverses) used in each column # in practice, these could be generated by row 0 server # and sent securely to the others in the same column. for race_id in election.race_ids: j = col_index rand_name = self.sdb[race_id]['a'][j]['rand_name'] sv.init_randomness_source(rand_name) # optional - TODO remove after transition to unshared memory only for k in election.k_list: pi = sv.random_permutation(election.p_list, rand_name) pi_inv = sv.inverse_permutation(pi) for i in self.row_list: self.sdb[race_id][i][j][k]['pi'] = pi self.sdb[race_id][i][j][k]['pi_inv'] = pi_inv dict_update_to_share = dict() for race_id in election.race_ids: dict_update_to_share[race_id] = dict() for i in self.row_list: dict_update_to_share[race_id][i] = dict() j = col_index assert type(j)==int dict_update_to_share[race_id][i][j] = dict() for k in election.k_list: dict_update_to_share[race_id][i][j][k] = dict() dict_update_to_share[race_id][i][j][k]['pi'] = self.sdb[race_id][i][j][k]['pi'] dict_update_to_share[race_id][i][j][k]['pi_inv'] = self.sdb[race_id][i][j][k]['pi_inv'] return dict_update_to_share
def read_cut_verifier_challenges(sbb_dict, sbb, db): """ Read verifier challenges from proof:cutandchoose_verifier_challenges; save into db. """ chs = sbb_dict['proof:cutandchoose_verifier_challenges']['challenges'] assert isdict(chs, ['cut']) assert isdict(chs['cut'], ['icl', 'opl']) icl = chs['cut']['icl'] assert isinstance(icl, list) assert len(icl) == db['n_reps'] // 2 assert set(icl).issubset(db['k_list']) opl = chs['cut']['opl'] assert isinstance(opl, list) assert len(opl) == db['n_reps'] // 2 assert set(opl).issubset(db['k_list']) assert set(icl).isdisjoint(set(opl)) db['icl'] = icl db['opl'] = opl # now check that icl and opl are consistent with sbb_hash # see make_cut_verifier_challenges in sv_prover.py rand_name = 'cut_verifier_challenges' sbb_hash = sbb_dict['proof:cutandchoose_verifier_challenges']['sbb_hash'] stop_before_header = 'proof:cutandchoose_verifier_challenges' sbb_hash2 = sv.bytes2hex(hash_sbb(sbb, stop_before_header)) assert sbb_hash2 == sbb_hash, "sbb_hash2: " + str( sbb_hash2) + "sbb_hash: " + str(sbb_hash) sv.init_randomness_source(rand_name, sv.hex2bytes(sbb_hash)) pi = sv.random_permutation(db['n_reps'], rand_name) m = db['n_reps'] // 2 pi = [pi[i] for i in range(2 * m)] icl2 = [db['k_list'][i] for i in sorted(pi[:m])] opl2 = [db['k_list'][i] for i in sorted(pi[m:])] assert icl2 == icl assert opl2 == opl print('read_cut_verifier_challenges: successful.')
def make_cut_and_choose_challenges(election, rand_name, challenges): """ Return random split of [0,1,...,n_reps-1] into two lists. Use specified randomness source. This icl/opl split will be the same for all races. (This can be easily changed if desired.) # icl = subset of election.k_list used for "input comparison" # opl = subset of election.k_list used for "output production" Save results in challenges dict. """ m = election.n_reps // 2 pi = sv.random_permutation(2 * m, rand_name) pi = [pi[i] for i in range(2 * m)] # icl = copies for input comparison # opl = copies for output production icl = [election.k_list[i] for i in sorted(pi[:m])] opl = [election.k_list[i] for i in sorted(pi[m:])] challenges['cut'] = {'icl': icl, 'opl': opl}
def make_cut_and_choose_challenges(election, rand_name, challenges): """ Return random split of [0,1,...,n_reps-1] into two lists. Use specified randomness source. This icl/opl split will be the same for all races. (This can be easily changed if desired.) # icl = subset of election.k_list used for "input comparison" # opl = subset of election.k_list used for "output production" Save results in challenges dict. """ m = election.n_reps // 2 pi = sv.random_permutation(2*m, rand_name) pi = [pi[i] for i in range(2*m)] # icl = copies for input comparison # opl = copies for output production icl = [election.k_list[i] for i in sorted(pi[:m])] opl = [election.k_list[i] for i in sorted(pi[m:])] challenges['cut'] = {'icl': icl, 'opl': opl}
def read_verifier_challenges(sbb_dict, sbb, db): """ Read verifier challenges from proof:verifier_challenges; save into db. """ chs = sbb_dict['proof:verifier_challenges']['challenges'] assert isdict(chs, ['cut', 'leftright']) assert isdict(chs['cut'], ['icl', 'opl']) icl = chs['cut']['icl'] assert isinstance(icl, list) assert len(icl) == db['n_reps'] // 2 assert set(icl).issubset(db['k_list']) opl = chs['cut']['opl'] assert isinstance(opl, list) assert len(opl) == db['n_reps'] // 2 assert set(opl).issubset(db['k_list']) assert set(icl).isdisjoint(set(opl)) db['icl'] = icl db['opl'] = opl leftright = chs['leftright'] assert isdict(leftright, db['race_ids']) for race_id in leftright.keys(): lr_dict = leftright[race_id] assert set(lr_dict.keys()) == set(db['p_list']) for p in db['p_list']: lr = lr_dict[p] assert lr == 'left' or lr == 'right' db['leftright'] = leftright # now check that icl, opl, and leftright are consistent with sbb_hash # see make_verifier_challenges in sv_prover.py rand_name = 'verifier_challenges' sbb_hash = sbb_dict['proof:verifier_challenges']['sbb_hash'] stop_before_header = 'proof:verifier_challenges' sbb_hash2 = sv.bytes2hex(hash_sbb(sbb, stop_before_header)) assert sbb_hash2 == sbb_hash sv.init_randomness_source(rand_name, sv.hex2bytes(sbb_hash)) pi = sv.random_permutation(db['n_reps'], rand_name) m = db['n_reps'] // 2 pi = [pi[i] for i in range(2 * m)] icl2 = [db['k_list'][i] for i in sorted(pi[:m])] opl2 = [db['k_list'][i] for i in sorted(pi[m:])] assert icl2 == icl assert opl2 == opl leftright2 = make_left_right_challenges(rand_name, db) assert leftright2 == leftright print('read_verifier_challenges: successful.')
def read_verifier_challenges(sbb_dict, sbb, db): """ Read verifier challenges from proof:verifier_challenges; save into db. """ chs = sbb_dict['proof:verifier_challenges']['challenges'] assert isdict(chs, ['cut', 'leftright']) assert isdict(chs['cut'], ['icl', 'opl']) icl = chs['cut']['icl'] assert isinstance(icl, list) assert len(icl) == db['n_reps'] // 2 assert set(icl).issubset(db['k_list']) opl = chs['cut']['opl'] assert isinstance(opl, list) assert len(opl) == db['n_reps'] // 2 assert set(opl).issubset(db['k_list']) assert set(icl).isdisjoint(set(opl)) db['icl'] = icl db['opl'] = opl leftright = chs['leftright'] assert isdict(leftright, db['race_ids']) for race_id in leftright.keys(): lr_dict = leftright[race_id] assert set(lr_dict.keys()) == set(db['p_list']) for p in db['p_list']: lr = lr_dict[p] assert lr == 'left' or lr == 'right' db['leftright'] = leftright # now check that icl, opl, and leftright are consistent with sbb_hash # see make_verifier_challenges in sv_prover.py rand_name = 'verifier_challenges' sbb_hash = sbb_dict['proof:verifier_challenges']['sbb_hash'] stop_before_header = 'proof:verifier_challenges' sbb_hash2 = sv.bytes2hex(hash_sbb(sbb, stop_before_header)) assert sbb_hash2 == sbb_hash sv.init_randomness_source(rand_name, sv.hex2bytes(sbb_hash)) pi = sv.random_permutation(db['n_reps'], rand_name) m = db['n_reps'] // 2 pi = [pi[i] for i in range(2*m)] icl2 = [db['k_list'][i] for i in sorted(pi[:m])] opl2 = [db['k_list'][i] for i in sorted(pi[m:])] assert icl2 == icl assert opl2 == opl leftright2 = make_left_right_challenges(rand_name, db) assert leftright2 == leftright print('read_verifier_challenges: successful.')
def mix(self): """ Mix votes. Information flows left to right. """ election = self.election # replicate input to become first-column x inputs for each race & pass for race_id in election.race_ids: for k in election.k_list: for i in self.row_list: x = self.sdb[race_id][i][0]['x'] # dict of n x's self.sdb[race_id][i][0][k]['x'] = x.copy() # generate permutations (and inverses) used in each column # in practice, these could be generated by row 0 server # and sent securely to the others in the same column. for race_id in election.race_ids: for j in range(self.cols): rand_name = self.sdb[race_id]['a'][j]['rand_name'] for k in election.k_list: pi = sv.random_permutation(election.p_list, rand_name) pi_inv = sv.inverse_permutation(pi) for i in self.row_list: self.sdb[race_id][i][j][k]['pi'] = pi self.sdb[race_id][i][j][k]['pi_inv'] = pi_inv # generate obfuscation values used in each column # in practice, these could be generated by row 0 server # and sent securely to the others in the same column. for race in election.races: race_id = race.race_id for j in range(self.cols): rand_name = self.sdb[race_id]['a'][j]['rand_name'] for k in election.k_list: fuzz_dict = dict() # fuzz_dict[i][pnn] for i in self.row_list: fuzz_dict[i] = dict() for v in election.p_list: share_list = sv.share(0, self.rows, self.threshold, rand_name, race.race_modulus) for row, i in enumerate(self.row_list): fuzz_dict[i][v] = share_list[row][1] for i in self.row_list: # note that fuzz_dict[i] is dict of size n self.sdb[race_id][i][j][k]['fuzz_dict'] = fuzz_dict[i] # process columns left-to-right, mixing as you go for race in self.election.races: race_id = race.race_id race_modulus = race.race_modulus for j in range(self.cols): for k in election.k_list: for i in self.row_list: # shuffle first pi = self.sdb[race_id][i][j][k]['pi'] # length n # note that pi is independent of i x = self.sdb[race_id][i][j][k]['x'] # length n xp = sv.apply_permutation(pi, x) # length n # then obfuscate by adding "fuzz" fuzz_dict = self.sdb[race_id][i][j][k]['fuzz_dict'] xpo = dict() for v in election.p_list: xpo[v] = (xp[v] + fuzz_dict[v]) % race_modulus y = xpo self.sdb[race_id][i][j][k]['y'] = y # this column's y's become next column's x's. # in practice would be sent via secure channels if j < self.cols - 1: self.sdb[race_id][i][j+1][k]['x'] = y
def mix(self): """ Mix votes. Information flows left to right. """ election = self.election # replicate input to become first-column x inputs for each race & pass for race_id in election.race_ids: for k in election.k_list: for i in self.row_list: x = self.sdb[race_id][i][0]['x'] # dict of n x's self.sdb[race_id][i][0][k]['x'] = x.copy() # generate permutations (and inverses) used in each column # in practice, these could be generated by row 0 server # and sent securely to the others in the same column. for race_id in election.race_ids: for j in range(self.cols): rand_name = self.sdb[race_id]['a'][j]['rand_name'] for k in election.k_list: pi = sv.random_permutation(election.p_list, rand_name) pi_inv = sv.inverse_permutation(pi) for i in self.row_list: self.sdb[race_id][i][j][k]['pi'] = pi self.sdb[race_id][i][j][k]['pi_inv'] = pi_inv # generate obfuscation values used in each column # in practice, these could be generated by row 0 server # and sent securely to the others in the same column. for race in election.races: race_id = race.race_id for j in range(self.cols): rand_name = self.sdb[race_id]['a'][j]['rand_name'] for k in election.k_list: fuzz_dict = dict() # fuzz_dict[i][pnn] for i in self.row_list: fuzz_dict[i] = dict() for v in election.p_list: share_list = sv.share(0, self.rows, self.threshold, rand_name, race.race_modulus) for row, i in enumerate(self.row_list): fuzz_dict[i][v] = share_list[row][1] for i in self.row_list: # note that fuzz_dict[i] is dict of size n self.sdb[race_id][i][j][k]['fuzz_dict'] = fuzz_dict[i] # process columns left-to-right, mixing as you go for race in self.election.races: race_id = race.race_id race_modulus = race.race_modulus for j in range(self.cols): for k in election.k_list: for i in self.row_list: # shuffle first pi = self.sdb[race_id][i][j][k]['pi'] # length n # note that pi is independent of i x = self.sdb[race_id][i][j][k]['x'] # length n xp = sv.apply_permutation(pi, x) # length n # then obfuscate by adding "fuzz" fuzz_dict = self.sdb[race_id][i][j][k]['fuzz_dict'] xpo = dict() for v in election.p_list: xpo[v] = (xp[v] + fuzz_dict[v]) % race_modulus y = xpo self.sdb[race_id][i][j][k]['y'] = y # this column's y's become next column's x's. # in practice would be sent via secure channels if j < self.cols - 1: self.sdb[race_id][i][j + 1][k]['x'] = y