def shanks_worst_tests(numOfTests: int, numOfBits: list, randSeed=0): seed(randSeed) total_steps_class_list, times_clasic_list, total_memory_clasic = [], [], [] total_steps_grumpy_list, times_grumpy_list, total_memory_grumpy = [], [], [] for bits in numOfBits: time_clas, time_grumpy = [], [] steps_clas, steps_grumpy = [], [] mem_clas, mem_grumpy = [], [] print("Started: ", bits) if bits >= 50: numOfTests = 50 elif bits >= 40: numOfTests = 100 for iter in range(numOfTests): p, g, exp, h = gnp.worst_shanks_numbers(bits) t = timer() x_c, small_clas, giant_clas, mem_c = shanks_classic(g, h, p, p - 1) steps_clas.append(small_clas + giant_clas) mem_clas.append(mem_c) passed_time = (timer() - t) * 1000 time_clas.append(passed_time) t = timer() x_c, oper, mem_c = shanks_two_grumpys_one_baby(g, h, p, p - 1) if x_c != exp: print("NG") steps_grumpy.append(oper) mem_grumpy.append(mem_c) passed_time = (timer() - t) * 1000 time_grumpy.append(passed_time) print( f"Avg steps clasic:{avg(steps_clas) / ceil(sqrt(p)):.4f} -- Avg steps grumpy:{avg(steps_grumpy) / ceil(sqrt(p)):.4f}" ) print( f"Avg memory clasic:{avg(mem_clas) / ceil(sqrt(p)):.4f} -- Avg memory grumpy:{avg(mem_grumpy) / ceil(sqrt(p)):.4f}" ) print( f"Avg time clasic:{avg(time_clas):.4f} -- Avg time grumpy:{avg(time_grumpy):.4f}" ) total_steps_class_list.append(avg(steps_clas) / ceil(sqrt(p))) total_steps_grumpy_list.append(avg(steps_grumpy) / ceil(sqrt(p))) times_clasic_list.append(avg(time_clas)) times_grumpy_list.append(avg(time_grumpy)) total_memory_clasic.append(avg(mem_clas) / ceil(sqrt(p))) total_memory_grumpy.append(avg(mem_grumpy) / ceil(sqrt(p))) print(f"Finished: {bits}\n") print( f"Avg steps clasic:{avg(total_steps_class_list):.4f} -- Avg steps grumpy:{avg(total_steps_grumpy_list):.4f}" ) print( f"Avg memory clasic:{avg(total_memory_clasic):.4f} -- Avg memory grumpy:{avg(total_memory_grumpy):.4f}" ) print( f"Avg time clasic:{avg(times_clasic_list):.4f} -- Avg time grumpy:{avg(times_grumpy_list):.4f}" )
def shanks_interleved(g, h, p, ordin): n = ceil(sqrt(ordin)) e = 1 u = pow(g, p - n - 1, p) s = h baby, giant = {e:0}, {s:0} # lista = {e:0, s:0} for j in range(1, n + 1): e = (e * g) % p if e == h: return j, 2 * j + 1, getsizeof(baby) + getsizeof(giant) #getsizeof(lista) else: i = giant.get(e, None) # i = lista.get(e, None) if i: return (j + i*n) % ordin, 2 * j + 1, getsizeof(baby) + getsizeof(giant) #getsizeof(lista) else: baby[e] = j # lista[e] = j s = (s * u) % p i = baby.get(s, None) # i = lista.get(s, None) if i: return (j*n + i) % ordin, 2 * (j + 1), getsizeof(baby) + getsizeof(giant)#getsizeof(lista) else: giant[s] = j # lista[s] = j return None
def shanks_centered(g, h, p, ordin): n = ceil(sqrt(ordin)) K = ordin // 2 small_steps = 1 e = pow(g, K, p) lista = {e: 0} for j in range(1, n): e = (e * g) % p if e == h: return K + j, small_steps, 0 else: lista[e] = j small_steps += 1 u = pow(g, p - n - 1, p) s = pow(g, n, p) ep = em = h for i in range(0, n): try: j = lista[em] return j + K - i * n, small_steps, 2 * (i + 1) except KeyError: try: j = lista[ep] return K + j + i * n, small_steps, 2 * (i + 1) except KeyError: ep = (ep * u) % p em = (em * s) % p return None
def shanks_order_unkown(g, h, p): rad_p = ceil(sqrt(p - 1)) n = 100 lista_n = [] while n < rad_p: lista_n.append(n) n *= 10 lista_n.append(rad_p) last_n = 1 e = 1 lista = {e: 0} for n in lista_n: for j in range(last_n, n + 1): e = (e * g) % p if e == h: return j lista[e] = j u = pow(g, p - n - 1, p) l = h for i in range(0, n + 1): try: j = lista[l] return i * n + j except KeyError: l = (l * u) % p last_n = n + 1 return None
def primes_up_to_B(B: int): a = [1] * B for i in range(2, ceil(sqrt(B))): if a[i]: for j in range(i * i, B, i): a[j] = 0 return [i for i in range(len(a)) if a[i] == 1][2:]
def shanks_two_grumpys_one_baby(g, h, p, ordin): n = ceil(sqrt(ordin)) m = ceil(n/2) u = pow(g, m, p) s = pow(g, p - (m + 1) - 1, p) b = 1 giant1 = h giant2 = pow(h, 2, p) babys, giants1, giants2 = {b: 0}, {giant1: 0}, {giant2: 0} for i in range(1, n + 1): b = (b * g) % p if b == h: return i, 3 * (i - 1) + 1, getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) else: j = giants1.get(b, None) if j: return (i - j * m) % ordin, 3 * (i - 1) + 1, getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) else: j = giants2.get(b, None) if j: r = (i + j * (m + 1)) // 2 l = ordin // 2 for _ in range(3): if pow(g, r, p) == h: return r, 3 * (i - 1) + 1, getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) r += l else: babys[b] = i giant1 = (giant1 * u) % p j = babys.get(giant1, None) if j: return (j - i * m) % ordin, 3 * (i - 1) + 2, getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) else: j = giants2.get(giant1, None) if j: return (i * m + j * (m + 1)) % ordin, 3 * (i - 1) + 2, getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) else: giants1[giant1] = i giant2 = (giant2 * s) % p j = babys.get(giant2, None) if j: r = (j + i * (m + 1)) // 2 l = ordin // 2 for _ in range(3): if pow(g, r, p) == h: return r, 3 * i , getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) r += l else: j = giants1.get(giant2, None) if j: return (j * m + i * (m + 1)) % ordin, 3 * i, getsizeof(babys) + getsizeof(giants1) + getsizeof(giants2) else: giants2[giant2] = i return None
def worst_shanks_numbers(numOfBits: int): prime = get_primes(numOfBits, 1)[0] while prime < 10: prime = get_primes(numOfBits, 1)[0] generator = artmod.generator_Zp(prime) n = math.ceil(artmod.sqrt(prime - 1)) exp = n * (n - 1) if exp >= prime - 1: exp = n * (n - 2) h = pow(generator, exp, prime) return prime, generator, exp, h
def shanks_classic_better_avg(g, h, p, ordin): n = ceil(sqrt(ordin/2)) e = 1 lista = {e: 0} for j in range(1, n): e = (e * g) % p if e == h: return j, j, 0, getsizeof(lista) else: lista[e] = j u = pow(g, p - n - 1, p) e = h for i in range(0, 2 * n): try: j = lista[e] return i * n + j, n, i + 1, getsizeof(lista) except KeyError: e = (e * u) % p return None
def shanks_classic_binary_search(g, h, p, ordin): n = ceil(sqrt(ordin)) small_steps = 1 e = 1 lista = [(e,0)] for j in range(1, n): e = (e * g) % p if e == h: return j, small_steps, 0, getsizeof(lista) else: lista.append((e,j)) small_steps += 1 lista.sort(key=lambda x: x[0]) u = pow(g, p - n - 1, p) e = h for i in range(0, n): j = find_index(lista, e) if j != None: return i * n + j, small_steps, i + 1, getsizeof(lista) else: e = (e * u) % p return None
def shanks_classic(g, h, p, ordin): n = ceil(sqrt(ordin)) e = 1 lista = {e: 0} dict_limit = 1.15 * (10 ** 10) for j in range(1, n): if getsizeof(lista) > dict_limit: return None, None, None, None e = (e * g) % p if e == h: return j, j, 0, getsizeof(lista) else: lista[e] = j u = pow(g, p - n - 1, p) e = h for i in range(0, n): try: j = lista[e] return i * n + j, n, i + 1, getsizeof(lista) except KeyError: e = (e * u) % p return None
def optim_factors(ordin): factori = [pow(x, e) for x, e in factorint(ordin).items()] factori.sort() if len(factori) == 1: return Shanks_ordin_cunoscut(g, h, p, ordin) if len(factori) == 2: l = ceil(sqrt(factori[1])) m = ceil(sqrt(factori[0])) else: fact_1 = reduce(mul, factori[:-1]) if fact_1 > factori[-1]: l = ceil(sqrt(fact_1)) m = ceil(sqrt(factori[-1])) else: l = ceil(sqrt(factori[-1])) m = ceil(sqrt(fact_1)) return l, m
def shanks_classic_with_memory(g, h_values, p, ordin): n = ceil(sqrt(ordin)) small_steps = 1 e = 1 lista = {e: 0} for j in range(1, n): e = (e * g) % p lista[e] = j small_steps += 1 u = pow(g, p - n - 1, p) exponents, giant_steps_list = [], [] for h in h_values: e = h for i in range(0, n): try: j = lista[e] exponents.append(i * n + j) giant_steps_list.append(i + 1) break except KeyError: e = (e * u) % p return exponents, small_steps, giant_steps_list, getsizeof(lista)
return exponents[-1] % (p - 1), t_cong, it if __name__ == '__main__': i = 0 ts, tts = [], [] its = [] seed(42) for q in range(5): for _ in range(500): ok = 1 while ok: ok = 0 p, g, exponent, h = logarithm_test_numbers(15, safe=False) x = 2**ceil(log2(p - 1)) B = ceil(exp(1 / sqrt(2) * sqrt(log(x) * log(log(x)))) / 2) # print(L(p), shanks_complex(p)) primesB = primes_up_to_B(B) max_equations = primes_upto(B) + 5 # print(B, max_equations, p) t = timer() x, ta, it = SELD_lect11(g, h, p, B, max_equations, primesB, 42) ts.append((timer() - t) * 1000) its.append(it) if x == exponent: # print("DA") i += 1 else: if pow(g, x, p) != h: print("Nu") avg_ts = avg(ts)
from aritmetica_modulara import sqrt, extended_euclid, avg from math import gcd, ceil, floor import random as rand from functools import partial from sys import getsizeof A = (sqrt(5) - 1) / 2 def found_match(g, h, p, a_x, a_y, b_x, b_y): u = (a_x - a_y) % (p - 1) v = (b_y - b_x) % (p - 1) if v == 0: return None d, s, t = extended_euclid(v, p - 1) if d == 1: return (u * s) % (p - 1) else: # print("D: ",d) w = ((u * s) % (p - 1)) // d sol_pos = [w] + [(w + k * ((p - 1) // d)) % (p - 1) for k in range(1, d)] for sol in sol_pos: if pow(g, sol, p) == h: return sol return None def hash_function(num, r): return floor(((A * num) % 1) * r) + 1
def test_pollard(numOfTests: int, listOfBits: list, contests: dict, img_path: str, rand_seeds=[0]): import matplotlib.pyplot as plt from matplotlib.lines import Line2D from itertools import cycle marker = cycle(rand.sample(Line2D.markers.keys(), len(contests))) plt.tight_layout(pad=0.05) times = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits] times_avg = [[0 for _ in contests] for _ in listOfBits] iterations = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits] iterations_avg = [[0 for _ in contests] for _ in listOfBits] for ind_b, bits in enumerate(listOfBits): print("Bits: ", bits) tests = num_of_tests(bits, numOfTests) print("Nr of tests: ", tests) p_set = set() print("Seed: ", end='') for ind_s, seed in enumerate(rand_seeds): rand.seed(seed) print(seed, end=', ') distinct_primes = number_of_distinct_primes(bits) for _ in range(tests): p, g, exp, h = logarithm_test_numbers(bits, safe=False) p_iter = 0 while p in p_set and len( p_set) < distinct_primes - 1 and p_iter < 10**2: p, g, exp, h = logarithm_test_numbers(bits, safe=False) p_iter += 1 p_set.add(p) bit_seed = rand.randint(1, seed) for ind_c, c in enumerate(contests): t = timer() x, iter = pollard_rho(g, h, p, cycle=c[0], func=c[1], rand_seed=bit_seed) if x != exp: print("WRONG " + c[0] + " " + c[1]) times[ind_b][ind_c][ind_s] += (timer() - t) * 1000 iterations[ind_b][ind_c][ind_s] += iter for ind_c, c in enumerate(contests): iterations[ind_b][ind_c][ind_s] /= tests times[ind_b][ind_c][ind_s] /= tests print() for ind_c, c in enumerate(contests): iterations_avg[ind_b][ind_c] = avg( iterations[ind_b][ind_c]) / ceil(sqrt(p)) times_avg[ind_b][ind_c] = avg(times[ind_b][ind_c]) print( f"Cycle: {c[0]}, function: {c[1]}, itertions: {iterations_avg[ind_b][ind_c]:.4f}, time: {times_avg[ind_b][ind_c]:.3f}" ) print() plt.figure(0) for ind_c, c in enumerate(contests): the_times = [t[ind_c] for t in times_avg] plt.plot(listOfBits, the_times, marker=next(marker), label=c[0] + '_' + c[1]) plt.legend() plt.ylabel("Milisecunde") plt.xlabel("biti") # plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) plt.yscale('log') plt.savefig(img_path + '/pollard_time.png', bbox_inches='tight') plt.figure(1) print("The avg number of iterations: ", end='') avgits = [] for ind_c, c in enumerate(contests): the_iterations = [it[ind_c] for it in iterations_avg] avg_c = avg(the_iterations) print(c[0] + '-' + c[1] + f": {avg_c:.4f}", end=' ') avgits.append(avg_c) plt.plot(listOfBits, the_iterations, marker=next(marker), label=c[0] + '_' + c[1]) plt.legend() plt.ylabel("Iteratii") plt.xlabel("biti") # plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 0)) plt.yscale('log') plt.savefig(img_path + '/pollard_iter.png', bbox_inches='tight') plt.show() return avgits
def test_pollard_dellays(numOfTests: int, listOfBits: list, contests: dict, img_path: str, rand_seeds=[0]): iterations = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits] iterations_avg = [[0 for _ in contests] for _ in listOfBits] lambs = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits] lambs_avg = [[0 for _ in contests] for _ in listOfBits] mus = [[[0 for _ in rand_seeds] for _ in contests] for _ in listOfBits] mus_avg = [[0 for _ in contests] for _ in listOfBits] for ind_b, bits in enumerate(listOfBits): print("Bits: ", bits) tests = num_of_tests(bits, numOfTests) print("Nr of tests: ", tests) p_set = set() print("Seed: ", end='') for ind_s, seed in enumerate(rand_seeds): rand.seed(seed) print(seed, end=', ') distinct_primes = number_of_distinct_primes(bits) for _ in range(tests): p, g, exp, h = logarithm_test_numbers(bits, safe=False) p_iter = 0 while p in p_set and len( p_set) < distinct_primes - 1 and p_iter < 10**2: p, g, exp, h = logarithm_test_numbers(bits, safe=False) p_iter += 1 p_set.add(p) bit_seed = rand.randint(1, seed) for ind_c, c in enumerate(contests): x, iter, lamb, mu = pollard_rho(g, h, p, cycle=c[0], func=c[1], rand_seed=bit_seed) if x != exp: print("WRONG " + c[0] + " " + c[1]) iterations[ind_b][ind_c][ind_s] += iter lambs[ind_b][ind_c][ind_s] += lamb mus[ind_b][ind_c][ind_s] += mu for ind_c, c in enumerate(contests): iterations[ind_b][ind_c][ind_s] /= tests lambs[ind_b][ind_c][ind_s] /= tests mus[ind_b][ind_c][ind_s] /= tests print() for ind_c, c in enumerate(contests): iterations_avg[ind_b][ind_c] = avg( iterations[ind_b][ind_c]) / ceil(sqrt(p)) lambs_avg[ind_b][ind_c] = avg(lambs[ind_b][ind_c]) / ceil(sqrt(p)) mus_avg[ind_b][ind_c] = avg(mus[ind_b][ind_c]) / ceil(sqrt(p)) print( f"Cycle: {c[0]}, function: {c[1]}, itertions: {iterations_avg[ind_b][ind_c]:.4f}, lambs: {lambs_avg[ind_b][ind_c]:.4f} mus: {mus_avg[ind_b][ind_c]:.4f}, " f"rho: {lambs_avg[ind_b][ind_c] + mus_avg[ind_b][ind_c]:.4f} delay: {iterations_avg[ind_b][ind_c]/(lambs_avg[ind_b][ind_c] + mus_avg[ind_b][ind_c]):.4f}" ) print() for ind_c, c in enumerate(contests): the_iterations = avg([it[ind_c] for it in iterations_avg]) the_lambs = [lamb[ind_c] for lamb in lambs_avg] the_mus = [mu[ind_c] for mu in mus_avg] the_rhos = avg([x + y for x, y in zip(the_lambs, the_mus)]) print( f"Cycle: {c[0]}, function: {c[1]}, itertions_avg: {the_iterations:.4f}, rho: {the_rhos:.4f}, delays {the_iterations/the_rhos:.4f}" )
def test_shanks_clasic_inter_grumpy(numOfTests: int, numOfBits: list, randSeeds=[0]): total_steps_class_list, times_clasic_list, total_memory_clasic = [], [], [] total_steps_inter_list, times_inter_list, total_memory_inter = [], [], [] total_steps_grumpy_list, times_grumpy_list, total_memory_grumpy = [], [], [] for bits in numOfBits: seed_steps_class_list, seed_times_clasic_list, seed_total_memory_clasic = [], [], [] seed_steps_inter_list, seed_times_inter_list, seed_total_memory_inter = [], [], [] seed_steps_grumpy_list, seed_times_grumpy_list, seed_total_memory_grumpy = [], [], [] print("Started: ", bits) if bits >= 50: numOfTests = 50 elif bits >= 40: numOfTests = 100 elif bits >= 30: numOfTests = 500 for s in randSeeds: seed(s) time_clas, time_inter, time_grumpy = [], [], [] steps_clas, steps_inter, steps_grumpy = [], [], [] mem_clas, mem_inter, mem_grumpy = [], [], [] for iter in range(numOfTests): p, g, exp, h = gnp.logarithm_test_numbers(bits, False) t = timer() x_c, small_clas, giant_clas, mem_c = shanks_classic( g, h, p, p - 1) steps_clas.append(small_clas + giant_clas) mem_clas.append(mem_c) passed_time = (timer() - t) * 1000 time_clas.append(passed_time) t = timer() x_c, oper, mem_c = shanks_interleved(g, h, p, p - 1) if x_c != exp: print("NI") steps_inter.append(oper) mem_inter.append(mem_c) passed_time = (timer() - t) * 1000 time_inter.append(passed_time) t = timer() x_c, oper, mem_c = shanks_two_grumpys_one_baby(g, h, p, p - 1) if x_c != exp: print("NG") steps_grumpy.append(oper) mem_grumpy.append(mem_c) passed_time = (timer() - t) * 1000 time_grumpy.append(passed_time) seed_steps_class_list.append(avg(steps_clas) / ceil(sqrt(p))) seed_steps_inter_list.append(avg(steps_inter) / ceil(sqrt(p))) seed_steps_grumpy_list.append(avg(steps_grumpy) / ceil(sqrt(p))) seed_times_clasic_list.append(avg(time_clas)) seed_times_inter_list.append(avg(time_inter)) seed_times_grumpy_list.append(avg(time_grumpy)) seed_total_memory_clasic.append(avg(mem_clas) / ceil(sqrt(p))) seed_total_memory_inter.append(avg(mem_inter) / ceil(sqrt(p))) seed_total_memory_grumpy.append(avg(mem_grumpy) / ceil(sqrt(p))) print( f"Avg steps clasic:{avg(seed_steps_class_list):.4f} -- Avg steps inter:{avg(seed_steps_inter_list):.4f} -- Avg steps grumpy:{avg(seed_steps_grumpy_list):.4f}" ) print( f"Avg memory clasic:{avg(seed_total_memory_clasic):.4f} -- Avg memory inter:{avg(seed_total_memory_inter):.4f} -- Avg memory grumpy:{avg(seed_total_memory_grumpy):.4f}" ) print( f"Avg time clasic:{avg(seed_times_clasic_list):.4f} -- Avg time inter:{avg(seed_times_inter_list):.4f} -- Avg time grumpy:{avg(seed_times_grumpy_list):.4f}" ) total_steps_class_list.append(avg(seed_steps_class_list)) total_steps_inter_list.append(avg(seed_steps_inter_list)) total_steps_grumpy_list.append(avg(seed_steps_grumpy_list)) times_clasic_list.append(avg(seed_times_clasic_list)) times_inter_list.append(avg(seed_times_inter_list)) times_grumpy_list.append(avg(seed_times_grumpy_list)) total_memory_clasic.append(avg(seed_total_memory_clasic)) total_memory_inter.append(avg(seed_total_memory_inter)) total_memory_grumpy.append(avg(seed_total_memory_grumpy)) print(f"Finished: {bits}\n") print( f"Avg steps clasic:{avg(total_steps_class_list):.4f} -- Avg steps inter:{avg(total_steps_inter_list):.4f} -- Avg steps grumpy:{avg(total_steps_grumpy_list):.4f}" ) print( f"Avg memory clasic:{avg(total_memory_clasic):.4f} -- Avg memory inter:{avg(total_memory_inter):.4f} -- Avg memory grumpy:{avg(total_memory_grumpy):.4f}" ) print( f"Avg time clasic:{avg(times_clasic_list):.4f} -- Avg time inter:{avg(times_inter_list):.4f} -- Avg time grumpy:{avg(times_grumpy_list):.4f}" )
def L(x): x = 2**ceil(log2(x)) return exp(sqrt(2) * sqrt(log(x) * log(log(x))))