RSA's Schools
Some RSA challenges of UDCTF 2023
Crypto
~4 minutes
RSA School 1st Grade
142 solves - 50 points
Description
First day of school!
Given Files
- First_Grade.py
- output.txt
Solution
En regardant le contenu de First_Grade.py :
from Crypto.Util.number import *
p=getPrime(512)
q=getPrime(512)
n=p*q
e=65537
msg=bytes_to_long(b'UDCTF{REDACTED}')
ct=pow(msg,e,n)
print(p)
print(n)
print(e)
print(ct)
et output.txt :
7009789528005665925389589645247771843738610365138497450285434114825324963561464592190523618045678504210355855286077875965585945664408796837853566415684077
73061872549912499570368059392056653520123131891860048946474996807859190776947568485365189613739847632132597352816568237525325622321891749472819811314630053648031678826291232292672975634200777457699671848298242827252269004463672931479153540235625891818449660268924228002522141737330313259535617652381070426543
65537
8099012654842320180974620472267007973324910863630262955526926760464542904631823196320598910081443799605804614201671967967929893760527002416689993003801924422327762868245291561376910828637706061326005113536536357969201659290874169593264337355365186414719656091960977568710047843815328537885731546232759484717
On peut voir qu'il s'agit d'un chiffrement RSA simple avec un exposant de 65537.
On peut faire un script python permettant de retrouver msg
:
from Crypto.Util.number import *
p = 7009789528005665925389589645247771843738610365138497450285434114825324963561464592190523618045678504210355855286077875965585945664408796837853566415684077
n =
73061872549912499570368059392056653520123131891860048946474996807859190776947568485365189613739847632132597352816568237525325622321891749472819811314630053648031678826291232292672975634200777457699671848298242827252269004463672931479153540235625891818449660268924228002522141737330313259535617652381070426543
e = 65537
ct =
8099012654842320180974620472267007973324910863630262955526926760464542904631823196320598910081443799605804614201671967967929893760527002416689993003801924422327762868245291561376910828637706061326005113536536357969201659290874169593264337355365186414719656091960977568710047843815328537885731546232759484717
q = n // p
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = pow(ct, d, n)
print(long_to_bytes(m))
UDCTF{y3a_b0i_b4by_RSA!}
RSA School 2nd Grade
133 solves - 50 points
Description
Ok a little tougher
Given Files
- Second_Grade.py
- output.txt
Solution
En regardant le contenu de Second_Grade.py :
from Crypto.Util.number import *
n=166045890368446099470756111654736772731460671003059151938763854196360081247044441029824134260263654537
e=65537
msg=bytes_to_long(b'UDCTF{REDACTED}')
ct=pow(msg,e,n)
print(n)
print(e)
print(ct)
et output.txt :
166045890368446099470756111654736772731460671003059151938763854196360081247044441029824134260263654537
65537
1419273799864099208451947034999412629880613167064332422893537768023750745252956889042151134458835896538
Le solve est quasiment identique au précédent. Il suffit de changer les variables et de lancer le script python.
On décompose n en produit de facteurs premiers :
p = 51700365364366863879483895851106199085813538441759
q = 3211696652397139991266469757475273013994441374637143
Puis avec la même méthode on trouve :
UDCTF{pr1m3_f4ct0r_the1f!}
RSA School 4th Grade
67 solves - 304 points
Description
Getting tired of school yet?
Given Files
- Fourth_Grade.py
- output.txt
Solution
En regardant le contenu de Fourth_Grade.py :
from Crypto.Util.number import *
e=65537
your_e = getPrime(20)
msg=bytes_to_long(b'UDCTF{REDACTED}')
p=getPrime(512)
q=getPrime(512)
n=p*q
assert(msg < n)
ct=pow(msg, e, n)
your_d = inverse(your_e, (p-1)*(q-1))
print(your_e)
print(your_d)
print(n)
print(e)
print(ct)
et output.txt :
548861
95173232432571941329231712692828118443780574466702093807146321250099677631827067825710345421542241500117509827717221625523077656554170307232963298108032249257829668442277402436905496971410095631707035128294281318370127935482352287840967522858886054571972660826718745245567014905338023490270530223206547055189
128923276994737790032784225847154420815473322545569053376748335367791339027988282369445542202224938698537424444443434684524386629219697192340629226569242894844874718895350330788650992608621499779776079293063355076268941953990983854217613662005027668855183281795022629934463967333582234624036115283306256019477
65537
101925091511033045433108849975441961999589763870098425244810307722908781911184299892072334641669931066841662878745617845011689451171244453969963211155840837507751273716371760271643490363012983256424608885239953158409708266675819028960222627654995967984657602529298637614235721996131897162063485544360691578861
Notre but ici va être d'utiliser l'algoithme de Pohlig-Hellman nous permettant de calculer à plusieurs reprise le PGCD du nombre et d'un nombre aléatoire. Si le PGCD > 1, alors on a trouvé un facteur premier de n.
On va donc utiliser le script suivant :
from math import gcd
from Crypto.Util.number import long_to_bytes
from random import randint
n = 128923276994737790032784225847154420815473322545569053376748335367791339027988282369445542202224938698537424444443434684524386629219697192340629226569242894844874718895350330788650992608621499779776079293063355076268941953990983854217613662005027668855183281795022629934463967333582234624036115283306256019477
d = 95173232432571941329231712692828118443780574466702093807146321250099677631827067825710345421542241500117509827717221625523077656554170307232963298108032249257829668442277402436905496971410095631707035128294281318370127935482352287840967522858886054571972660826718745245567014905338023490270530223206547055189
c = 101925091511033045433108849975441961999589763870098425244810307722908781911184299892072334641669931066841662878745617845011689451171244453969963211155840837507751273716371760271643490363012983256424608885239953158409708266675819028960222627654995967984657602529298637614235721996131897162063485544360691578861
e = 548861
def find_pq(n,e,d):
k = e * d - 1
r = k
t = 0
while r % 2 == 0:
t += 1
r = r // 2
p = 0
g = randint(1, n-1)
while p == 0:
for i in range(t+1):
x = pow(g,k//2**i,n)
p = gcd(x-1,n)
if (x > 1 and p > 1):
break
g = randint(1, n-1)
return p, n//p
p, q = find_pq(n, e, d)
phi = (p-1) * (q-1)
print(phi)
d = pow(65537, -1, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
UDCTF{m0d_mult1pl1c4tiv3_inv3r5e_nd_57uff}
RSA School 7th Grade
71 solves - 280 points
Description
It's grind time
Given Files
- Seventh_Grade.py
- output.txt
Solution
En regardant le contenu de Seventh_Grade.py :
from Crypto.Util.number import *
import sympy.ntheory as nt
import random
p=getPrime(1024)
q=nt.nextprime(p)
for _ in range(random.randint(500,10000)):
q=nt.nextprime(q)
N=p*q
msg="UDCTF{REDACTED}"
pt=bytes_to_long(msg)
e=655
ct=pow(pt,e,N)
print(N)
print(e)
print(ct)
et output.txt :
17740803753336460891508014077951088945415214329359164945595622460861617151883658129377771074141448545977293824812472806768754107334272113784618671425945265453677763300584120796664192793654787317526905676618168560287204392207536711238413377822113265783504873957094131330620182217422910507867161033695120195691266283498385072573721376398480018719760538723050237163598524153522595496137288270407836138586188296538117138982579560625325815068701431157466298638302885600982291990551448117534677697122276691651611734934147801954625280213769902451417946572231015611006746186167211313556716518863585799128114202130873384852581
65537
7617664236008252568996899627946125782926068188323112773389474654757630578865481085502759186904920518615173703165984894164411436709177950136929724052191922739861682189280802963747906815275683543148623167088950096943169566195634558711652670745197446307315888349532981492405588457559228674864147994684328968321710022127803384848143475788457274558988285904875669797926919759123645348144531804252200718312650929926931919262408975771593313266992606751663814830129337536342634243623652919127335934704778878412649409415730419077839365246227059700689395639431013008985996793686430486195007712091309878718060405038405039494286
On peut voir que le nombre de chiffrement est très grand. On va donc utiliser la méthode de Fermat pour trouver les facteurs premiers de N.
On a de la chance, RsaCtfTool permet de faire cela :
python3 RsaCtfTool.py -n 17740803753336460891508014077951088945415214329359164945595622460861617151883658129377771074141448545977293824812472806768754107334272113784618671425945265453677763300584120796664192793654787317526905676618168560287204392207536711238413377822113265783504873957094131330620182217422910507867161033695120195691266283498385072573721376398480018719760538723050237163598524153522595496137288270407836138586188296538117138982579560625325815068701431157466298638302885600982291990551448117534677697122276691651611734934147801954625280213769902451417946572231015611006746186167211313556716518863585799128114202130873384852581 -e 65537 --uncipher 7617664236008252568996899627946125782926068188323112773389474654757630578865481085502759186904920518615173703165984894164411436709177950136929724052191922739861682189280802963747906815275683543148623167088950096943169566195634558711652670745197446307315888349532981492405588457559228674864147994684328968321710022127803384848143475788457274558988285904875669797926919759123645348144531804252200718312650929926931919262408975771593313266992606751663814830129337536342634243623652919127335934704778878412649409415730419077839365246227059700689395639431013008985996793686430486195007712091309878718060405038405039494286
UDCTF{F3rma7_c4n_sur3_fac70r!}
Greatest Hits 2 of 4
64 solves - 100 points
Description
X
Given Files
- rsa.py
- rsaout.txt
Solution
En regardant le contenu de rsa.py :
from Crypto.Util.number import *
p=getPrime(1024)
q=getPrime(1024)
n=p*q
e1=32
e2=94
msg=bytes_to_long("REDACTED")
assert(pow(msg,2) < n)
c1 = pow(msg, e1, n)
c2 = pow(msg, e2, n)
print(n)
print(e1)
print(e2)
print(c1)
print(c2)
et rsaout.txt :
15144989296069059933372368453196092175005161975349151110345314566785160131088640293080496647831336241835434081246752372095089223274410617149601529995353586979709767320781773241635911841825135157128620635284850556358212336804356913383250552153118005157608892746468253056994929497147176358510660250974046147584489593314250043332900225627695013699452589204281775937461626931870469970564649337891804670484615877731064389199146553155645996166903057997780769847954473558252319887360004797752922471164238094762917170732419058459198871816368754874928563582062094607146743861963241102686280889624636580265012154494857871226911
32
94
517413713703886999866857886363089094585257050613499021392236739949207714015445698823055234855661713319078211477553629447153099784179447532323740595057178898139959674381355432131055787089201673781698752057672521217038516832753572594045829378268006522196608125682968252235804171902500675561571516482830716057356093346644739755000641419389456649384154636696468100735075639775740773984117668523785494430624107703773927953688140653884319491595701619752757483259322185639861570200460175036940484201361523531829151771132059047908439112074722779866239565825707838090161372153338024174748440497243107864663782108641727771659
7627448403143228380990811828784190441589966806784538493012623116575366382931836531487460665746937844089811800210162413422176546183916362252942569359187329261606901744873414894672206518833504277712248120517227097337821671357183002903689123275299969496743046843235865472598002895668376113637844709030956945481612135136663699655327584977008477587437014970931004029432308882904616641276931607404737262279319635052041442201857436898171408177118684300765925831306704477989772422231625570934627171304088385754161129883791893955034648200851254688716049371226939666530556140959866437156338956068301001303202802889970914365861
Le challenge ressemble fortement à BrokenRSA sur CryptoHack, seulement ici on a 2 exposants différents.
Les deux exposants ne sont pas premiers. On peut oublier la plupart des attaques car e1
et e2
sont coprimes.
Si e1
et e2
sont premieux entre eux, alors il existe u
et v
tels que (a ^ u) mod n = (a ^ v) mod n
.
On va donc chercher un c1_u
et c2_v
, avec libnum
:
from Crypto.Util.number import long_to_bytes
from math import isqrt
import libnum
n = 15144989296069059933372368453196092175005161975349151110345314566785160131088640293080496647831336241835434081246752372095089223274410617149601529995353586979709767320781773241635911841825135157128620635284850556358212336804356913383250552153118005157608892746468253056994929497147176358510660250974046147584489593314250043332900225627695013699452589204281775937461626931870469970564649337891804670484615877731064389199146553155645996166903057997780769847954473558252319887360004797752922471164238094762917170732419058459198871816368754874928563582062094607146743861963241102686280889624636580265012154494857871226911
e1 = 32
e2 = 94
c1 = 517413713703886999866857886363089094585257050613499021392236739949207714015445698823055234855661713319078211477553629447153099784179447532323740595057178898139959674381355432131055787089201673781698752057672521217038516832753572594045829378268006522196608125682968252235804171902500675561571516482830716057356093346644739755000641419389456649384154636696468100735075639775740773984117668523785494430624107703773927953688140653884319491595701619752757483259322185639861570200460175036940484201361523531829151771132059047908439112074722779866239565825707838090161372153338024174748440497243107864663782108641727771659
c2 = 7627448403143228380990811828784190441589966806784538493012623116575366382931836531487460665746937844089811800210162413422176546183916362252942569359187329261606901744873414894672206518833504277712248120517227097337821671357183002903689123275299969496743046843235865472598002895668376113637844709030956945481612135136663699655327584977008477587437014970931004029432308882904616641276931607404737262279319635052041442201857436898171408177118684300765925831306704477989772422231625570934627171304088385754161129883791893955034648200851254688716049371226939666530556140959866437156338956068301001303202802889970914365861
u, v, z_gcd= libnum.xgcd(e1, e2)
c1_u = pow(c1, u, n)
c2_v = pow(c2, v, n)
print(long_to_bytes(isqrt((c1_u * c2_v) % n)))
UDCTF{l4rg3_int3ger_sqrt_w1th0ut_fl04ts}