def prime_gen(dimension): """ Используем алгоритм Диемитко для генерации чисел нужного порядка """ start_prime = chose_start_prime(dimension) current_prime = mpz(start_prime) p = mpz(start_prime) repit_flag = True U = 0 while p.num_digits() <= dimension: if repit_flag: repit_flag = False N = f_div(mpz(10**(dimension - 1)), mpz(current_prime)) + \ f_div(mpz(10**(dimension - 1) * mpfr(random())), mpz(current_prime)) N = N + 1 if N.is_odd() else N U = 0 p = (N + U) * current_prime + 1 if pow(2, p - 1, p) == 1 and pow(2, N + U, p) != 1: repit_flag = True break else: U += 2 return p
def dec_plaintext(c, secret_msg): ''' brute forces plain text for LSB parity oracle param1 -> cipher text param2 -> secret_msg, here just to see if function is working wouldn't make sense for actual case returns -> brute forced plain text ''' print(secret_msg) e, n = public # msg somewhere in between 0,n as it is mod n lower_bound = 0 upper_bound = n # iterate througn log_2 (n) for i in range(1, int(math.log(n, 2) + 1)): # multiply cipher with 2^(ie) where i [0....log_2(N)] multiplier = pow(2, i * e, n) is_odd = parity_oracle(multiplier * cipher) if is_odd: lower_bound = int(f_div(upper_bound + lower_bound, 2).digits()) else: upper_bound = int(f_div((upper_bound + lower_bound), 2).digits()) if i % 10 == 0: print('upper_bound', long_to_bytes(upper_bound)) if secret_msg in long_to_bytes(upper_bound): break return (upper_bound)
def _step2c_searching_with_one_interval_left(self): ## this is the hardest one. # You need to get the most recent interval set from M, # and then get the first interval of that set. Unpack # the interval tuple to variables a, b most_recent_interval_set = self.M[-1] (a, b) = most_recent_interval_set[0] # Next, compute ri = (2(b x s[-1] - 2B))/self.n # (use gmpy2.c_div for these computations) div_ri = 2 * ((b * self.s[-1]) - self.B * 2) ri = gmpy2.c_div(div_ri, self.n) # Finally, search for an s between (2B+(ri x n))/b # and (3B+(ri x n))/a low = gmpy2.f_div((self.B * 2 + (ri * self.n)), b) high = gmpy2.c_div((self.B * 3 + (ri * self.n)), a) si = self._find_s(low, high) # # If no si is found, increase ri by one and try again. while not si: ri += 1 low = gmpy2.f_div((self.B * 2 + (ri * self.n)), b) high = gmpy2.c_div((self.B * 3 + (ri * self.n)), a) si = self._find_s(low, high) return si
def decrypt(priv, pub, cipher): one = gmpy2.mpz(1) x = gmpy2.sub(gmpy2.powmod(cipher, priv.l, pub.n_sq), one) plain = gmpy2.f_mod(gmpy2.mul(gmpy2.f_div(x, pub.n), priv.m), pub.n) if plain >= gmpy2.f_div(pub.n, 2): plain = plain - pub.n return plain
def biprimality_check(self): self.receive_gg() self.Q = gmpy2.powmod(self.gg, gmpy2.f_div(self.pi + self.qi, 4), self.N) self.send_data(self.Q, 1) self.send_data(33331111, 1) self.send_data(self.Q, 2) self.send_data(33332222, 2) while True: if self.flag_send_3_to_2.value == 0: break Q_list = self.receive_Q_list() # print("Q_list = ", Q_list) # print("Q_list = ", Q_list) Q1 = Q_list[0] Q2 = Q_list[1] Q3 = Q_list[2] Q2_inv = gmpy2.invert(Q2, self.N) Q3_inv = gmpy2.invert(Q3, self.N) biprimality_check = gmpy2.f_mod( (Q1 * Q2_inv * Q3_inv), self.N) == gmpy2.f_mod( mpz(1), self.N) or gmpy2.f_mod( (Q1 * Q2_inv * Q3_inv), self.N) == gmpy2.f_mod( mpz(-1), self.N) return biprimality_check
def initialize(self, num, den, Precision): num = mpz(num) den = mpz(den) self.precision = Precision quotient = gmpy2.f_div(num, den) if gmpy2.is_odd(quotient): self.decimal = 1 else: self.decimal = 0 remainder = gmpy2.fmod(num, den) self.value = [] remainder *= 2 i = 0 while i < self.precision: if remainder < den: remainder *= 2 self.value.append(False) elif remainder > den: self.value.append(True) remainder -= den remainder *= 2 elif remainder == den: self.value.append(True) remainder -= den elif remainder == 0: self.value.append(False) i += 1
def biprimality_check(self): ggt = self.gen_coprime(self.N) while gmpy2.jacobi(ggt, self.N) != 1: ggt = self.gen_coprime(self.N) self.gg = ggt self.send_data(self.gg, 2) self.send_data(11112222, 2) self.send_data(self.gg, 3) self.send_data(11113333, 3) self.Q = gmpy2.powmod(self.gg, gmpy2.f_div((self.N + 1 - self.pi - self.qi), 4), self.N) self.send_data(self.Q, 2) self.send_data(11112222, 2) self.send_data(self.Q, 3) self.send_data(11113333, 3) while True: if self.flag_send_1_to_3.value == 0: break Q_list = self.receive_Q_list() # print("Q_list = ", Q_list) # print("Q_list = ", Q_list) Q1 = Q_list[0] Q2 = Q_list[1] Q3 = Q_list[2] Q2_inv = gmpy2.invert(Q2, self.N) Q3_inv = gmpy2.invert(Q3, self.N) check_data = gmpy2.f_mod((Q1 * Q2_inv * Q3_inv), self.N) if check_data == gmpy2.f_mod( mpz(1), self.N) or check_data == gmpy2.f_mod(mpz(-1), self.N): return True return False
def factoring_challenge_3(): """ Given |3p - 2q| < N^(1/4) and considering A = (3p + 2q) / 2 we can show that A - sqrt(6N) < 1 => A = ceil(sqrt(6N)). Let x be equal distance from A to 3p and 2q, then x = sqrt(A^2 - 6N) => we can calculate p and q based on this. """ modulus = mpz( "72006226374735042527956443552558373833808445147399984182665305798191" "63556901883377904234086641876639384851752649940178970835240791356868" "77441155132015188279331812309091996246361896836573643119174094961348" "52463970788523879939683923036467667022162701835329944324119217381272" "9276147530748597302192751375739387929" ) a, rem = gmpy2.isqrt_rem(6 * modulus) if rem > 0: a += 1 x = gmpy2.isqrt(a ** 2 - 6 * modulus) a_minus_x, a_plus_x = a - x, a + x # either p = (A - x) / 3 and q = (A + x) / 2 p, rem = gmpy2.f_divmod(a_minus_x, 3) if rem == 0: q, rem = gmpy2.f_divmod(a_plus_x, 2) if gmpy2.mul(p, q) == modulus: return p if p < q else q # or p = (A + x) / 3 and q = (A - x) / 2 p, rem = gmpy2.f_divmod(a_plus_x, 3) if rem == 0: q = gmpy2.f_div(a_minus_x, 2) if gmpy2.mul(p, q) == modulus: return p if p < q else q
def p_q_gen(self, bits): self.p = mpz(2)**(bits - 1) + mpz_urandomb(rand, bits - 1) while True: self.p = next_prime(self.p) self.q = f_div(self.p - 1, 2) if is_prime(self.q): break
def output(s1, en1, en2): output_values = s1 #P1 initially set the output to be s1 for i in range(0, len(s2)): a = decrypt(priv, pub, en1[i]) b = decrypt(priv, pub, en2[i]) if (a != 0) and (b != 0): output_values.append(int(gmpy2.f_div(a, b))) return output_values
def _step3_narrowing_set_of_solutions(self, si): # This step reduces the number of possible solutions # It will start by iterating through all the Intervals in the # most recent M. As you iterate through each Interval, unpack # the Interval to variables a, b # most_recent_M = self.M[-1] new_intervals = [] # For each interval a,b for interval in most_recent_M: (a, b) = interval # r_min is ((a x si) - 3B+1)/n (use gmpy2.c_div) div_a = (a * si) - ((self.B * 3) - 1) r_min = gmpy2.c_div(div_a, self.n) # r_max is ((b x si) - 2B)/n (use **gmpy2.f_div**) div_b = (b * si) - (self.B * 2) r_max = gmpy2.f_div(div_b, self.n) # For r in range (r_min, r_max): for r in range(r_min, r_max + 1): # new_a = (2B + (r x n))/ si (use gmpy2.c_div) div_new_a = (self.B * 2) + (r * self.n) new_a = gmpy2.c_div(div_new_a, si) # new_b = ((3B-1) + (r x n))/si (use **gmpy2.f_div**) div_new_b = ((self.B * 3) + 1) + (r * self.n) new_b = gmpy2.f_div(div_new_b, si) # new_interval = Interval( max(a, new_a), min(b, new_b)) new_interval = Interval(max(a, new_a), min(b, new_b)) # add interval to a set of intervals new_intervals.append(new_interval) # append the new intervals to M (the new last element of M will # be the list of intervals discovered) self.M.append(new_intervals) # append si to self.s self.s.append(si) # IF the length of new intervals is 1 AND this single Interval's # a == b, return True, otherwise False if len(new_intervals) == 1: (a, b) = new_intervals[0] if a == b: return True # For explanations on why to use c_div vs f_div, look up these # functions in gmpy2 and then see if you can figure out why one is # used over the other return False
def _step3_narrowing_set_of_solutions(self, si): # This step reduces the number of possible solutions # It will start by iterating through all the Intervals in the # most recent M. As you iterate through each Interval, unpack # the Interval to variables a, b # # For each interval a,b # r_min is ((a x si) - 3B+1)/n (use gmpy2.c_div) # r_max is ((b x si) - 2B)/n (use **gmpy2.f_div**) # For r in range (r_min, r_max): # new_a = (2B + (r x n))/ si (use gmpy2.c_div) # new_b = ((3B-1) + (r x n))/si (use **gmpy2.f_div**) # new_interval = Interval( max(a, new_a), min(b, new_b)) # add interval to a set of intervals # append the new intervals to M (the new last element of M will # be the list of intervals discovered) # append si to self.s # IF the length of new intervals is 1 AND this single Interval's # a == b, return True, otherwise False # For explanations on why to use c_div vs f_div, look up these # functions in gmpy2 and then see if you can figure out why one is # used over the other mostRecentM = self.M[-1] intervals = [] for a,b in mostRecentM: r_min = ((a * si) - 3 * self.B + 1) r_min = gmpy2.c_div(r_min, self.n) r_max = ((b * si) - 2 * self.B) r_max = gmpy2.f_div(r_max, self.n) for r in range(r_min, r_max + 1): new_a = (2 * self.B + (r * self.n)) new_a = gmpy2.c_div(new_a, si) new_b = ((3 * self.B-1) + (r * self.n)) new_b = gmpy2.f_div(new_b, si) new_interval = Interval( max(a, new_a), min(b, new_b)) intervals.append(new_interval) self.M.append(intervals) self.s.append(si) if len(intervals) == 1 and intervals[0].a == intervals[0].b: return True else: return False
def _step3_narrowing_set_of_solutions(self, si): new_intervals = set() for a,b in self.M[-1]: r_min = gmpy2.c_div((a*si - 3*self.B + 1),self.n) r_max = gmpy2.f_div((b*si - 2*self.B),self.n) for r in range(r_min, r_max+1): a_candidate = gmpy2.c_div((2*self.B+r*self.n),si) b_candidate = gmpy2.f_div((3*self.B-1+r*self.n),si) new_interval = Interval(max(a, a_candidate), min(b,b_candidate)) new_intervals.add(new_interval) new_intervals = list(new_intervals) self.M.append(new_intervals) self.s.append(si) if len(new_intervals) == 1 and new_intervals[0].a == new_intervals[0].b: return True return False
def decrypt(c, lbd, mu, n): """ Decrypts encrypted number c with respect to private keys lambda and mu (and public key n) Parameters: m: number to be encrypted lbd,mu: private keys used for the decryption n: public key necessary for decryption Returns: c: encrypted representation of m """ n2 = pow(n, 2) one = gmpy2.mpz(1) x = gmpy2.sub(gmpy2.powmod(c, lbd, n2), one) m = gmpy2.f_mod(gmpy2.mul(gmpy2.f_div(x, n), mu), n) if m >= gmpy2.f_div(n, 2): m = m - n return m
def cf(n, m): """Rational number ``n // m`` to continued fraction. :param n: numerator. :param m: denominator. """ res = [] while m: x = gmpy2.f_div(n, m) res.append(x) n, m = m, n - m * x return res
def proot(a, b, c): tr = gmpy2.mul(b, b) ac = gmpy2.mul(a, c) tr -= gmpy2.mul(ac, 4) tr = gmpy2.isqrt(tr) ta = gmpy2.mul(a, 2) # +ve side ret1 = b + tr ret1 = gmpy2.f_div(ret1, ta) if 0 > ret1: return -ret1 # -ve side ret2 = b - tr ret2 = gmpy2.f_div(ret2, ta) if 0 > ret2: return -ret2 else: print "proot Error" sys.exit()
def cf(n, m): """Rational number ``n / m`` to continued fraction. :param n: numerator. :param m: denominator. """ res = [] while m: x = gmpy2.f_div(n, m) res.append(x) n, m = m, n - m * x return res
def get_prime(dimension : int): dim = dimension start_prime = 1351 repit_flag = True p = mpz(start_prime) while p.num_digits() <= dim: if repit_flag: repit_flag = False # Используется теорема Диемитко https://studfile.net/preview/6268704/page:28/ # Она позволяет строить большие числа на основе существуюших меньших простых чисел # n=qR+1, где q – простое число, R – четное, R<4(q+1). # Высчитаем число N N = f_div(mpz(10 ** (dim - 1)), mpz(start_prime)) + f_div(mpz(10 ** (dim - 1) * mpfr(random())),mpz(start_prime)) # Если оно нечетное, то добавляем 1 N = N + 1 if is_odd(N) else N U = 0 # получаем число и проверяем его на условие теоремы p = (N + U) * start_prime + 1 # если условия выполнены, то ищем новое простое число для расчета if pow(2, p - 1, p) == 1 and pow(2, N + U, p) != 1: return int(p) else: U += 2
def findAVulnerablePrime(bitSize): generator = 65537 m = nt.primorial(prime_default(bitSize), False) max_order = nt.totient(m) max_order_factors = nt.factorint(max_order) order = element_order_general(generator, m, max_order, max_order_factors) order_factors = nt.factorint(order) power_range = [0, order - 1] min_prime = g.bit_set( g.bit_set(g.mpz(0), bitSize // 2 - 1), bitSize // 2 - 2 ) # g.add(pow(g.mpz(2), (length / 2 - 1)), pow(g.mpz(2), (length / 2 - 2))) max_prime = g.bit_set( min_prime, bitSize // 2 - 4 ) # g.sub(g.add(min_prime, pow(g.mpz(2), (length / 2 - 4))), g.mpz(1)) multiple_range = [g.f_div(min_prime, m), g.c_div(max_prime, m)] random_state = g.random_state(random.SystemRandom().randint(0, 2**256)) return random_prime(random_state, nt.primorial(prime_default(bitSize), False), generator, power_range, multiple_range)
def findFactorsCaseThree(self): print("===========================================") print("Modulus N is: " + str(self.N)) #A = ceil(2 * sqrt(6N)) A = gmpy2.ceil(gmpy2.mul(mpz(2), gmpy2.sqrt(gmpy2.mul(mpz(6), self.N)))) print("A is: " + str(A)) #X = sqrt(A^2 - 24N) A_square = gmpy2.mul(A, A) X = gmpy2.sqrt(gmpy2.sub(A_square, gmpy2.mul(mpz(24), self.N))) print("X is: " + str(X)) #q = (A + X)/4 AND p = N/q self.q = gmpy2.f_div(mpz(gmpy2.add(A, X)), mpz(4)) self.p = gmpy2.div(self.N, self.q) prod = gmpy2.mul(self.p, self.q) print("Product of pq is: " + str(prod)) if prod == self.N: print("We have got the factors RIGHT") else: print("We didn't get the factors") print(self.p) print(self.q) self.p = 0 self.q = 0 print("===========================================")
def biprimality_check(self, flag_send_2_to_1, flag_send_2_to_3, data_2_to_1_queue, data_2_to_3_queue, q21, q23): self.receive_gg(q21) self.Q = gmpy2.powmod(self.gg, gmpy2.f_div(self.pi + self.qi, 4), self.N) self.send_data(self.Q, 1, flag_send_2_to_1, flag_send_2_to_3, data_2_to_1_queue, data_2_to_3_queue) self.send_data(22221111, 1, flag_send_2_to_1, flag_send_2_to_3, data_2_to_1_queue, data_2_to_3_queue) self.send_data(self.Q, 3, flag_send_2_to_1, flag_send_2_to_3, data_2_to_1_queue, data_2_to_3_queue) self.send_data(22223333, 3, flag_send_2_to_1, flag_send_2_to_3, data_2_to_1_queue, data_2_to_3_queue) while True: if flag_send_2_to_3.value == 0: break Q_list = self.receive_Q_list(q21, q23) # print("Q_list = ", Q_list) # print("Q_list = ", Q_list) Q1 = Q_list[0] Q2 = Q_list[1] Q3 = Q_list[2] Q2_inv = gmpy2.invert(Q2, self.N) Q3_inv = gmpy2.invert(Q3, self.N) biprimality_check = gmpy2.f_mod((Q1 * Q2_inv * Q3_inv), self.N) == gmpy2.f_mod(mpz(1), self.N) or gmpy2.f_mod( (Q1 * Q2_inv * Q3_inv), self.N) == gmpy2.f_mod(mpz(-1), self.N) return biprimality_check
import gmpy2 from gmpy2 import mpz p=input("enter p") #input a prime number (len(p))<=10^18, p>=3 q=input("enter q") #input a prime number (len(q))<=10^18, q>p m=input("enter m") #The string to be encrypted n=gmpy2.mul(mpz(p),mpz(q)) #product of p, q phi=gmpy2.mul(mpz(mpz(p)-1),mpz(mpz(q)-1)) #product of p-1 and q-1 m=mpz(m) e=gmpy2.next_prime(mpz(gmpy2.f_div(phi,2))) #divide phi by 2, then find the next prime # e=mpz(2) # e=next_prime(mpz(q)) # while (e<phi): # if (phi%e!=0): # break # else: # e=gmpy2.next_prime(e) d=mpz(gmpy2.invert(e,phi)) # e*d=1modphi, therefore calculate d which is the secret key # c=mpz((mpz(mpz(m))**e)%mpz(n)) c=mpz(gmpy2.powmod(m,e,n)) # c is the encrypted value. # m_d=mpz((mpz(mpz(c))**d)%mpz(n)) # m_d=gmpy2.powmod(c,d,n) # print (m_d) print (c) print (e) print (d) print (n)
list_primes = [] p = mpz(start_prime) repit_flag = True U = 0 for i in range(1): print(i) while p.num_digits() <= dimension: if repit_flag: repit_flag = False N = f_div(mpz(10**(dimension - 1)), mpz(current_prime)) + \ f_div(mpz(10**(dimension - 1) * mpfr(random())), mpz(current_prime)) N = N + 1 if N.is_odd() else N U = 0 p = mul((N + U), current_prime) + 1 print(p) if powmod(2, p - 1, p) == 1 and powmod(2, N + U, p) != 1: print(p) list_primes.append(p) repit_flag = True break else: U += 2
def dec(priv, pub, cipher): #(private key, public key, cipher) #to do x = powmod(cipher, priv.l, pub.n_sq) L = f_div(x - 1, pub.n) plain = mpz(L * priv.m) % pub.n return plain
def decimal_round(q: Decimal) -> Decimal: # Implements the workaround by # https://gmplib.org/list-archives/gmp-discuss/2009-May/003767.html *) return f_div(2 * q.numerator + q.denominator, 2 * q.denominator) # type:ignore
#задаем порядок чисел для поиска dim = 10**20000 U = 0 # пока число имеет порядок меньше задаваемого while p.num_digits() <= dim: if repit_flag: repit_flag = False # Используется теорема Диемитко https://studfile.net/preview/6268704/page:28/ # Она позволяет строить большие числа на основе существуюших меньших простых чисел # n=qR+1, где q – простое число, R – четное, R<4(q+1). # Высчитаем число N print(1) N = f_div(mpz(10**(dim - 1)), mpz(current_prime)) + f_div( mpz(10**(dim - 1) * mpfr(random())), mpz(current_prime)) print(2) # Если оно нечетное, то добавляем 1 N = N + 1 if is_odd(N) else N U = 0 # получаем число и проверяем его на условие теоремы p = (N + U) * current_prime + 1 print(p) # если условия выполнены, то ищем новое простое число для расчета if pow(2, p - 1, p) == 1 and pow(2, N + U, p) != 1: print(p) repit_flag = True break else: U += 2
import gmpy2 from gmpy2 import mpz c1 = input() c2 = input() e = input() d = input() n = input() c1 = mpz(c1) c2 = mpz(c2) e = mpz(e) d = mpz(d) n = mpz(n) m_k = mpz(mpz(gmpy2.powmod(c1, d, n)) - 1) # c1^d mod n m_d = gmpy2.f_div(c2, gmpy2.powmod(m_k, e, n)) #c2/(m_k^e mod(n)) print(m_d) print(m_k)
def __init__(self): self.sk = mpz(0) self.pk = [mpz(0) for i in range(2 * beta + 1)] self.seed = 0 self.u_1 = mpz(0) self.modified_secret_key = [mpz(0) for i in range(Theta)] self.encrypted_sk = [mpz(0) for i in range(Theta)] sk_file_check = Path('secret_key.txt') if not sk_file_check.is_file(): print('generating secret key') sk_file = open('secret_key.txt', 'w') self.generate_secret_key() sk_file.write(self.sk.digits()) sk_file.close() else: print('loading secret key') sk_file = open('secret_key.txt', 'r') self.sk = mpz(sk_file.read()) sk_file.close() print('secret key:', self.sk) pk_file_check = Path('short_public_key.txt') if not pk_file_check.is_file(): pk_file = open('short_public_key.txt', 'w') self.generate_public_key() pk_file.writelines("%s\n" % str(pk_i.digits()) for pk_i in self.pk) print('public key generated,', len(self.pk), 'elements') #print([str(pk_i) for pk_i in self.pk]) pk_file.close() else: pk_file = open('short_public_key.txt', 'r') self.pk = [mpz(element.rstrip()) for element in pk_file.readlines()] print('public key loaded,', len(self.pk), 'elements') pk_file.close() enc_sk_file_check = Path('encrypted_sk_and_seed.txt') if not enc_sk_file_check.is_file(): x_p = mpz(gmpy2.mul_2exp(1, kappa)) x_p = mpz(gmpy2.f_div(x_p, self.sk)) self.seed, self.u_1 = generate_sparse_matrix(self.u_1, self.modified_secret_key, x_p) for i in range(Theta): if self.modified_secret_key[i] is True: self.encrypted_sk[i] = self.symmetric_encryption(self.encrypted_sk[i], 1) else: self.encrypted_sk[i] = self.symmetric_encryption(self.encrypted_sk[i], 0) enc_sk_file = open('encrypted_sk_and_seed.txt', 'w') enc_sk_file.write('%s\n' % str(self.seed)) enc_sk_file.write('%s\n' % str(self.u_1)) for i in range(Theta): enc_sk_file.write('%s\n' % str(self.encrypted_sk[i])) enc_sk_file.close() else: enc_sk_file = open('encrypted_sk_and_seed.txt', 'r') file_contents = [element.rstrip() for element in enc_sk_file.readlines()] self.seed = int(file_contents[0]) self.u_1 = mpz(file_contents[1]) temp = mpz() for i in range(Theta): self.encrypted_sk[i] = mpz(file_contents[i+2]) temp = self.decrypt_bit(self.encrypted_sk[i]) if temp == 1: self.modified_secret_key[i] = True else: self.modified_secret_key[i] = False enc_sk_file.close()
def mpz_mod_modified(op1, op2): rop = gmpy2.f_mod(mpz(op1), mpz(op2)) temp = gmpy2.f_div(mpz(op2), two) if rop > temp: rop = gmpy2.sub(rop, mpz(op2)) return rop
def floor_divide(x, y): return gmpy2.f_div(gmpy2.mpz(x), gmpy2.mpz(y))