def DLogOptim(x,a,dic={}): ''' Return y such as a**y = x using optimized methods in Fp12 to perform multiplications. The algorithm is base on the baby-step / giant-step method. The dictionnary dic stores the precomputed values of a needed for the algo. This dictionnary can be computed with the method self.giantSteps ''' Pair = self.PPATSpp.Pair Fpk = Pair.Fpk gamma = Pair.gamma if x == x.F.one(): return 0 elif a == x : return 1 order = self.PPATSpp.order b = oEC.toTupleFp12(a) xp = oEC.toTupleFp12(x) if dic == {}: if self.giantStepsDict == {}: dic = self.giantSteps(b) self.giantStepsDict = dic else : dic = self.giantStepsDict t = dic['t'] # baby-step / giant-step algo for i in range(0,t+1): ai = dic['e1'][i] bi = oEC.tmulFp12(Fpk,xp,ai,gamma) if bi in dic['e2'].keys(): j = dic['e2'][bi] return (j*t-i)%order #y return None # in case the value y is not found
def giantSteps(self,a): ''' This method computes a series of exponentiations of a. Assuming a is in Fq12. maxi is the maximum value of the possible discrete log to be found (by default 2**16). The method will precompute exponentiation of a at each of the t steps where t is the square root of maxi : a^0, a^t, a^2t, ..., a^maxi. In addition (not in the original algo but inserted here because 2^8 is a small number), the method computes a^0, a^1, a^2, ..., a^t. Since this is also needed to compute the discrete logarithm. Finally, all the precomputed exponentiations are stored in a dictionnary. ''' limit = 2**self.maxexp Pair = self.PPATSpp.Pair gamma = Pair.gamma Fpk = Pair.Fpk t = int(math.sqrt(limit)) l = int(limit//t) dic = {} dic['t'] = t # storing t for a later use at = oEC.squareAndMultiply(Fpk,a,t,oEC.tmulFp12,oEC.tsqrtFp12,gamma) one = oEC.toTupleFp12(Pair.Fpk1) dic['e1'] = {} dic['e2'] = {} dic['e1'][0] = one dic['e1'][1] = a dic['e2'][one] = 0 dic['e2'][at] = 1 ai = a ait = at # dic['e1'] is a dictionnary containing the a^i for i=0,...,t where the # keys are the indexes for i in range(2,t+1): ai = oEC.tmulFp12(Fpk,ai,a,gamma) dic['e1'][i] = ai # dic['e2'] is a dictionnary containing the a^it for i=0,...,l where the # keys are the a^it and the values are the indexes for i in range(2,l+1): ait = oEC.tmulFp12(Fpk,ait,at,gamma) dic['e2'][ait] = i return dic
def make_Ftable(Field, elt): #This function makes a multiplication table to aid in computing discrete #logarithims to speed up decryption of multiple messages encrypted with the #same public/private key baby_steps = {} gt = oEC.toTupleFp12(Field.one()) for j in xrange(2**16): gt = oEC.tmulFp12(Fp12, gt, oEC.toTupleFp12(elt), Gamma) baby_steps[gt] = j + 1 return baby_steps
def log_field( a, b, Field, table={} ): # Computes x such that a^x = b over a field of order p using baby step-giant step #baby_steps = {} x = oEC.toTupleFp12(a.invert()**(2**16)) gamma = oEC.toTupleFp12(b) if table == {}: print 'No Table Found' table = make_Ftable(Field, a) for i in range(2**16): if gamma in table: return (i) * (2**16) + table[gamma] else: gamma = oEC.tmulFp12(Fp12, gamma, x, Gamma) return "No Match"