Path: blob/master/attacks/factorization/known_phi.py
2589 views
from math import gcd1from math import isqrt2from random import randrange34from sage.all import is_prime567def factorize(N, phi):8"""9Recovers the prime factors from a modulus if Euler's totient is known.10This method only works for a modulus consisting of 2 primes!11:param N: the modulus12:param phi: Euler's totient, the order of the multiplicative group modulo N13:return: a tuple containing the prime factors, or None if the factors were not found14"""15s = N + 1 - phi16d = s ** 2 - 4 * N17p = int(s - isqrt(d)) // 218q = int(s + isqrt(d)) // 219return p, q if p * q == N else None202122def factorize_multi_prime(N, phi):23"""24Recovers the prime factors from a modulus if Euler's totient is known.25This method works for a modulus consisting of any number of primes, but is considerably be slower than factorize.26More information: Hinek M. J., Low M. K., Teske E., "On Some Attacks on Multi-prime RSA" (Section 3)27:param N: the modulus28:param phi: Euler's totient, the order of the multiplicative group modulo N29:return: a tuple containing the prime factors30"""31prime_factors = set()32factors = [N]33while len(factors) > 0:34# Element to factorize.35N = factors[0]3637w = randrange(2, N - 1)38i = 139while phi % (2 ** i) == 0:40sqrt_1 = pow(w, phi // (2 ** i), N)41if sqrt_1 > 1 and sqrt_1 != N - 1:42# We can remove the element to factorize now, because we have a factorization.43factors = factors[1:]4445p = gcd(N, sqrt_1 + 1)46q = N // p4748if is_prime(p):49prime_factors.add(p)50elif p > 1:51factors.append(p)5253if is_prime(q):54prime_factors.add(q)55elif q > 1:56factors.append(q)5758# Continue in the outer loop59break6061i += 16263return tuple(prime_factors)646566