Пример #1
0
 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