def index_calculus(g, h, p, b=0): if not b: b = ceil(exp(sqrt(log(p)*(log(log(p)))))**(1/sqrt(2))) primes = nt.eratosthenes(b) crt_factors = nt.prime_factorise(p-1, counted=True) relations = [] # we need to find a number of linearly dependent relations # first we'll just find 4 times as many as we need while len(relations) < 4*len(primes): x = randint(1, p-1) y = pow(g, x, p) if nt.is_b_smooth(y, b): factorisation = nt.prime_factorise(y, counted=True) relation = [factorisation.get(q, 0) for q in primes] + [x] relations.append(relation) # perform Gaussian elimination on relations modulo each factor sols = [] for base in sorted(crt_factors.keys()): m = base**crt_factors[base] sol = nt.reduced_row_echelon(relations, m) sols.append([sol[i][-1] for i in range(len(sol[0])-1)]) small_prime_logs = [] # use the CRT to stitch together the solutions for i in range(len(primes)): congruences = [] for j, base in enumerate(sorted(crt_factors.keys())): m = base**crt_factors[base] congruences.append((sols[j][i], m)) small_prime_logs.append(nt.chinese_remainder_theorem(congruences)[0]) # have the logs of the small primes g_inv = nt.mod_mult_inv(g, p) g_k = g_inv for k in range(1, p): v = (h * g_k) % p if nt.is_b_smooth(v, b): out = k factors = nt.prime_factorise(v, counted=True) for i, q in enumerate(primes): out += small_prime_logs[i] * factors[q] return out % (p-1) g_k *= g_inv
def pohlig_hellman(g, h, mov_point=False): factorisation = nt.prime_factorise(g.order(), counted=True) ys = [] for q in factorisation.keys(): order = q**factorisation[q] g_i = pow(g, g.order()//order) h_i = pow(h, g.order()//order) ys.append((discrete_log_pp(g_i, h_i, q, factorisation[q], mov_point), order)) return nt.chinese_remainder_theorem(ys)[0]
def order(self): field_order = self.field.order() fac = prime_factorise(field_order, counted=True) powers = [range(e+1) for e in [fac[p] for p in sorted(fac.keys())]] candidates = [] for p in product(*powers): value = [f**p for f, p in zip(sorted(fac.keys()), p)] out = 1 for v in value: out *= v candidates.append(out) for c in sorted(candidates): if self**c == 1: return c
def bad_reduction_primes(self): a, b = self.curve[0].value[0].value, self.curve[1].value[0].value d = 4*a**3+27*b**2 if d == 0: return [self.field.p] return set(nt.prime_factorise(abs(d)))