def verify_prf(*args, **kwargs) -> 'bool': """ Verification of ZKP for square relation between preimages Positional args : tuple(A1, A2), tuple(B1, B2) - ElGamal encryptions Keyword args - as below """ try: (A1, A2) = args[0] (B1, B2) = args[1] pid = kwargs['pid'] pk = kwargs['pubkey'] (C_a1, C_a2) = kwargs['C_a'] (C_b1, C_b2) = kwargs['C_b'] v = kwargs['v'] z_a = kwargs['z_a'] z_b = kwargs['z_b'] except: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) sys.exit(1) logger.info( "Verifying ZKP for square relation for participant id {}".format(pid)) # generate crs using SHA256 crs = ''.join( [str(_) for _ in [pid, A1, A2, B1, B2, C_a1, C_a2, C_b1, C_b2]]) c = int(SHA256.new(crs.encode('utf-8')).hexdigest(), 16) % order # Canny, step4 (e1, e2) = elgamal_encrypt(pk, z_a, v * G) (f1, f2) = elgamal_encrypt(pk, z_b, 0 * G) # check statements if e1 != c * A1 + C_a1: return False if e2 != c * A2 + C_a2: return False if f1 + v * A1 != c * B1 + C_b1: return False if f2 + v * A2 != c * B2 + C_b2: return False # ZKP successful verification return True
def gen_prf(*args, **kwargs) -> 'dict': """ Generate proof of square relation between preimages of two ElGamal encrytions Positional args : tuple(A1, A2), tuple(B1, B2) - ElGamal encryptions Keyword args - as below """ try: (A1, A2) = args[0] (B1, B2) = args[1] pid = kwargs['pid'] s_a = kwargs['secret1'] s_b = kwargs['secret2'] a = kwargs['message'] pk = kwargs['pubkey'] except: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) sys.exit(1) logger.info( "Generating proof of square relation for participant id {}".format( pid)) # Canny, step1 x, r_a, r_b = random.randint(0, order), random.randint( 0, order), random.randint(0, order) (C_a1, C_a2) = elgamal_encrypt(pk, r_a, x * G) (C_b1, C_b2) = elgamal_encrypt(pk, r_b, 0 * G) (C_b1, C_b2) = (C_b1 + x * A1, C_b2 + x * A2) # generate crs using SHA256 crs = ''.join( [str(_) for _ in [pid, A1, A2, B1, B2, C_a1, C_a2, C_b1, C_b2]]) c = int(SHA256.new(crs.encode('utf-8')).hexdigest(), 16) % order # Canny, step3 v = (c * a + x) % order z_a = (c * s_a + r_a) % order z_b = (c * (s_b - a * s_a) + r_b) % order return { 'C_a': (C_a1, C_a2), 'C_b': (C_b1, C_b2), 'v': v, 'z_a': z_a, 'z_b': z_b }
def gen_prf(*args, **kwargs) -> 'dict': """ Generate proof """ try: (x,y) = args[0] pid = kwargs['pid'] v = kwargs['message'] secret = kwargs['secret'] pk = kwargs['pubkey'] b = kwargs['bound'] except: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) sys.exit(1) logger.info("Generating range ZKP for participant id {}".format(pid)) # represent the original value in binary form vb_str = "{0:b}".format(v) vb = [] for c in vb_str: vb.append(int(c)) v_new = 0 L = len(vb) for l in range(L): v_new += vb[l] * 2**(L - 1 - l) assert v_new == v, "{}, {}".format(str(v_new), str(v)) LB = math.ceil(math.log2(b)) if L > LB: print('Range Proof: input value {} exceeds bound {}'.format(v, b)) sys.exit(1) vb_enc = [] vb_prf = [] rsum = 0 # the randomness for the weighted sum # generate 1 out of 2 proofs for l in range(L): bit = vb[l] r = random.randint(0, order) rsum += 2**(L-1-l)*r cbit = elgamal_encrypt(pk, r, bit * G) (c1, c2) = cbit prf = zkp_oneOutOfTwo.gen_prf(c1, c2, pid = pid, message = bit, secret = r, pubkey = pk) vb_enc.append(cbit) vb_prf.append(prf) # generate dhtuple proof c1sum = I c2sum = I for l in range(L): c1sum += 2**(L - 1 - l)*vb_enc[l][0] c2sum += 2**(L - 1 - l)*vb_enc[l][1] dhtuple = (G, pk, x - c1sum, y - c2sum) dhtuple_prf = zkp_dhTuple.gen_prf(dhtuple, pid=pid, secret=secret - rsum) return {'zkp01':vb_prf, 'zkp_dhtuple':dhtuple_prf, 'encrypted_bits':vb_enc}
def simpleElGamal(): # generate secret-key sk = random.randint(0, order) pk = sk * G # generate secret randomness r = random.randint(0, order) # message to encrypt m = int(42) # point on the curve corresponding to the message m_point = m * G (c1, c2) = elgamal_encrypt(pk, r, m_point) logger.info("ElGamal ciphertext: {}, {}".format(c1, c2)) m_point_decrypt = elgamal_decrypt(sk, c1, c2) logger.info("ElGamal decrypted: {}".format(m_point_decrypt)) # data recovered from ElGamal is a point on the curve. We need to solve # the discrete log problem to get the message - exhaustive search or # Baby/Giant assert m_point_decrypt == m_point plaintext = baby_giant(m_point_decrypt) print("Plaintext: {}".format(plaintext))
def run(): # generate secret-key sk = random.randint(0, order) pk = sk*G m = int(42) m_point = m * G r_m = random.randint(0, order) # secret for m m_sq = m**2 m_sq_point = m_sq * G r_m_sq = random.randint(0, order) # secret for m_sq # ElGamal encryptions E_m = elgamal_encrypt(pk, r_m, m_point) E_m_sq = elgamal_encrypt(pk, r_m_sq, m_sq_point) prf = zkp_square.gen_prf(E_m, E_m_sq, pid=0, secret1=r_m, secret2=r_m_sq, message=m, pubkey=pk) success = zkp_square.verify_prf(E_m, E_m_sq, pid=0, pubkey=pk, **prf) print("ZKP verification %s."%('Passed' if success is True else 'Failed'))
def run(): # generate secret-key sk = random.randint(0, order) pk = sk * G # message to encrypt m = int(1) m2 = int(3) mmax = 2 # point on the curve corresponding to the message m_point = m * G m2_point = m2 * G # generate secret randomness L = math.ceil(math.log2(mmax)) c1 = elgamal_encrypt(pk, sk, m_point) c2 = elgamal_encrypt(pk, sk, m2_point) prf = zkp_range.gen_prf(c1, pid=0, message=m, secret=sk, pubkey=pk, bound=mmax) prf2 = zkp_range.gen_prf(c2, pid=1, message=m, secret=sk, pubkey=pk, bound=mmax) success = zkp_range.verify_prf(c1, pid=0, pubkey=pk, bound=mmax, **prf) success2 = zkp_range.verify_prf(c2, pid=1, pubkey=pk, bound=mmax, **prf2) print("ZKP verification 0 %s." % ('Passed' if success is True else 'Failed')) print("ZKP verification 1 %s." % ('Passed' if success2 is True else 'Failed'))
def run(): # generate secret-key sk = random.randint(0, order) pk = sk*G # generate secret randomness r = random.randint(0, order) # message to encrypt m = int(1) # point on the curve corresponding to the message m_point = m * G (c1, c2) = elgamal_encrypt(pk, r, m_point) prf = zkp_oneOutOfTwo.gen_prf(c1, c2, pid=0, message=m, secret=r, pubkey=pk) success = zkp_oneOutOfTwo.verify_prf(c1, c2, pid=0, pubkey=pk, **prf) print("ZKP verification %s."%('Passed' if success is True else 'Failed'))
def prove(self): if (self.ledger.cur_phase != 'p'): print("Not in proof phase!") return # verify zkp for discrete log if (not self.check_zkp_discretelog(self.ledger.pk_list, self.ledger.zkp_discretelog_dict)): print("ZKP discrete log validation failed!") return # compute the encryption of g (equation 2), which cancels after addition; generate range proof for each value of g encrypted_g1 = [] h_list = [] zkp_range_g1 = [] for x in range(self.len): h = I for u in self.ledger.pk_list: if (u < self.uid): h += self.ledger.pk_list[u][x] elif (u > self.uid): h -= self.ledger.pk_list[u][x] h_list.append(h) c = elgamal_encrypt(h, self.secrets[x], self.g[x] * G) encrypted_g1.append(c) prf = zkp_range.gen_prf(c, pid=str(self.uid) + ":" + str(x), message=self.g[x], secret=self.secrets[x], pubkey=h_list[x], bound=self.gmax) zkp_range_g1.append(prf) if (self.ledger.commit_zkp_range(zkp_range_g1, self.uid) == 0): print("Failed to upload ZKP of range proof for {}!".format( self.uid)) return # compute another encryption of g, which uses the same public key for all values; generate zkp for dhtuple (equation 3) encrypted_g2 = [] zkp_dhtuple_list = [] for x in range(self.len): encrypted_g2.append( elgamal_encrypt(self.h, self.secrets[x], self.g[x] * G)) dhtuple = (G, h_list[x] - self.h, self.secrets[x] * G, encrypted_g1[x][1] - encrypted_g2[x][1]) prf = zkp_dhTuple.gen_prf(dhtuple, pid=str(self.uid) + ":" + str(x), secret=self.secrets[x]) zkp_dhtuple_list.append(prf) if (self.ledger.commit_zkp_dhtuple(self.h, h_list, encrypted_g1, encrypted_g2, zkp_dhtuple_list, self.uid) == 0): print("Failed to upload ZKP of dhtuple for {}!".format(self.uid)) return # generate range proof for sum g_sum = 0 g_encsum1 = I g_encsum2 = I g_secsum = 0 for x in range(self.len): g_sum += self.g[x] g_encsum1 += encrypted_g2[x][0] g_encsum2 += encrypted_g2[x][1] g_secsum += self.secrets[x] g_encsum = (g_encsum1, g_encsum2) zkp_sumRange = zkp_range.gen_prf(g_encsum, pid=str(self.uid), message=g_sum, secret=g_secsum, pubkey=self.h, bound=self.bound) if (self.ledger.commit_zkp_sumRange(zkp_sumRange, self.uid) == 0): print("Failed to upload ZKP of sum range for {}!".format(self.uid)) return
def prove(self): if (self.ledger.cur_phase != 'p'): print("Not in proof phase!") return # verify zkp for discrete log all_pk_list = self.ledger.pk_list if (not self.check_zkp_discretelog(all_pk_list, self.ledger.zkp1_dict)): print("ZKP discrete log validation failed!") return # compute the encryption of g (equation 2) encrypted_g1 = [] h_list = [] for x in range(self.len): h = I for u in all_pk_list: if (u < self.uid): h += all_pk_list[u][x] elif (u > self.uid): h -= all_pk_list[u][x] h_list.append(h) encrypted_g1.append( elgamal_encrypt(h, self.sk_list[x], self.g[x] * G)) # compute another encryption of g, generate zkp for dhtuple (equation 3) encrypted_g2 = [] zkp_dhtuple_list = [] for x in range(self.len): encrypted_g2.append( elgamal_encrypt(self.h, self.sk_list[x], self.g[x] * G)) dhtuple = (G, h_list[x] - self.h, self.pk_list[x], encrypted_g1[x][1] - encrypted_g2[x][1]) prf = zkp_dhTuple.gen_prf(dhtuple, pid=str(self.uid) + ":" + str(x), secret=self.sk_list[x]) zkp_dhtuple_list.append(prf) if (self.ledger.zkp2(self.h, h_list, encrypted_g1, encrypted_g2, zkp_dhtuple_list, self.uid) == 0): print("Failed to upload ZKP of dhtuple for {}!".format(self.uid)) return # generate square vector and its binary representation w = [] s = 0 for x in range(self.len): w.append(self.g[x]**2) s += w[x] sb_str = "{0:b}".format(s) sb = [] for c in sb_str: sb.append(int(c)) s_new = 0 L = len(sb) for x in range(L): s_new += sb[x] * 2**(L - 1 - x) assert s_new == s, "{}, {}".format(str(s_new), str(s)) # encrypt the binary representation (equation 6), and generate zkp01 for each binary value encrypted_sb = [] r_list_sb = [] zkp01 = [] for x in range(L): r_sb = random.randint(0, order) e_sb = elgamal_encrypt(self.h, r_sb, sb[x] * G) (c1, c2) = e_sb prf = zkp_oneOutOfTwo.gen_prf(c1, c2, pid=str(self.uid) + ":" + str(x), message=sb[x], secret=r_sb, pubkey=self.h) r_list_sb.append(r_sb) encrypted_sb.append(e_sb) zkp01.append(prf) if (self.ledger.zkp3(encrypted_sb, zkp01, self.uid) == 0): print("Failed to upload ZKP01 for {}!".format(self.uid)) return # generate randomness for w and encrypt w (equation 7, equation 8) r_list_w = [] encrypted_w = [] zkp_square_list = [] for x in range(self.len): r_w = random.randint(0, order) r_list_w.append(r_w) sum_rw = 0 sum_rw_new = 0 for x in range(self.len): r_w = 0 for y in range(self.len): if (y < x): r_w += r_list_w[y] elif (y > x): r_w -= r_list_w[y] r_w *= r_list_w[x] if (x < L): r_w_new = r_w + r_list_sb[x] * 2**(L - 1 - x) else: r_w_new = r_w sum_rw += r_w sum_rw_new += r_w_new e_w = elgamal_encrypt(self.h, r_w_new, w[x] * G) prf = zkp_square.gen_prf(encrypted_g2[x], e_w, pid=str(self.uid) + ":" + str(x), secret1=self.sk_list[x], secret2=r_w_new, message=self.g[x], pubkey=self.h) encrypted_w.append(e_w) zkp_square_list.append(prf) if (self.ledger.zkp4(encrypted_w, zkp_square_list, self.uid) == 0): print("Failed to upload ZKP square for {}".format(self.uid)) assert sum_rw == 0, "sum_rw = {}".format(sum_rw) sum_e_w = I sum_e_sb = I for x in range(self.len): sum_e_w += encrypted_w[x][1] for x in range(L): sum_e_sb += encrypted_sb[x][1] * 2**(L - 1 - x) assert (sum_e_w == sum_e_sb), "check sum failed"