CrossCTF Finals 2018 : BabyRSA3 (crypto)
So I heard that you can flip the private and public information for RSA...
Creator - prokarius (@prokarius)
We are given a file outNerfed.txt, which contains c
, the ciphertext, d
, the private exponent and phi(n)
, which is equal to (p-1)(q-1)
.
Challenge
To decrypt the ciphertext, we will need d
and n
. So the challenge here is to find a way to get n
from phi(n)
.
Solution
Factorization
To get n
from phi(n)
, the most sensical step is to find p-1
and q-1
, so that we can find n=pq
. We tried to use yafu to do it, and it worked very nicely.
daniel@daniel ~/Downloads/yafu ./yafu 'factor(25744472610420721576721354142700666534585707423276540379553111662924462766649397845238736588395849560582824664399879219093936415146333463826035714360316647265405615591383999147878527778914526369981160444050742606139799706884875928674153255909145624833489266194817757115584913491575124670523917871310421296173148930930573096639196103714702234087492)'
fac: factoring 25744472610420721576721354142700666534585707423276540379553111662924462766649397845238736588395849560582824664399879219093936415146333463826035714360316647265405615591383999147878527778914526369981160444050742606139799706884875928674153255909145624833489266194817757115584913491575124670523917871310421296173148930930573096639196103714702234087492
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C346
rho: x^2 + 2, starting 1000 iterations on C346
rho: x^2 + 1, starting 1000 iterations on C346
pm1: starting B1 = 150K, B2 = gmp-ecm default on C346
ecm: 0/30 curves on C334, B1=2K, B2=gmp-ecm default
ecm: 0/29 curves on C322, B1=2K, B2=gmp-ecm default
ecm: 0/28 curves on C310, B1=2K, B2=gmp-ecm default
ecm: 0/27 curves on C272, B1=2K, B2=gmp-ecm default
ecm: 0/26 curves on C259, B1=2K, B2=gmp-ecm default
ecm: 1/25 curves on C246, B1=2K, B2=gmp-ecm default
ecm: 0/23 curves on C221, B1=2K, B2=gmp-ecm default
ecm: 1/22 curves on C196, B1=2K, B2=gmp-ecm default
ecm: 1/20 curves on C183, B1=2K, B2=gmp-ecm default
ecm: 0/18 curves on C170, B1=2K, B2=gmp-ecm default
ecm: 2/17 curves on C157, B1=2K, B2=gmp-ecm default
ecm: 3/14 curves on C144, B1=2K, B2=gmp-ecm default
ecm: 1/10 curves on C132, B1=2K, B2=gmp-ecm default
ecm: 8/8 curves on C119, B1=2K, B2=gmp-ecm default
ecm: 3/74 curves on C119, B1=11K, B2=gmp-ecm default
fac: factoring 48636585985082768736526784024200750021
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C38
rho: x^2 + 2, starting 1000 iterations on C38
rho: x^2 + 1, starting 1000 iterations on C38
pm1: starting B1 = 150K, B2 = gmp-ecm default on C38
ecm: 0/30 curves on C38, B1=2K, B2=gmp-ecm default
ecm: 0/29 curves on C26, B1=2K, B2=gmp-ecm default
Total factoring time = 0.1867 seconds
fac: factoring 52537838568268884632273629
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C26
rho: x^2 + 2, starting 1000 iterations on C26
rho: x^2 + 1, starting 1000 iterations on C26
pm1: starting B1 = 150K, B2 = gmp-ecm default on C26
ecm: 1/30 curves on C26, B1=2K, B2=gmp-ecm default
Total factoring time = 0.2959 seconds
fac: factoring 9434943930960179869296047
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C25
rho: x^2 + 2, starting 1000 iterations on C25
rho: x^2 + 1, starting 1000 iterations on C25
pm1: starting B1 = 150K, B2 = gmp-ecm default on C25
ecm: 1/30 curves on C25, B1=2K, B2=gmp-ecm default
Total factoring time = 0.2060 seconds
Total factoring time = 4.6255 seconds
***factors found***
P1 = 2
P1 = 2
P13 = 2767687179787
P12 = 333600482773
P13 = 6938103821809
P13 = 3680247726403
P13 = 8313722160551
P13 = 6438418759151
P13 = 6545600536253
P13 = 6672422609813
P13 = 6579600728639
P13 = 3639128890921
P13 = 9566431650679
P13 = 9220079755217
P106 = 2293498615990071511610820895302086940796564989168281123737588839386922876088484808070018553110125686555051
P13 = 4065711354007
P13 = 1973804930501
P13 = 6060693342503
P13 = 7265658595571
P13 = 7230980905199
P13 = 4754509728797
P13 = 1984419944251
ans = 1
Cleaning up the output, and putting them into a python script
a = []
a.append(2)
a.append(2)
a.append(2767687179787)
a.append(7230980905199)
a.append(3680247726403)
a.append(7265658595571)
a.append(6545600536253)
a.append(6579600728639)
a.append(3639128890921)
a.append(333600482773)
a.append(9220079755217)
a.append(8313722160551)
a.append(9566431650679)
a.append(6938103821809)
a.append(6438418759151)
a.append(2293498615990071511610820895302086940796564989168281123737588839386922876088484808070018553110125686555051)
a.append(4754509728797)
a.append(6672422609813)
a.append(1973804930501)
a.append(6060693342503)
a.append(1984419944251)
a.append(4065711354007)
c = 5499541793182458916572235549176816842668241174266452504513113060755436878677967801073969318886578771261808846567771826513941339489235903308596884669082743082338194484742630141310604711117885643229642732544775605225440292634865971099525895746978617397424574658645139588374017720075991171820873126258830306451326541384750806605195470098194462985494
d = 15664449102383123741256492823637853135125214807384742239549570131336662433268993001893338579081447660916548171028888182200587902832321164315176336792229529488626556438838274357507327295590873540152237706572328731885382033467068457038670389341764040515475556103158917133155868200492242619473451848383350924192696773958592530565397202086200003936447
phi = 25744472610420721576721354142700666534585707423276540379553111662924462766649397845238736588395849560582824664399879219093936415146333463826035714360316647265405615591383999147878527778914526369981160444050742606139799706884875928674153255909145624833489266194817757115584913491575124670523917871310421296173148930930573096639196103714702234087492
Find n
Now, we just need to split the factors into 2 sets, satisfying the condition that the product of the integers in each set, added by 1, will be a prime number.
In other words, split the factors we got into p-1
and q-1
, while making sure that p
and q
are both prime.
To do so, we can use itertools.combinations
to generate different combinations of factors, and check if they fit the conditions above. Once we managed to find the p
and q
we need, all we need is to do left is find m = c ^ d % n
.
import itertools
import gmpy2
def P(a):
return reduce(lambda x, y: x*y, a)
for n in range(1, 12):
for i in itertools.combinations(a, n):
// check if p and q are prime
if (gmpy2.is_prime(P(i) + 1)) and gmpy2.is_prime(phi / P(i) + 1):
p = P(i) + 1
q = phi / P(i) + 1
// found n, decrypt the ciphertext
n = p * q
plain = gmpy2.powmod(c, d, n)
print hex(plain)[2:].decode('hex')
exit()