def attack(self, publickey, cipher=[], progress=True): """Run tests against mersenne composites""" with timeout(self.timeout): try: p = q = None for i in tqdm(range(2, ilog2(publickey.n)), disable=(not progress)): i2 = 2**i mersenne = [i2 - 1, i2 + 1] g0, g1 = gcd(mersenne[0], publickey.n), gcd(mersenne[1], publickey.n) if 1 < g0 < publickey.n: p = publickey.n // g0 q = g0 break if 1 < g1 < publickey.n: p = publickey.n // g1 q = g1 break if p is not None and q is not None: priv_key = PrivateKey(int(p), int(q), int(publickey.e), int(publickey.n)) return (priv_key, None) return (None, None) except TimeoutError: 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 attack(self, publickey, cipher=[], progress=True): """Run tests against primorial +-1 composites""" with timeout(self.timeout): try: limit = 10000 prime = 1 primorial = 1 p = q = None for x in tqdm(range(0, limit), disable=(not progress)): prime = next_prime(prime) primorial *= prime primorial_p1 = [primorial - 1, primorial + 1] g0, g1 = gcd(primorial_p1[0], publickey.n), gcd(primorial_p1[1], publickey.n) if 1 < g0 < publickey.n: p = publickey.n // g0 q = g0 break if 1 < g1 < publickey.n: p = publickey.n // g1 q = g1 break if p is not None and q is not None: priv_key = PrivateKey(int(p), int(q), int(publickey.e), int(publickey.n)) return (priv_key, None) return (None, None) except TimeoutError: return (None, None)
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 common_modulus_attack(self, c1, c2, k1, k2): if k1.n != k2.n: return None if gcd(k1.e, k2.e) != 1: return None deciphered_message = common_modulus(k1.e, k2.e, k1.n, c1, c2) return long_to_bytes(deciphered_message)
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 comfact(self, cipher, publickey): for c in cipher: commonfactor = gcd(publickey.n, s2n(c)) if commonfactor > 1: publickey.q = commonfactor publickey.p = publickey.n // publickey.q priv_key = PrivateKey( int(publickey.p), int(publickey.q), int(publickey.e), int(publickey.n), ) return (priv_key, None) return (None, None)
def pollard_rho(self, n, seed=2, p=2, c=1): if n & 1 == 0: return 2 if n % 3 == 0: return 3 if n % 5 == 0: return 5 if is_prime(n): return n f = lambda x: x**p + c x, y = seed, seed while True: x = f(x) % n y = f(f(y)) % n d = gcd((x - y), n) if d > 1: return d
def SQUFOF(N): s = int(isqrt(N) + 0.5) L = int(2 * isqrt(2 * s)) if s ** 2 == N: return s for k in range(0, len(multiplier)): D = multiplier[k] * N Po = Pprev = P = isqrt(D) Qprev = 1 Q = D - pow(Po, 2) B = 3 * L c0 = True i = 2 while c0: b = int((Po + P) // Q) P = b * Q - P q = Q Q = Qprev + b * (Pprev - P) r = int(isqrt(Q) + 0.5) if not (i & 1) and (pow(r, 2) == Q): break Qprev = q Pprev = P i += 1 c0 = i <= B b = (Po - P) // r Pprev = P = b * r + P Qprev = r Q = (D - pow(Pprev, 2)) // Qprev i = 0 c1 = True while c1: b = int((Po + P) // Q) Pprev = P P = b * Q - P q = Q Q = Qprev + b * (Pprev - P) Qprev = q i += 1 c1 = P != Pprev r = gcd(N, Qprev) if 1 < r < N: return r, N // r return -1
def attack(self, publickey, cipher=[], progress=True): """Run tests against fermat composites""" with timeout(self.timeout): try: limit = 10000 p = q = None for x in tqdm(range(1, limit), disable=(not progress)): f = gcd(fib(x), publickey.n) if 1 < f < publickey.n: p = publickey.n // f q = f break if p is not None and q is not None: priv_key = PrivateKey(int(p), int(q), int(publickey.e), int(publickey.n)) return (priv_key, None) return (None, None) except TimeoutError: return (None, None)
def attack(self, publickey, cipher=[], progress=True): """System primes in crypto constants""" with timeout(self.timeout): try: primes = load_system_consts() for prp in tqdm(primes, disable=(not progress)): g = gcd(publickey.n, prp) if publickey.n > g > 1: publickey.q = g publickey.p = publickey.n // publickey.q priv_key = PrivateKey( int(publickey.p), int(publickey.q), int(publickey.e), int(publickey.n), ) return (priv_key, None) except TimeoutError: return (None, None) return (None, None)
def attack(self, publickeys, cipher=[]): """Common factor attack""" if not isinstance(publickeys, list): return (None, None) with timeout(self.timeout): try: pubs = [pub.n for pub in publickeys] # Try to find the gcd between each pair of moduli and resolve the private keys if gcd > 1 priv_keys = [] M = ProductTree(pubs) for i in range(0, len(pubs) - 1): pub = pubs[i] x = publickeys[i] R = M // pub g = gcd(pub, R) if pub > g > 1: try: p = g q = pub // g x.p = p x.q = q # update each attackobj with a private_key priv_key_1 = PrivateKey( int(x.p), int(x.q), int(x.e), int(x.n) ) priv_keys.append(priv_key_1) self.logger.info( "[*] Found common factor in modulus for " + x.filename ) except ValueError: continue except TimeoutError: return (None, None) priv_keys = list(set(priv_keys)) if len(priv_keys) == 0: priv_keys = None return (priv_keys, None)
def euler(self, n): if n & 1 == 0: return (n >> 1, 2) if n > 2 else (2, 1) end = isqrt(n) a = 0 solutionsFound = [] firstb = -1 while a < end and len(solutionsFound) < 2: bsquare = n - pow(a, 2) if bsquare > 0: b = isqrt(bsquare) if (pow(b, 2) == bsquare) and (a != firstb) and (b != firstb): firstb = b solutionsFound.append([b, a]) a += 1 if len(solutionsFound) < 2: return None a = solutionsFound[0][0] b = solutionsFound[0][1] c = solutionsFound[1][0] d = solutionsFound[1][1] k = pow(gcd(a - c, d - b), 2) h = pow(gcd(a + c, d + b), 2) m = pow(gcd(a + c, d - b), 2) l = pow(gcd(a - c, d + b), 2) p, q = gcd(k + h, n), gcd(l + m, n) if n > p > 1: return p, n // p if n > q > 1: return q, n // q