Since we are given e, daβ and dbβ, we know the values of kaβ(pβ1)(qβ1) and kbβ(pβ1)(rβ1). It is trivial to deduce that the greatest common divisor (GCD) between these two values is a multiple of (pβ1). Let's call this Ξ±(pβ1).
We can write the following code to obtain Ξ±(pβ1):
We could then iteratively test for the value of Ξ± by asserting that p must be prime.
After finding p, we simply note that
pβ1edaββ1β=kaβ(qβ1)
and use a similar method to find q. Then, we attempt to decode the ciphertext:
paβ=(caβ)dmodn
The method to find r and decode the second part of the flag is exactly the same.
from decimal import *
getcontext().prec = 1000
def gcd(a, b):
while b:
a, b = b, a % b
return a
de_a = d_a * e
de_b = d_b * e
p_multiple = Decimal(gcd(de_a - 1, de_b - 1))
def isPrime(n, k=5): # miller-rabin
from random import randint
if n < 2: return False
for p in [2,3,5,7,11,13,17,19,23,29]:
if n % p == 0: return n == p
s, d = 0, n-1
while d % 2 == 0:
s, d = s+1, d//2
for i in range(k):
x = pow(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in range(1, s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break
else: return False
return True
for i in range(2, 100):
p = Decimal(p_multiple) / Decimal(i) + 1
if isPrime(int(p)):
print('p =', p)
break
q_multiple = Decimal(de_a - 1) / (p - 1)
for i in range(2, 100000):
q = Decimal(q_multiple) / Decimal(i) + 1
if isPrime(int(q)):
m = pow(int(ct_a), int(d_a), int(p) * int(q))
msg = long_to_bytes(m)
try:
print(msg.decode())
break
except:
continue
r_multiple = Decimal(de_b - 1) / (p - 1)
for i in range(2, 100000):
r = Decimal(r_multiple) / Decimal(i) + 1
if isPrime(int(r)):
m = pow(int(ct_b), int(d_b), int(p) * int(r))
msg = long_to_bytes(m)
try:
print(msg.decode())
break
except:
continue