def __compute_guardian_challenge_threshold_separated(self, public_key: int, commitment: int) -> int: """ computes challenge (c_ij) with hash, H(cij = H(base hash, public key, commitment) % q, each guardian has quorum number of these challenges :param public_key: public key, under each guardian, previously listed as k :param commitment: commitment, under each guardian, previously listed as h :return: a challenge value of a guardian, separated by quorum """ return number.mod_p(number.hash_elems(self.base_hash, public_key, commitment))
def verify_tracking_hashes(self, hashes_dic: dict) -> bool: """ verifies the tracking hash chain correctness NOTE: didn't check the first and closing hashes :param hashes_dic: a dictionary of "previous tracking - current tracking " hash code pairs :return: True if all the tracking hashes satisfy Bi, Hi = H(Hi-1, D, T, Bi) """ error = self.initialize_error() # get all previous and current hashes prev_hashes = set(hashes_dic.values()) curr_hashes = set(hashes_dic.keys()) # find the set that only contains first and last hash union_set = prev_hashes.union(curr_hashes) intersection_set = prev_hashes.intersection(curr_hashes) first_last_set = union_set - intersection_set first_hash, last_hash = 0, 0 # find the first and last hash for h in first_last_set: if h in prev_hashes: first_hash = h elif h in curr_hashes: last_hash = h # verify the first hash H0 = H(Q-bar) zero_hash = number.hash_elems(self.extended_hash) print(hashes_dic) print(first_last_set) print(self.extended_hash) print(zero_hash) print(first_hash) if not number.equals(int(zero_hash), int(first_hash)): error = self.set_error() # verify the closing hash, H-bar = H(Hl, 'CLOSE') closing_hash_computed = number.hash_elems(last_hash, 'CLOSE') return not error
def verify_selection_validity(self) -> bool: """ verify the encryption validity of a selection within a contest :return: True if no error occurs, False if some errors """ error = self.initialize_error() # get dictionaries proof_dic = self.selection_dic.get('proof') cipher_dic = self.selection_dic.get('ciphertext') # get values selection_id = self.selection_dic.get('object_id') zero_pad = int(proof_dic.get('proof_zero_pad')) # a0 one_pad = int(proof_dic.get('proof_one_pad')) # a1 zero_data = int(proof_dic.get('proof_zero_data')) # b0 one_data = int(proof_dic.get('proof_one_data')) # b1 zero_challenge = int(proof_dic.get('proof_zero_challenge')) # c0 one_challenge = int(proof_dic.get('proof_one_challenge')) # c1 zero_response = int(proof_dic.get('proof_zero_response')) # v0 one_response = int(proof_dic.get('proof_one_response')) # v1 # point 1: check alpha, beta, a0, b0, a1, b1 are all in set Zrp if not (self.__check_params_within_zrp(cipher_dic) and self.__check_params_within_zrp(proof_dic)): error = self.set_error() # point 3: check if the given values, c0, c1, v0, v1 are each in the set zq if not self.__check_params_within_zq(proof_dic): error = self.set_error() # point 2: conduct hash computation, c = H(Q-bar, (alpha, beta), (a0, b0), (a1, b1)) challenge = number.hash_elems(self.extended_hash, self.pad, self.data, zero_pad, zero_data, one_pad, one_data) # point 4: c = c0 + c1 mod q is satisfied if not self.__check_hash_comp(challenge, zero_challenge, one_challenge): error = self.set_error() # point 5: check 2 chaum-pedersen proofs, zero proof and one proof if not (self.__check_cp_proof_zero_proof( self.pad, self.data, zero_pad, zero_data, zero_challenge, zero_response) and self.__check_cp_proof_one_proof( self.pad, self.data, one_pad, one_data, one_challenge, one_response)): error = self.set_error() if error: print(selection_id + ' validity verification failure.') return not error
def verify_tracking_hash(self) -> bool: """ verify all the middle (index 1 to n) tracking hash :return: true if all the tracking hashes are correct, false otherwise """ crypto_hash = self.ballot_dic.get('crypto_hash') prev_hash, curr_hash = self.get_tracking_hash() timestamp = self.get_timestamp() curr_hash_computed = number.hash_elems(prev_hash, timestamp, crypto_hash) res = number.equals(int(curr_hash), int(curr_hash_computed)) return res
def __check_challenge(self, challenge: int, pad: int, data: int, partial_decrypt: int) -> bool: """ check if the given challenge values Ci satisfies ci = H(Q-bar, (A,B), (ai, bi), Mi) :param challenge: given challenge of a share, Ci, for comparison :param pad: pad of a share, ai :param data: data number of a share, bi :param partial_decrypt: partial decryption of a guardian, Mi :return: True if the given Ci equals to the ci computed using hash """ challenge_computed = number.hash_elems(self.extended_hash, self.selection_pad, self.selection_data, pad, data, partial_decrypt) res = number.equals(challenge, challenge_computed) if not res: print("challenge value error. ") return res
def verify_a_contest(self) -> Tuple[bool, bool]: """ verify a contest within a ballot, ballot correctness :return True if no error, False otherwise """ # initialize errors to false encryption_error, limit_error = self.initialize_error( ), self.initialize_error() # get variables selections_list = self.contest_dic.get('ballot_selections') vote_limit = int(self.vote_limit_dic.get(self.contest_id)) placeholder_count = 0 selection_alpha_product = 1 selection_beta_product = 1 for selection in selections_list: # verify encryption correctness on every selection - selection check # create selection verifiers sv = BallotSelectionVerifier(selection, self.param_g) # get alpha, beta products selection_alpha_product = selection_alpha_product * int( sv.get_pad()) % int(self.param_g.get_large_prime()) selection_beta_product = selection_beta_product * int( sv.get_data()) % int(self.param_g.get_large_prime()) # check validity of a selection is_correct = sv.verify_selection_validity() if not is_correct: encryption_error = self.set_error() # check selection limit, whether each a and b are in zrp is_within_limit = sv.verify_selection_limit() if not is_within_limit: limit_error = self.set_error() # get placeholder counts if sv.is_placeholder_selection(): placeholder_count = self.__increment_num(placeholder_count) # verify the placeholder numbers match the maximum votes allowed - contest check placeholder_match = self.__match_vote_limit_by_contest( self.contest_id, placeholder_count) if not placeholder_match: limit_error = self.set_error() # calculate c = H(Q-bar, (A,B), (a,b)) challenge_computed = number.hash_elems(self.extended_hash, selection_alpha_product, selection_beta_product, self.contest_alpha, self.contest_beta) # check if given contest challenge matches the computation challenge_match = self.__check_challenge(challenge_computed) if not challenge_match: limit_error = self.set_error() # check equations equ1_check = self.__check_cp_proof_alpha(selection_alpha_product) equ2_check = self.__check_cp_proof_beta(selection_beta_product, vote_limit) if not equ1_check or not equ2_check: limit_error = self.set_error() if encryption_error or limit_error: output = self.contest_id + ' verification failure:' if encryption_error: output += ' encryption error. ' if limit_error: output += ' selection limit error. ' print(output) return not encryption_error, not limit_error