def attack(self, publickey, cipher=[], progress=True): """Same n huge e attack""" if not isinstance(publickey, list): return (None, None) with timeout(self.timeout): try: if len(set([_.n for _ in publickey])) == 1: n = publickey[0].n e_array = [] for k in publickey: e_array.append(k.e) if (cipher is None) or (len(cipher) < 2): self.logger.info( "[-] Lack of ciphertexts, skiping the same_n_huge_e test..." ) return (None, None) # e1*s1 + e2*s2 = 1 _, s1, s2 = gcdext(e_array[0], e_array[1]) # m ≡ c1^s1 * c2*s2 mod n plain = ( powmod(int.from_bytes(cipher[0], "big"), s1, n) * powmod(int.from_bytes(cipher[1], "big"), s2, n)) % n return (None, number.long_to_bytes(plain)) except TimeoutError: return (None, None) return (None, None)
def brent(N): """ Pollard rho with brent optimizations taken from: https://gist.github.com/ssanin82/18582bf4a1849dfb8afd""" if N & 1 == 0: return 2 g = N while g == N: y, c, m = randint(1, N - 1), randint(1, N - 1), randint(1, N - 1) g, r, q = 1, 1, 1 while g == 1: x = y i = 0 while i <= r: y = (powmod(y, 2, N) + c) % N i += 1 k = 0 while k < r and g == 1: ys = y i = 0 while i <= min(m, r - k): y = (powmod(y, 2, N) + c) % N q = q * (abs(x - y)) % N i += 1 g, k = gcd(q, N), k + m if N > g > 1: return g r <<= 1 if g == N: while True: ys = (powmod(ys, 2, N) + c) % N g = gcd(abs(x - ys), N) if N > g > 1: return g
def _fib_res(self, n, p): """ fibonacci sequence nth item modulo p """ if n == 0: return (0, 1) a, b = self._fib_res(n >> 1, p) c = mod((mod(a, p) * mod(((b << 1) - a), p)), p) d = mod((powmod(a, 2, p) + powmod(b, 2, p)), p) if n & 1 == 0: return (c, d) return (d, mod((c + d), p))
def pollard_P_1(self, n, progress=True): """Pollard P1 implementation""" z = [] logn = math.log(int(isqrt(n))) prime = primes(997) for j in range(0, len(prime)): primej = prime[j] logp = math.log(primej) for i in range(1, int(logn / logp) + 1): z.append(primej) try: for pp in tqdm(prime, disable=(not progress)): i = 0 x = pp while 1: x = powmod(x, z[i], n) i = i + 1 y = gcd(n, x - 1) if y != 1: p = y q = n // y return p, q if i >= len(z): return 0, None except TypeError: return 0, None
def solve(M, n, a, m, XX, invmod_Mn, F, x, beta): # I need to import it in the function otherwise multiprocessing doesn't find it in its context from sage_functions import coppersmith_howgrave_univariate base = int(65537) # the known part of p: 65537^a * M^-1 (mod N) known = int(powmod(base, a, M) * invmod_Mn) pol = x + known t = m + 1 # Find a small root (x0 = k) using Coppersmith's algorithm roots = coppersmith_howgrave_univariate(pol, n, beta, m, t, XX) # There will be no roots for an incorrect guess of a. for k in roots: # reconstruct p from the recovered k p = int(k * M + powmod(base, a, M)) if n % p == 0: return p, n // p
def get_n_mod_d(self, n, d, use="mersenne"): if n < 0: ValueError("Negative arguments not implemented") if use == "gmpy": return mod(fib(n), d) elif use == "mersenne": return powmod(2, n, d) - 1 else: return self._fib_res(n, d)[0]
def dixon_factor(N, B=7, explain=False): if is_prime(N): return N, 1 start = isqrt(N) if (start ** 2) == N: return start, start base = primes(B) lqbf = pow(base[-1], 2) + 1 QBF = bitarray.bitarray(lqbf) # This is our quasi-bloom-filter basej2N = [] for j in range(0, len(base)): p = powmod(base[j], 2, N) basej2N.append(p) QBF[p] = 1 # We populate our quasi-bloom-filter i = start while i < N: i2N = pow(i, 2, N) if i2N < lqbf and QBF[i2N] == 1: for k in range(0, len(base)): if QBF[basej2N[k]] == 1: # if i2N == basej2N[k]: # this is replaced with a quasi-bloom-filter f = gcd(i - base[k], N) if explain: print("N = %d" % N) print("%d = isqrt(N)" % start) print("%d = pow(%d,2,n)" % (i2N, i)) print("%d = pow(%d,2,n)" % (basej2N[k], base[k])) print("%d - %d = %d" % (i, base[k], f)) print("%d = gcd(%d - % d, N)" % (f, i, base[k])) print( "%d = gcd(%d + % d, N)" % (gcd(i + base[k], N), i, base[k]) ) if 1 < f < N: return f, N // f i += 1 return None, None
def attack(self, publickey, cipher=[], progress=True): """use elliptic curve method only works if the sageworks() function returned True """ try: sageresult = [] try: sageresult = subprocess.check_output( ["sage", "%s/sage/ecm2.sage" % rootpath, str(publickey.n)], timeout=self.timeout, stderr=subprocess.DEVNULL, ) sageresult = sageresult[1:-2].split(b", ") except (subprocess.CalledProcessError, subprocess.TimeoutExpired): return (None, None) if len(sageresult) > 0: plain = [] sageresults = [int(_.decode("utf-8")) for _ in sageresult] phi = 1 for fac in sageresults: phi = phi * (int(fac) - 1) if cipher is not None and len(cipher) > 0: for c in cipher: try: cipher_int = int.from_bytes(c, "big") d = invert(publickey.e, phi) m = hex(powmod(cipher_int, d, publickey.n))[2::] plain.append(bytes.fromhex(m)) except: continue return (None, plain) return (None, None) except KeyboardInterrupt: pass return (None, None)
def decrypt(self, cipher): """Uncipher data with private key :param cipher: input cipher :type cipher: string """ if not isinstance(cipher, list): cipher = [cipher] plain = [] for c in cipher: if self.n is not None and self.d is not None and self.key is None: try: cipher_int = int.from_bytes(c, "big") m_int = powmod(cipher_int, self.d, self.n) m = binascii.unhexlify(hex(m_int)[2:]).decode() plain.append(m) except: pass try: rsakey = RSA.importKey(str(self)) rsakey = PKCS1_OAEP.new(rsakey) plain.append(rsakey.decrypt(c)) except: pass try: tmp_priv_key = tempfile.NamedTemporaryFile() with open(tmp_priv_key.name, "wb") as tmpfd: tmpfd.write(str(self).encode("utf8")) tmp_priv_key_name = tmp_priv_key.name tmp_cipher = tempfile.NamedTemporaryFile() with open(tmp_cipher.name, "wb") as tmpfd: tmpfd.write(c) tmp_cipher_name = tmp_cipher.name with open("/dev/null") as DN: try: openssl_result = subprocess.check_output( [ "openssl", "rsautl", "-raw", "-decrypt", "-in", "-oaep", tmp_cipher_name, "-inkey", tmp_priv_key_name, ], stderr=DN, timeout=30, ) plain.append(openssl_result) except: pass try: openssl_result = subprocess.check_output( [ "openssl", "rsautl", "-raw", "-decrypt", "-in", tmp_cipher_name, "-inkey", tmp_priv_key_name, ], stderr=DN, timeout=30, ) plain.append(openssl_result) except: pass except: plain.append(cipher) return plain