Ни в чём не ошибся
Ни в чём не ошибся
Platform: duckerz | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-01-09 | Status: Solved Techniques: prime_factor_leak, trivial_factorization
Summary
Task: RSA encryption with encoder.py and out.txt files. Solution: Discovered that e_output = e + p leaks the prime factor; recovered p by subtracting standard e=65537, then trivially factored n and decrypted the flag.
Ни в чём не ошибся — duckerz CTF
Description
"Я реализовал классический алгоритм шифрования RSA, но у меня ощущение, что в конце я немного ошибся..."
Provided files:
encoder.py— encryption scriptout.txt— encrypted output
Analysis
Source code encoder.py
python read-only • copy allowedfrom Crypto.Util.number import getPrime, bytes_to_long from secret import flag FLAG = bytes_to_long(flag) p = getPrime(1024) q = getPrime(1024) n = p * q e = 2**16 + 1 ct = pow(FLAG, e, n) print(f'n: {n}') print(f'e: {e + p}') # <-- BUG! print(f'ct: {ct}')
Vulnerability
Critical error on line 13: instead of the public exponent e, the value e + p is output.
This is an information leak — knowing the standard value e = 65537, we can recover the prime p:
p = e_output - 65537
Having p, we trivially find q = n / p and completely break RSA.
Vulnerability Indicators
- The
evalue in output is anomalously large (~309 bits instead of the usual 17 bits) - In the code
e = 2**16 + 1, but the output contains a completely different number - The task name hints at an error: "Ни в чём не ошибся" (irony — "Made no mistakes")
Solution
python read-only • copy allowed#!/usr/bin/env python3 """ duckerz CTF - Ни в чём не ошибся RSA with prime factor leak via e + p """ from Crypto.Util.number import long_to_bytes # Data from out.txt n = 18798751967178426381504731083645551181218121488252117174796390511662473223223405610358317360347533449725615650254937132757565862618074878444613133832079916631885992852274828236728617177721086544314236544562012971734513398321560619671317933405328568764783210898904175003033756768051691521868667268800572467570661416685980520830365227303101263220236115846257527363406328867070133263900860663213557708577848719178814761347152620792372847762483281132577137885981623016382936239562664037534610728652936498358752385455426412465419275613674679023680184197311118816809602224346016670679758338521715152362623465755928516580959 e_output = 166612997784562961050427402417959231610727289110449701096278048384004974210290958240913379674222687635734122544375614765473080442343653698415642775890353274310399072042600668814731842221602949909207395384402750419354408938463901094165980590478308424439117927846922386509060315654925327343542424625687693632068 ct = 17273356561619461078492198358303284146147837550026408083524518067748963714274545090109597771904129978632339754019199704530534497145745599609523527982760088915455559056009877592308177940333975618592015789383850494306210308069932391687742058641729313031291497958105019656727012043907079761118369894363732951513833446149610076031667795704343794624910397891428467219520881918134803714315257669793473836503542698570979981732999911129987227518836611490653123917494699687532642255114180923045867064695532251042613174669465051256868327606783121329453124577844785770741291338048163170224764870183574855853190001231864675756254 # Standard RSA exponent e = 65537 # 2^16 + 1 # Recover p from the leak: e_output = e + p p = e_output - e print(f"[+] Recovered p: {p}") # Find q q = n // p assert p * q == n, "Factorization failed!" print(f"[+] Recovered q: {q}") # Compute private key phi = (p - 1) * (q - 1) d = pow(e, -1, phi) # Decrypt m = pow(ct, d, n) flag = long_to_bytes(m) print(f"[+] Flag: {flag.decode()}")
Output
[+] Recovered p: 166612997784562961050427402417959231610727289110449701096278048384004974210290958240913379674222687635734122544375614765473080442343653698415642775890353274310399072042600668814731842221602949909207395384402750419354408938463901094165980590478308424439117927846922386509060315654925327343542424625687693566531
[+] Recovered q: 112821...
[+] Flag: DUCKERZ{REDACTED}
Theory
Why This Is Critical
RSA is secure as long as factorization of n = p * q is computationally hard. Any information leak about p or q can completely compromise the system.
In this case the leak is trivial: p = e_leaked - e_known, which gives instant factorization.
Similar Vulnerabilities
- Leak of
d mod (p-1)ord mod (q-1) - Leak of
p + q(solved via quadratic equation) - Leak of high bits of
p(Coppersmith attack)