Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/attacks/factorization/known_phi.py
2589 views
1
from math import gcd
2
from math import isqrt
3
from random import randrange
4
5
from sage.all import is_prime
6
7
8
def factorize(N, phi):
9
"""
10
Recovers the prime factors from a modulus if Euler's totient is known.
11
This method only works for a modulus consisting of 2 primes!
12
:param N: the modulus
13
:param phi: Euler's totient, the order of the multiplicative group modulo N
14
:return: a tuple containing the prime factors, or None if the factors were not found
15
"""
16
s = N + 1 - phi
17
d = s ** 2 - 4 * N
18
p = int(s - isqrt(d)) // 2
19
q = int(s + isqrt(d)) // 2
20
return p, q if p * q == N else None
21
22
23
def factorize_multi_prime(N, phi):
24
"""
25
Recovers the prime factors from a modulus if Euler's totient is known.
26
This method works for a modulus consisting of any number of primes, but is considerably be slower than factorize.
27
More information: Hinek M. J., Low M. K., Teske E., "On Some Attacks on Multi-prime RSA" (Section 3)
28
:param N: the modulus
29
:param phi: Euler's totient, the order of the multiplicative group modulo N
30
:return: a tuple containing the prime factors
31
"""
32
prime_factors = set()
33
factors = [N]
34
while len(factors) > 0:
35
# Element to factorize.
36
N = factors[0]
37
38
w = randrange(2, N - 1)
39
i = 1
40
while phi % (2 ** i) == 0:
41
sqrt_1 = pow(w, phi // (2 ** i), N)
42
if sqrt_1 > 1 and sqrt_1 != N - 1:
43
# We can remove the element to factorize now, because we have a factorization.
44
factors = factors[1:]
45
46
p = gcd(N, sqrt_1 + 1)
47
q = N // p
48
49
if is_prime(p):
50
prime_factors.add(p)
51
elif p > 1:
52
factors.append(p)
53
54
if is_prime(q):
55
prime_factors.add(q)
56
elif q > 1:
57
factors.append(q)
58
59
# Continue in the outer loop
60
break
61
62
i += 1
63
64
return tuple(prime_factors)
65
66