def encrypt(self,m,r1=None,r2=None, r3=None): ''' Outputs a PPATCCiphertext on m using r1,r2 as the randomness for the commitment and r1,r2,r3 as the randomness for the encryption ''' # notations q = self.PPATCpp.order g = self.PPATCpp.g ECG = g.ECG # EFp2 Jcoord = self.PPATCpp.Jcoord if r1 == None: r1 = randint(1,int(q)) if r2 == None: r2 = randint(1,int(q)) if r3 == None: r3 = randint(1,int(q)) # commitment d = self.commit(m,r1,r2) # encryption c1t = oEC.mul_comb2_EFp2(ECG,r2,self.precomp_g,Jcoord) c1 = oEC.toEFp2(ECG,c1t,Jcoord) #c1 = r2*g c2t = oEC.mul_comb2_EFp2(ECG,r3,self.precomp_g,Jcoord) c2 = oEC.toEFp2(ECG,c2t,Jcoord) #c2 = r3*g c31t = oEC.mul_comb2_EFp2(ECG,r1,self.precomp_g1,Jcoord) c32t = oEC.mul_comb2_EFp2(ECG,r3,self.precomp_g2,Jcoord) c3t = oEC.addEFp2(ECG,c31t,c32t,Jcoord) c3 = oEC.toEFp2(ECG,c3t,Jcoord) #c3 = (r1*g1)+(r3*g2) return PPATCCiphertext(d,c1,c2,c3,self)
def encrypt(self, m, r1=None, r2=None, r3=None): ''' Outputs a PPATCCiphertext on m using r1,r2 as the randomness for the commitment and r1,r2,r3 as the randomness for the encryption ''' # notations q = self.PPATCpp.order g = self.PPATCpp.g ECG = g.ECG # EFp2 Jcoord = self.PPATCpp.Jcoord if r1 == None: r1 = randint(1, int(q)) if r2 == None: r2 = randint(1, int(q)) if r3 == None: r3 = randint(1, int(q)) # commitment d = self.commit(m, r1, r2) # encryption c1t = oEC.mul_comb2_EFp2(ECG, r2, self.precomp_g, Jcoord) c1 = oEC.toEFp2(ECG, c1t, Jcoord) #c1 = r2*g c2t = oEC.mul_comb2_EFp2(ECG, r3, self.precomp_g, Jcoord) c2 = oEC.toEFp2(ECG, c2t, Jcoord) #c2 = r3*g c31t = oEC.mul_comb2_EFp2(ECG, r1, self.precomp_g1, Jcoord) c32t = oEC.mul_comb2_EFp2(ECG, r3, self.precomp_g2, Jcoord) c3t = oEC.addEFp2(ECG, c31t, c32t, Jcoord) c3 = oEC.toEFp2(ECG, c3t, Jcoord) #c3 = (r1*g1)+(r3*g2) return PPATCCiphertext(d, c1, c2, c3, self)
def encrypt(self,m,r=None,s=None): ''' Outputs a PPATSCiphertext on m using r as the randomness for the commitment and s as the randomness for the encryption ''' #limit = 2**self.maxexp #assert m < limit #assert m >= 0 order = self.PPATSpp.order if r == None: r = randint(1,int(order)) if s == None: s = randint(1,int(order)) # notations g1 = self.g1 ECG = g1.ECG Jcoord = self.PPATSpp.Jcoord # commitment part d,r = self.commit(m,r) #d = (r*h)+(m*h1) # encryption part c1t = oEC.mul_comb2_EFp2(ECG,s,self.precomp_g,Jcoord) c1 = oEC.toEFp2(ECG,c1t,Jcoord) #c1 = s*g rgt = oEC.mul_comb2_EFp2(ECG,r,self.precomp_g,Jcoord) sg1t = oEC.mul_comb2_EFp2(ECG,s,self.precomp_g1,Jcoord) c2t = oEC.addEFp2(ECG,rgt,sg1t,Jcoord) c2 = oEC.toEFp2(ECG,c2t,Jcoord) #c2 = (r*g)+(s*g1) return PPATSCiphertext(d,c1,c2,self)
def splitCommitment(ppatspk, com, m, a): ''' This method is a simpler version of self.decomposeCommitment() Assuming that commitment com commits on the message m and has opening a. The method decomposes com in two parts com1,com2 such that com = com1+com2. com2 is a commitment on 0, com1 is a commitment on m The output of the method is a list of two elements : the two commitments com1 and com2 together with the randomness and opening used in each. Remark : The point of doing this is, in some way, to modify the randomness used in the commitment. For example, suppose that you know the opening of the commitment but not the randomness used in the commitment. With this method, you can create another commitment that commits on the same value but now, you know the randomness used in it. This is usefull in order to produce set membership proofs. ''' g = ppatspk.PPATSpp.g Jcoord = ppatspk.PPATSpp.Jcoord com1, r1 = ppatspk.commit(m) ECG = g.ECG a1t = oEC.mul_comb2_EFp2(ECG, r1, ppatspk.precomp_g, Jcoord) a1 = oEC.toEFp2(ECG, a1t, Jcoord) com2d = com.d - com1.d com2 = ppat.ppats.PPATSCommitment(com2d, ppatspk) a2 = a - a1 comlist = [(m, r1, a1, com1), (0, None, a2, com2)] return comlist
def splitCommitment(ppatspk, com, m, a): """ This method is a simpler version of self.decomposeCommitment() Assuming that commitment com commits on the message m and has opening a. The method decomposes com in two parts com1,com2 such that com = com1+com2. com2 is a commitment on 0, com1 is a commitment on m The output of the method is a list of two elements : the two commitments com1 and com2 together with the randomness and opening used in each. Remark : The point of doing this is, in some way, to modify the randomness used in the commitment. For example, suppose that you know the opening of the commitment but not the randomness used in the commitment. With this method, you can create another commitment that commits on the same value but now, you know the randomness used in it. This is usefull in order to produce set membership proofs. """ g = ppatspk.PPATSpp.g Jcoord = ppatspk.PPATSpp.Jcoord com1, r1 = ppatspk.commit(m) ECG = g.ECG a1t = oEC.mul_comb2_EFp2(ECG, r1, ppatspk.precomp_g, Jcoord) a1 = oEC.toEFp2(ECG, a1t, Jcoord) com2d = com.d - com1.d com2 = ppat.ppats.PPATSCommitment(com2d, ppatspk) a2 = a - a1 comlist = [(m, r1, a1, com1), (0, None, a2, com2)] return comlist
def commit(self,m,r1=None,r2=None): q = self.PPATCpp.order if r1 == None: r1 = randint(1,int(q)) if r2 == None: r2 = randint(1,int(q)) # notations Jcoord = self.PPATCpp.Jcoord ECG1 = self.h1.ECG ECG2 = self.g1.ECG # commitment d11t = oEC.mul_comb2_EFp(ECG1,r1,self.precomp_h,Jcoord) d12t = oEC.mul_comb2_EFp(ECG1,r2,self.precomp_h1,Jcoord) d1t = oEC.addEFp(ECG1,d11t,d12t,Jcoord) d1 = oEC.toEFp(ECG1,d1t,Jcoord) #d1 = (r1*h)+(r2*h1) mp = self.encode(m) d21t = oEC.mul_comb2_EFp2(ECG2,r2,self.precomp_g1,Jcoord) d2t = oEC.addEFp2(ECG2,mp,d21t,Jcoord) d2 = oEC.toEFp2(ECG2,d2t,Jcoord) #d2 = mp + r2*g1 return PPATCCommitment(d1,d2,self)
def encode(self,m): ''' Return a torsion point over EFp which is m*g (or m*P) ''' Jcoord = self.PPATCpp.Jcoord ECG = self.g1.ECG mt = oEC.mul_comb2_EFp2(ECG,m,self.precomp_g,Jcoord) return mt
def commit(self, m, r1=None, r2=None): q = self.PPATCpp.order if r1 == None: r1 = randint(1, int(q)) if r2 == None: r2 = randint(1, int(q)) # notations Jcoord = self.PPATCpp.Jcoord ECG1 = self.h1.ECG ECG2 = self.g1.ECG # commitment d11t = oEC.mul_comb2_EFp(ECG1, r1, self.precomp_h, Jcoord) d12t = oEC.mul_comb2_EFp(ECG1, r2, self.precomp_h1, Jcoord) d1t = oEC.addEFp(ECG1, d11t, d12t, Jcoord) d1 = oEC.toEFp(ECG1, d1t, Jcoord) #d1 = (r1*h)+(r2*h1) mp = self.encode(m) d21t = oEC.mul_comb2_EFp2(ECG2, r2, self.precomp_g1, Jcoord) d2t = oEC.addEFp2(ECG2, mp, d21t, Jcoord) d2 = oEC.toEFp2(ECG2, d2t, Jcoord) #d2 = mp + r2*g1 return PPATCCommitment(d1, d2, self)
def encode(self, m): ''' Return a torsion point over EFp which is m*g (or m*P) ''' Jcoord = self.PPATCpp.Jcoord ECG = self.g1.ECG mt = oEC.mul_comb2_EFp2(ECG, m, self.precomp_g, Jcoord) return mt
def verifyEvalBatch(self, com, B, rem1_x, rem2_x, w_B): ''' Check if com is a commitment on a polynomial phi such that (b_j,phi_b_j) belongs to the polynomial for each b_j in B. The verification uses the witness w_B and the remainder polynomial rem1_x, rem2_x (see self.createWitnessBatch(...) for their construction). Return True if the verification succeeds. This method computes 3 pairings. ''' Fr = self.Fr e = oEC.OptimAtePairing Pair = self.pairing gp = self.gprimeVec[-1] EFp2 = gp.ECG Fp12 = Pair.Fpk prod_x_minus_b_j = field.polynom(Fr,[Fr.one()]) for b_j in B : x_minus_b_j = field.polynom(Fr,[Fr.one(),-b_j]) prod_x_minus_b_j *= x_minus_b_j if len(prod_x_minus_b_j.coef) < self.deg_pol+1 : # Append zeros coef to phi_x if its coef list is too short (< deg_pol+1) diff = self.deg_pol+1 - len(prod_x_minus_b_j.coef) L = [Fr.zero()]*diff new_prod_x_minus_b_j = field.polynom(Fr,L+prod_x_minus_b_j.coef) prod_x_minus_b_j = new_prod_x_minus_b_j t1 = EFp2.infty t1t = oEC.toTupleEFp2(t1, self.Jcoord) #TODO: Optimize here # DONE for i in range(self.deg_pol+1): #t1 += prod_x_minus_b_j.coef[i].val*self.gprimeVec[i] a = oEC.mul_comb2_EFp2(EFp2,prod_x_minus_b_j.coef[i].val,self.gprimeVecTab[i],self.Jcoord) t1t = oEC.addEFp2(EFp2,t1t,a,self.Jcoord) t1g = oEC.toEFp2(EFp2,t1t,self.Jcoord) if self.Jcoord : t1g.toAffine() #assert t1g == t1 u1 , rem2_x = self.commit(rem1_x,rem2_x) rm = e(com.c,gp,Pair) lm1 = e(w_B.c,t1g,Pair) lm2 = e(u1.c,gp,Pair) lm = oEC.mulFp12(Fp12,lm1,lm2) return rm == lm
def verifyEval(self, com, b, phi_b, phiprime_b, w_b): ''' Check if com is a commitment on a polynomial phi such that (b,phi_b) belongs to the polynomial. The verification uses the witness w_b and the evaluation of the polynomial phiprime at b. Return True if the verification succeeds. This method computes 3 pairings. ''' EFp = self.pairing.EFp e = oEC.OptimAtePairing Pair = self.pairing Fp12 = Pair.Fpk #gamma = Pair.gamma #g = self.gVec[-1] #h = self.hVec[-1] gp = self.gprimeVec[-1] EFp2 = gp.ECG gp_alpha = self.gprimeVec[-2] #TODO: Optimize here # DONE #gprime_b = (b.val)*gp gprime_bt = oEC.mul_comb2_EFp2(EFp2,b.val,self.gprimeVecTab[-1],self.Jcoord) mgprime_bt = oEC.negEFp2(gprime_bt,self.Jcoord) gpat = oEC.toTupleEFp2(gp_alpha,self.Jcoord) t1t = oEC.addEFp2(EFp2,gpat,mgprime_bt,self.Jcoord) #t1 = gp_alpha-gprime_b #u1 = (phi_b.val)*g + (phiprime_b.val)*h a1 = oEC.mul_comb2_EFp(EFp,phi_b.val,self.gVecTab[-1],self.Jcoord) b1 = oEC.mul_comb2_EFp(EFp,phiprime_b.val,self.hVecTab[-1],self.Jcoord) u1t = oEC.addEFp(EFp,a1,b1,self.Jcoord) t1g = oEC.toEFp2(EFp2,t1t,self.Jcoord) u1g = oEC.toEFp(EFp,u1t,self.Jcoord) if self.Jcoord : t1g.toAffine() u1g.toAffine() #assert t1g == t1 #assert u1g == u1 rm = e(com.c,gp,Pair) lm1 = e(w_b.c,t1g,Pair) lm2 = e(u1g,gp,Pair) lm = oEC.mulFp12(Fp12,lm1,lm2) return rm == lm
def verifyZKS(self, com, b, proof): ''' Checks that the NIZKPoK holds meaning that phi(b) = 0 or phi(b) != 0 where phi is the polynomial commited to in com. ''' Fr = self.Fr e = oEC.OptimAtePairing Pair = self.pairing Fp12 = Pair.Fpk gp = self.gprimeVec[-1] gp_alpha = self.gprimeVec[-2] EFp2 = gp.ECG bp, w_b, phiprime_b_eval, A = proof if A == None : return self.verifyEval(com, b, Fr.zero(), phiprime_b_eval, w_b) elif phiprime_b_eval == None : #TODO: Optimize here # DONE z_j, proof_z_j = A cond1 = self.checkOpeningNIZKPOK(com,proof_z_j) #gprime_b = b.val*gp gprime_bt = oEC.mul_comb2_EFp2(EFp2,b.val,self.gprimeVecTab[-1],self.Jcoord) mgprime_bt = oEC.negEFp2(gprime_bt,self.Jcoord) gpat = oEC.toTupleEFp2(gp_alpha,self.Jcoord) t1t = oEC.addEFp2(EFp2,gpat,mgprime_bt,self.Jcoord) t1g = oEC.toEFp2(EFp2,t1t,self.Jcoord) if self.Jcoord : t1g.toAffine() #gprime_alpha_minus_b = self.gprimeVec[-2]-gprime_b #assert gprime_alpha_minus_b == t1g rm = e(com.c,gp,Pair) lm1 = e(w_b.c,t1g,Pair) lm2 = e(z_j,gp,Pair) lm = oEC.mulFp12(Fp12,lm1,lm2) #cond2 = e(com.c,gp,Pair) == e(w_b.c,t1g,Pair)*e(z_j,gp,Pair) cond2 = rm == lm return cond1 and cond2 else : return False