CyberYard CTF – M4ths
Some gaps are small some are huge
CyberYard CTF – M4ths
M4ths Crypto Write-up
Category: Crypto
Prompt:Some gaps are small some are huge
Artifact: ⬇️ challenge.py - ⬇️ out.txt.
Flag format:FlagY{...}
intro
The RSA key was generated with: p = getPrime(1024) q = nextprime(p + getrandbits(512)) # q is “close” to p n = p*q e = 0x10001 ct = pow(m, e, n)
Because q − p < 2^512 ≈ n^(1/4), the modulus has close primes. This makes it vulnerable to a (Fermat) Coppersmith-style factorization. After factoring n, compute d, decrypt ct, and the plaintext contains the flag.
Challenge Description
If p and q are close:
- a = (p + q)/2 is near sqrt(n)
- a^2 − n = ((q − p)/2)^2 is a small square
Brute-force Fermat is borderline when the gap is ~n^(1/4), but a small-root (Coppersmith) approach around A = ceil(sqrt(n)) finds the tiny x = a − A, then we reconstruct p, q.
Steps
- Parse given n and ct.
- Let A = ceil(sqrt(n)).
- Work mod n with f(x) = (A + x)^2 − n. For the correct small x0, f(x0) ≡ 0 (mod n).
- Use a lattice/small-root routine to recover x0 with bound ~n^(1/4).
- Set a = A + x0, b^2 = a^2 − n; then p = a − b, q = a + b.
- Compute φ(n) = (p−1)(q−1), d = e^(-1) mod φ(n).
- Decrypt m = ct^d mod n → extract flag.
Solver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from math import isqrt
n = int("18552214896423000565964954068282406674971502238215699518204084178601023077567456930188156395781444480169555146234541486771975129395421945283826496993577134629895154884651234859474819728020830892121433460525545135205587268408425559426550762417843991744925510144029739862807981944979919916268589586865132555346023498442806710752734146923223300583104281816519175209412466936071517687843790168151470769561076697356665770717280611580181034640693557159172981118154808220340247196391098947022592690509310486372915020481920496588908523098998781484123506337821031358268724386295531256963177210773145861403142734317334978452179")
ct = int("18459930372229983090709259793073039760162724641648071179302308034168492705233927026484739957819997919805563724299301163802794657833298411691334435225417004319062183234585304346867308523296832044235997514383209842727896931538736364988657063157149571233951460519202401843295478583491530387169689999661106298890646815511068619749403350972695081661635128386944078959555401596832292631727796273344063149749279149812751994363266882130576897125326601597821920342681466341364542099588989233325033407384904272804565460157152863222376670867517777186398003282984784986169902365780957994725978466219239319955097268446160554266498")
e = 0x10001
s = isqrt(4*n)
S = s + 1
D2 = S*S - 4*n
D = isqrt(D2)
assert D*D == D2
p = (S - D) // 2
q = (S + D) // 2
assert p*q == n
phi = (p-1)*(q-1)
d = pow(e, -1, phi)
m = pow(ct, d, n)
from Crypto.Util.number import long_to_bytes
mb = long_to_bytes(m)
start = mb.find(b"FlagY{")
end = mb.find(b"}", start)
flag = mb[start:end+1].decode()
print(flag)
Output:
1
FlagY{l0ng_fl@g_But_e4sy_Ch4ll3ng3_C0pp3rsm!th_w4s_4_M4ths_G33k}
هذا المنشور تحت ترخيص CC BY 4.0 بواسطة المؤلف.