def __check_cp_proof_zero_proof(self, pad: int, data: int, zero_pad: int, zero_data: int, zero_chal: int, zero_res: int) -> bool: """ check if Chaum-Pedersen proof zero proof(given challenge c0, response v0) is satisfied. To proof the zero proof, two equations g ^ v0 = a0 * alpha ^ c0 mod p, K ^ v0 = b0 * beta ^ c0 mod p have to be satisfied. In the verification process, the challenge c of a selection is allowed to be broken into two components in any way as long as c = (c0 + c1) mod p, c0 here is the first component broken from c. :param pad: alpha of a selection :param data: beta of a selection :param zero_pad: zero_pad of a selection :param zero_data: zero_data of a selection :param zero_chal: zero_challenge of a selection :param zero_res: zero_response of a selection :return: True if both equations of the zero proof are satisfied, False if either is not satisfied """ equ1_left = pow(self.generator, zero_res, self.large_prime) equ1_right = number.mod_p( int(zero_pad) * pow(pad, zero_chal, self.large_prime)) equ2_left = pow(self.public_key, zero_res, self.large_prime) equ2_right = number.mod_p( int(zero_data) * pow(data, zero_chal, self.large_prime)) res = number.equals(equ1_left, equ1_right) and number.equals( equ2_left, equ2_right) if not res: print("Chaum-pedersen proof zero proof failure. ") return res
def __check_cp_proof_beta(self, beta_product: int, votes_allowed: int) -> bool: """ check if equation g ^ (L * c) * K ^ v = b * B ^ C mod p is satisfied This function checks the second part of aggregate encryption, B in (A, B), is used together with __check_cp_proof_alpha() to form a pair-wise check on a complete encryption value pair (A,B) :param beta_product: the accumalative product of pad/beta values of all the selections within a contest :param votes_allowed: the maximum votes allowed for this contest :return: True if the equation is satisfied, False if not """ left = number.mod_p( pow(self.generator, number.mod_q(votes_allowed * self.contest_challenge), self.large_prime) * pow(self.public_key, self.contest_response, self.large_prime)) right = number.mod_p( self.contest_beta * pow(beta_product, self.contest_challenge, self.large_prime)) res = number.equals(left, right) if not res: print("contest selection limit check equation 2 error. ") return res
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 __check_cp_proof_alpha(self, alpha_product: int) -> bool: """ check if equation g ^ v = a * A ^ c mod p is satisfied, This function checks the first part of aggregate encryption, A in (A, B), is used together with __check_cp_proof_beta() to form a pair-wise check on a complete encryption value pair (A,B) :param alpha_product: the accumulative product of all the alpha/pad values on all selections within a contest :return: True if the equation is satisfied, False if not """ left = pow(self.generator, self.contest_response, self.large_prime) right = number.mod_p( number.mod_p(self.contest_alpha) * pow(alpha_product, self.contest_challenge, self.large_prime)) res = number.equals(left, right) if not res: print("Contest selection limit check equation 1 error. ") return res
def __get_accum_product(dic: dict, selection_name: str, num: int): """ get the accumulative product of alpha/pad and beta/data for all the selections :param dic: the dictionary alpha or beta values are being added into :param selection_name: name of a selection, noted as "object id" under a selection :param num: a number being multiplied to get the final product :return: none """ if dic.get(selection_name) == '': dic[selection_name] = str(num) else: temp = int(dic[selection_name]) product = number.mod_p(temp * num) dic[selection_name] = str(product)
def __check_cp_proof_one_proof(self, pad: int, data: int, one_pad: int, one_data: int, one_chal: int, one_res: int) -> bool: """ check if Chaum-Pedersen proof one proof(given challenge c1, response v1) is satisfied. To proof the zero proof, two equations g ^ v1 = a1 * alpha ^ c1 mod p, g ^ c1 * K ^ v1 = b1 * beta ^ c1 mod p have to be satisfied. In the verification process, the challenge c of a selection is allowed to be broken into two components in any way as long as c = (c0 + c1) mod p, c1 here is the second component broken from c. :param pad: alpha of a selection :param data: beta of a selection :param one_pad: one_pad of a selection :param one_data: one_data of a selection :param one_chal: one_challenge of a selection :param one_res: one_response of a selection :return: True if both equations of the one proof are satisfied, False if either is not satisfied """ equ1_left = pow(self.generator, one_res, self.large_prime) equ1_right = number.mod_p(one_pad * pow(pad, one_chal, self.large_prime)) equ2_left = number.mod_p( pow(self.generator, one_chal, self.large_prime) * pow(self.public_key, one_res, self.large_prime)) equ2_right = number.mod_p(one_data * pow(data, one_chal, self.large_prime)) res = number.equals(equ1_left, equ1_right) and number.equals( equ2_left, equ2_right) if not res: print("Chaum-pedersen proof one proof failure. ") return res
def __verify_individual_key_computation(self, response: str, commitment: str, public_key: str, challenge: str) -> bool: """ check the equation generator ^ response mod p = (commitment * public key ^ challenge) mod p :param response: response given by a guardian, ui,j :param commitment: commitment given by a guardian, hi,j :param public_key: public key of a guardian, Ki,j :param challenge: challenge of a guardian, ci,j :return: True if both sides of the equations are equal, False otherwise """ response = int(response) commitment = int(commitment) public_key = int(public_key) challenge = int(challenge) left = pow(self.generator, response, self.large_prime) right = number.mod_p(commitment * pow(public_key, challenge, self.large_prime)) return number.equals(left, right)
def __check_equation2(self, response: int, data: int, challenge: int, partial_decrypt: int) -> bool: """ check if equation A ^ vi = bi * (Mi^ ci) mod p is satisfied. The equation is checked along with the one specified in check_equation1() to give proof that the guardian has knowledge about the secret key that would give the secret key without revealing the actual secret. :param response: response of a share, vi :param data: data of a share, bi :param challenge: challenge of a share, ci :param partial_decrypt: partial decryption of a guardian, Mi :return True if the equation is satisfied, False if not """ left = pow(self.selection_pad, response, self.large_prime) right = number.mod_p(data * pow(partial_decrypt, challenge, self.large_prime)) res = number.equals(left, right) if not res: print("equation 2 error. ") return res
def __check_equation1(self, pad: int, response: int, challenge: int, public_key: int) -> bool: """ check if equation g ^ vi = ai * (Ki ^ ci) mod p is satisfied. The equation is checked along with the one specified in check_equation2() to give proof that the guardian has knowledge about the secret key that would give the secret key without revealing the actual secret. :param response: response of a share, vi :param pad: pad of a share, ai :param public_key: public key of a guardian, Ki :param challenge: challenge of a share, ci :return True if the equation is satisfied, False if not """ left = pow(self.generator, response, self.large_prime) right = number.mod_p(pad * pow(public_key, challenge, self.large_prime)) res = number.equals(left, right) if not res: print("equation 1 error. ") return res