def reenc_return_r(self): """ Reencryption with fresh randomness, which is returned. """ r = Utils.random_mpz_lt(self.pk.q) new_c = self.reenc_with_r(r) return [new_c, r]
def prove_decryption(self, ciphertext): """ given g, y, alpha, beta/(encoded m), prove equality of discrete log with Chaum Pedersen, and that discrete log is x, the secret key. Prover sends a=g^w, b=alpha^w for random w Challenge c = sha1(a,b) with and b in decimal form Prover sends t = w + xc Verifier will check that g^t = a * y^c and alpha^t = b * beta/m ^ c """ m = (Utils.inverse(pow(ciphertext.alpha, self.x, self.pk.p), self.pk.p) * ciphertext.beta) % self.pk.p beta_over_m = (ciphertext.beta * Utils.inverse(m, self.pk.p)) % self.pk.p # pick a random w w = Utils.random_mpz_lt(self.pk.q) a = pow(self.pk.g, w, self.pk.p) b = pow(ciphertext.alpha, w, self.pk.p) c = int(hashlib.sha1(str(a) + "," + str(b)).hexdigest(),16) t = (w + self.x * c) % self.pk.q return m, { 'commitment' : {'A' : str(a), 'B': str(b)}, 'challenge' : str(c), 'response' : str(t) }
def encrypt_return_r(self, plaintext): """ Encrypt a plaintext and return the randomness just generated and used. """ r = Utils.random_mpz_lt(self.q) ciphertext = self.encrypt_with_r(plaintext, r) return [ciphertext, r]
def simulate_encryption_proof(self, plaintext, challenge=None): # generate a random challenge if not provided if not challenge: challenge = Utils.random_mpz_lt(self.pk.q) proof = ZKProof() proof.challenge = challenge # compute beta/plaintext, the completion of the DH tuple beta_over_plaintext = (self.beta * Utils.inverse(plaintext.m, self.pk.p)) % self.pk.p # random response, does not even need to depend on the challenge proof.response = Utils.random_mpz_lt(self.pk.q); # now we compute A and B proof.commitment['A'] = (Utils.inverse(pow(self.alpha, proof.challenge, self.pk.p), self.pk.p) * pow(self.pk.g, proof.response, self.pk.p)) % self.pk.p proof.commitment['B'] = (Utils.inverse(pow(beta_over_plaintext, proof.challenge, self.pk.p), self.pk.p) * pow(self.pk.y, proof.response, self.pk.p)) % self.pk.p return proof
def __init__(self, c0=None, scheme=None, EG=None): self.coeff = [] self.coeff.append(c0) self.EG = EG self.scheme = scheme self.grade = self.scheme.k - 1 p = self.EG.p for i in range(self.grade): # Dit moet p zijn!!? werkt niet met p..? fout? self.coeff.append(Utils.random_mpz_lt(p))
def generate(self, p, q, g): """ Generate an ElGamal keypair """ self.pk.g = g self.pk.p = p self.pk.q = q self.sk.x = Utils.random_mpz_lt(p) self.pk.y = pow(g, self.sk.x, p) self.sk.public_key = self.pk
def prove_sk(self, challenge_generator): """ Generate a PoK of the secret key Prover generates w, a random integer modulo q, and computes commitment = g^w mod p. Verifier provides challenge modulo q. Prover computes response = w + x*challenge mod q, where x is the secret key. """ w = Utils.random_mpz_lt(self.pk.q) commitment = pow(self.pk.g, w, self.pk.p) challenge = challenge_generator(commitment) % self.pk.q response = (w + (self.x * challenge)) % self.pk.q return DLogProof(commitment, challenge, response)
def generate_encryption_proof(self, plaintext, randomness, challenge_generator): """ Generate the disjunctive encryption proof of encryption """ # random W w = Utils.random_mpz_lt(self.pk.q) # build the proof proof = ZKProof() # compute A=g^w, B=y^w proof.commitment['A'] = pow(self.pk.g, w, self.pk.p) proof.commitment['B'] = pow(self.pk.y, w, self.pk.p) # generate challenge proof.challenge = challenge_generator(proof.commitment); # Compute response = w + randomness * challenge proof.response = (w + (randomness * proof.challenge)) % self.pk.q; return proof;
def generate(cls, n_bits): """ generate an El-Gamal environment. Returns an instance of ElGamal(), with prime p, group size q, and generator g """ EG = cls() # find a prime p such that (p-1)/2 is prime q EG.p = Utils.random_safe_prime(n_bits) # q is the order of the group # FIXME: not always p-1/2 EG.q = (EG.p-1)/2 # find g that generates the q-order subgroup while True: EG.g = Utils.random_mpz_lt(EG.p) if pow(EG.g, EG.q, EG.p) == 1: break return EG
def generate(cls, little_g, little_h, x, p, q, challenge_generator): """ generate a DDH tuple proof, where challenge generator is almost certainly EG_fiatshamir_challenge_generator """ # generate random w w = Utils.random_mpz_lt(q) # create proof instance proof = cls() # compute A = little_g^w, B=little_h^w proof.commitment['A'] = pow(little_g, w, p) proof.commitment['B'] = pow(little_h, w, p) # get challenge proof.challenge = challenge_generator(proof.commitment) # compute response proof.response = (w + (x * proof.challenge)) % q # return proof return proof