Category: Cryptography
Flag: apoorvctf{3ncrypt1ng_w1th_RSA_c4n_b3_4_d4ng3r0us_cl1ff_83}
Challenge Description
The Riddler never settles for a single puzzle… why should you? Layers of encryption guard the flag, each hiding some secret. Break through them one by one and prove that even the Riddler’s cleverest traps can be unraveled.
Analysis
The challenge looked like a “many layers” crypto puzzle, but opening enc.py immediately showed classic textbook RSA with e = 3 and no padding. To confirm what mattered, I pulled out the exact public parameters and the encryption line directly from the script.
python inspect_enc.py# N = 17520886769422446781402845171452766678392945055507226042115591127790949038926405961588057901152880775198538951363849458511296788407527886190154759113620716962246342938913740398465525503895457929394994569820769711534794538522137993456194572001467194513826600891537022249206765745867423270603572791751504625621683522248065102814089587644651305112722919320696919194544558237008950904152753314856531469392976852299194227815343105809059455186267184706498969875531092067425496067267400027976328334687257293407409892934030446988318349271430705178690957392508571214791220858911022252486038830213798547638612103672306741523579
# e = 3
# c = 5959848254333830910624523071067197529743942832931749422613446095759596470869632698744448445022974243192082623200541274049999046045462632699888118125553180389758240097512080800465269924123706310996597928101365256237876736940573969864179631586328876422479408805381027940806738410297399027560825960052951200511768291312433697743253773594534719688371211151318607767527029263892621127356788516738086153844247429662752321125
e = 3
c = pow(m, e, N)At that point the solve path is short and sweet: when RSA uses small exponent e = 3 without padding, and the message is small enough, encryption becomes c = m^3 over the integers (no modulo wrap). That means decryption is just taking an integer cube root of c.

I used gmpy2.iroot to compute the exact cube root and converted it back to bytes. The True output confirms the cube root is exact, which is exactly what we expect in this vulnerability.
python solve_riddler.pyTrue
apoorvctf{3ncrypt1ng_w1th_RSA_c4n_b3_4_d4ng3r0us_cl1ff_83}So despite the flavor text hinting at multiple layers, this was an elegant single-weakness RSA break: low exponent + no padding + small plaintext.
Solution
# solve_riddler.py
from Crypto.Util.number import long_to_bytes
import gmpy2
c = 5959848254333830910624523071067197529743942832931749422613446095759596470869632698744448445022974243192082623200541274049999046045462632699888118125553180389758240097512080800465269924123706310996597928101365256237876736940573969864179631586328876422479408805381027940806738410297399027560825960052951200511768291312433697743253773594534719688371211151318607767527029263892621127356788516738086153844247429662752321125
m, exact = gmpy2.iroot(c, 3)
print(exact)
print(long_to_bytes(int(m)).decode())python solve_riddler.pyTrue
apoorvctf{3ncrypt1ng_w1th_RSA_c4n_b3_4_d4ng3r0us_cl1ff_83}