def rsa_recovery(dp, dq, ciphertext, keysize=1024, start=3): ''' This extensive process loops through all unknown e, typically between 3..65537 and given the dP and dQ will search for primes p and q, then attempt to decrypt the ciphertext that is known to have been encrypted with them. ''' # init counters r, p, q, d, count, count2, count3 = (0L, 0L, 0L, 0L, 0, 0, 0) # start generalised loop for an unknown e for j in range(start, 65538, 2): dp1 = long(gmpy2.mul(dp, j) - 1) for k in range(3, j): d = long(k) a, r = gmpy2.t_divmod(dp1, d) assert(dp1 == (k * a) + r) if r == 0: count += 1 p = long(a + 1) if gmpy2.is_odd(p) and gmpy2.is_strong_prp(p, 10): count2 += 1 dq1 = long(gmpy2.mul(dq, j) - 1) for l in range(3, j): d = long(l) a, r = gmpy2.t_divmod(dq1, d) assert(dq1 == (l * a) + r) if r == 0: q = long(a + 1) if gmpy2.is_odd(q) and gmpy2.is_strong_prp(q, 10): count3 += 1 # just some basic progress on the console if count3 % 10 == 0: sys.stdout.write('.') sys.stdout.flush() # only attempt the decrypt if p,q are expected bitlength if p.bit_length() + q.bit_length() == keysize: try: result = rsa_decrypt(p, q, ciphertext, j) if len(result) == 0 or result == "None": # indicates a failed decryption attempt sys.stdout.write('x') else: # SUCCESS! This is your decrypted message, sir... print "\n:: DECRYPTED::\n message = %s" % result # show all the p, q candidates just in case print "\np = %X\nq = %X\n" % (p, q) except Exception as e: print "ERROR: ", e # if cipher text length wrong, change decryption padding etc. pass # do nothing # finish with a counter summary print "count: %d count2: %d count3: %d\n\n" % (count, count2, count3)
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 train_rsa_reduction(n, e, d) : """You are given an RSA secret key. Find p and q and convert them to bytes code from : https://gist.github.com/ddddavidee/b34c2b67757a54ce75cb """ k = d * e - 1 if gmpy2.is_odd(k) : raise ValueError('Prime factors p and q not found') else: t = 0 r = k while(not gmpy2.is_odd(r)): r = int(r // 2) t += 1 for i in range(1, 101): rs = gmpy2.random_state(hash(gmpy2.random_state())) g = int(gmpy2.mpz_random(rs, n)) # random g in [0, n-1] y = pow(g, r, n) if y == 1 or y == n - 1: continue else: for j in range(1, t): # j \in [1, t-1] x = pow(y, 2, n) if x == 1: p, q = outputPrimes(y - 1, n) return (base64.b16decode(hex(p)[2:], casefold=True), base64.b16decode(hex(q)[2:], casefold=True)) elif x == n - 1: continue y = x x = pow(y, 2, n) if x == 1: p, q = outputPrimes(y - 1, n) return (base64.b16decode(hex(p)[2:], casefold=True), base64.b16decode(hex(q)[2:], casefold=True))
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
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 print() print("Общее время:" + str(time() - start_time)) summ = 0