[๐Ÿฅˆ Silver 3] 2048๋น„ํŠธ RSA๊ฐ€ 0์Šคํ…์— ๊ฐˆ๋ผ์ง€๋Š” ์ด์œ  โ€” DreamHack crt rsa ํ’€์ด

2026-07-22ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅˆ Silver 3] 2048๋น„ํŠธ RSA๊ฐ€ 0์Šคํ…์— ๊ฐˆ๋ผ์ง€๋Š” ์ด์œ  โ€” DreamHack crt rsa ํ’€์ด

๊ณต๊ฐœ ์ง€์ˆ˜ e ๋„ ๊ฐœ์ธํ‚ค d ๋„ ์ฃผ์ง€ ์•Š๊ณ  dp, dq, qinv ์™€ ์•”ํ˜ธ๋ฌธ๋งŒ ์ฃผ๋Š” RSA-CRT ๋ฌธ์ œ. ๋‘ ์†Œ์ˆ˜๋ฅผ p = nextprime(q + 1) ๋กœ ๋งŒ๋“ค์–ด ์‚ฌ์‹ค์ƒ ์—ฐ์† ์†Œ์ˆ˜๋ผ, 2048๋น„ํŠธ ๋ชจ๋“ˆ๋Ÿฌ์Šค์ธ๋ฐ๋„ Fermat ์ธ์ˆ˜๋ถ„ํ•ด๋กœ 0์Šคํ…์— ๊ฐˆ๋ผ์ง„๋‹ค. dpยทdqยทqinv ๋Š” ๊ทธ ์ž์ฒด๊ฐ€ CRT ๋ณตํ˜ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋ผ, ์†Œ์ธ์ˆ˜๋งŒ ์•Œ๋ฉด eยทd ๋ณต์› ์—†์ด ๊ณง์žฅ ํ‰๋ฌธ์„ ์–ป๋Š”๋‹ค.

๋ฌธ์ œ: DreamHack โ€” crt rsa ๋ถ„๋ฅ˜: Crypto ๋‚œ์ด๋„: ๐Ÿฅˆ Silver 3 FLAG: DH{B45ic_Crt_R54_w1th_A_bit_0f_f3rmat_fact0r}

RSA ๋ฌธ์ œ์ธ๋ฐ ์ฃผ๋Š” ๊ฐ’์ด ํ‰์†Œ์™€ ๋‹ค๋ฅด๋‹ค. ๋ชจ๋“ˆ๋Ÿฌ์Šค N, ๊ทธ๋ฆฌ๊ณ  dp, dq, qinv ์„ธ ๊ฐœ, ๋งˆ์ง€๋ง‰์œผ๋กœ ์•”ํ˜ธ๋ฌธ ํ•˜๋‚˜. ๊ณต๊ฐœ ์ง€์ˆ˜ e ๋„, ๊ฐœ์ธํ‚ค d ๋„, ์†Œ์ˆ˜ pยทq ๋„ ์—†๋‹ค. ์ด๋ฆ„์ด "crt rsa"์ธ ๋งŒํผ ์ด ์„ธ ๊ฐ’์€ RSA๋ฅผ CRT(์ค‘๊ตญ์ธ์˜ ๋‚˜๋จธ์ง€ ์ •๋ฆฌ)๋กœ ๋น ๋ฅด๊ฒŒ ๋ณตํ˜ธํ•  ๋•Œ ์“ฐ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์ด๋‹ค.

ํฌ์ธํŠธ๋Š” ๋‘ ๊ฐ€์ง€๋‹ค. ํ•˜๋‚˜๋Š” ์ด dpยทdqยทqinv ๊ฐ€ ์†Œ์ธ์ˆ˜๋งŒ ์•Œ๋ฉด ๊ทธ๋Œ€๋กœ ๋ณตํ˜ธ์— ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ฐ’์ด๋ผ๋Š” ๊ฒƒ, ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์ถœ์ œ์ž๊ฐ€ ์†Œ์ˆ˜๋ฅผ p = nextprime(q + 1) ๋กœ ๋ฝ‘์•„ ๋‘ ์†Œ์ˆ˜๋ฅผ ๋ถ™์—ฌ ๋†“์€ ๊ฒƒ. 2048๋น„ํŠธ ๋ชจ๋“ˆ๋Ÿฌ์Šค๋ผ ๊ฒ์„ ์ฃผ์ง€๋งŒ, ์ด ๋‘ ๋ฒˆ์งธ ์‚ฌ์‹ค์ด ์ธ์ˆ˜๋ถ„ํ•ด๋ฅผ ํ†ต์งธ๋กœ ์—ด์–ด ์ค€๋‹ค.


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…crt rsa
๋‚œ์ด๋„๐Ÿฅˆ Silver 3
๋ถ„๋ฅ˜Crypto
์ œ๊ณต ํŒŒ์ผprob.py, output.txt (Nยทdpยทdqยทqinvยทencrypted flag)
ํ•ต์‹ฌ ์ทจ์•ฝ์ ์—ฐ์† ์†Œ์ˆ˜ โ†’ Fermat ์ธ์ˆ˜๋ถ„ํ•ด + CRT ํŒŒ๋ผ๋ฏธํ„ฐ ์ง์ ‘ ๋ณตํ˜ธ

prob.py ๋Š” flag ๋ฅผ RSA ๋กœ ์•”ํ˜ธํ™”ํ•˜๊ณ  output.txt ์— ๊ณต๊ฐœ๊ฐ’์„ ๋ฑ‰๋Š”๋‹ค. ์†Œ์ˆ˜ pยทq ์™€ ๊ฐœ์ธํ‚ค d ๋Š” ๋ฌผ๋ก  ์ˆจ๊ฒจ์ ธ ์žˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ•ด์•ผ ํ•  ๊ฑด (1) N ์„ ์ธ์ˆ˜๋ถ„ํ•ดํ•˜๊ณ , (2) ์ฃผ์–ด์ง„ CRT ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณตํ˜ธํ•˜๋Š” ๊ฒƒ.



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” RSA-CRT ๋ณตํ˜ธ๋ž€

์ผ๋ฐ˜ RSA ๋ณตํ˜ธ๋Š” m = c^d mod N ํ•œ ๋ฐฉ์ด์ง€๋งŒ, d ๊ฐ€ 2048๋น„ํŠธ๋ผ ์ด ๊ฑฐ๋“ญ์ œ๊ณฑ์€ ๋А๋ฆฌ๋‹ค. ๊ทธ๋ž˜์„œ ์‹ค์ œ ๊ตฌํ˜„์€ ๋ชจ๋“ˆ๋Ÿฌ์Šค๋ฅผ ์†Œ์ˆ˜ ๋‹จ์œ„๋กœ ์ชผ๊ฐœ๋Š” CRT ์ตœ์ ํ™”๋ฅผ ์“ด๋‹ค. ๋ฏธ๋ฆฌ ๋‹ค์Œ ์„ธ ๊ฐ’์„ ์ค€๋น„ํ•ด ๋‘”๋‹ค.

  • dp = d mod (p - 1) โ€” p ์ชฝ ์ง€์ˆ˜
  • dq = d mod (q - 1) โ€” q ์ชฝ ์ง€์ˆ˜
  • qinv = qโปยน mod p โ€” ๋‘ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์น  ๋•Œ ์“ฐ๋Š” ๊ณ„์ˆ˜

๋ณตํ˜ธ๋Š” ๊ฐ ์†Œ์ˆ˜์—์„œ ๋”ฐ๋กœ ๊ฑฐ๋“ญ์ œ๊ณฑํ•œ ๋’ค(๋ชจ๋“ˆ๋Ÿฌ๊ฐ€ ์ ˆ๋ฐ˜ ํฌ๊ธฐ๋ผ ํ›จ์”ฌ ๋น ๋ฅด๋‹ค) Garner ๊ณต์‹์œผ๋กœ ํ•ฉ์นœ๋‹ค.

RSA-CRT ๋ณตํ˜ธ ํ๋ฆ„ โ€” c ๋ฅผ p, q ๊ฐ๊ฐ์—์„œ ๊ฑฐ๋“ญ์ œ๊ณฑํ•œ ๋’ค qinv ๋กœ ํ•ฉ์ณ ํ‰๋ฌธ m ์„ ์–ป๋Š”๋‹ค. e ๋‚˜ d ๋Š” ํ•„์š” ์—†๋‹ค
RSA-CRT ๋ณตํ˜ธ ํ๋ฆ„ โ€” c ๋ฅผ p, q ๊ฐ๊ฐ์—์„œ ๊ฑฐ๋“ญ์ œ๊ณฑํ•œ ๋’ค qinv ๋กœ ํ•ฉ์ณ ํ‰๋ฌธ m ์„ ์–ป๋Š”๋‹ค. e ๋‚˜ d ๋Š” ํ•„์š” ์—†๋‹ค

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์‚ฌ์‹ค ํ•˜๋‚˜. ์ด ๋ณตํ˜ธ ๊ณผ์ •์—๋Š” ๊ณต๊ฐœ ์ง€์ˆ˜ e ๋„, ์›๋ž˜ ๊ฐœ์ธํ‚ค d ๋„ ๋“ฑ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•„์š”ํ•œ ๊ฑด ์†Œ์ˆ˜ pยทq ์™€ ์ด๋ฏธ ์ฃผ์–ด์ง„ dpยทdqยทqinv ๋ฟ์ด๋‹ค. ์ฆ‰ ์ด ๋ฌธ์ œ๋Š” "๋ณตํ˜ธ์— ํ•„์š”ํ•œ ์žฌ๋ฃŒ๋ฅผ ์ด๋ฏธ ๋‹ค ์คฌ๋Š”๋ฐ, ๋”ฑ ํ•˜๋‚˜ ์†Œ์ธ์ˆ˜๋งŒ ์•ˆ ์ค€" ์ƒํƒœ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋‚จ์€ ์ผ์€ N ์„ ์ธ์ˆ˜๋ถ„ํ•ดํ•˜๋Š” ๊ฒƒ๋ฟ์ด๋‹ค.


๐Ÿ”ฌ ์ฝ”๋“œ ์ •์ฐฐ

prob.py ๋ถ€ํ„ฐ ๋ณธ๋‹ค.

์ด ๊ธ€์˜ ๋ช…๋ น์€ ๋ชจ๋‘ ๋ฌธ์ œ ํด๋” ์ตœ์ƒ์œ„(extracted/ ์˜ ๋ถ€๋ชจ) ์—์„œ ์‹คํ–‰ํ•œ๋‹ค.

cat extracted/prob.py

prob.py ์†Œ์Šค โ€” getPrime ๋กœ q ๋ฅผ ๋ฝ‘๊ณ  p = nextprime(q + 1) ๋กœ ๋‘ ๋ฒˆ์งธ ์†Œ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค
prob.py ์†Œ์Šค โ€” getPrime ๋กœ q ๋ฅผ ๋ฝ‘๊ณ  p = nextprime(q + 1) ๋กœ ๋‘ ๋ฒˆ์งธ ์†Œ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค

ํ•ต์‹ฌ์€ ์†Œ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ์„ธ ์ค„์ด๋‹ค.

q = getPrime(1024)
p = nextprime(q + 1)     # โ† q ๋ฐ”๋กœ ๋‹ค์Œ ์†Œ์ˆ˜. p ์™€ q ๊ฐ€ ๋ถ™์–ด ์žˆ๋‹ค
N = p * q

getPrime(1024) ๋กœ q ๋ฅผ ๋ฝ‘์€ ๋’ค, p ๋ฅผ nextprime(q + 1) โ€” ์ฆ‰ q ๋ฐ”๋กœ ๋‹ค์Œ ์†Œ์ˆ˜ โ€” ๋กœ ์žก๋Š”๋‹ค. 1024๋น„ํŠธ ๊ทผ์ฒ˜์—์„œ ์—ฐ์†ํ•œ ์†Œ์ˆ˜ ์‚ฌ์ด ๊ฐ„๊ฒฉ์€ ํ‰๊ท  ์ˆ˜๋ฐฑ ์ •๋„๋ผ, p ์™€ q ๋Š” ์‚ฌ์‹ค์ƒ ๋”ฑ ๋ถ™์–ด ์žˆ๋‹ค. ์ด๊ฒŒ ์ด ๋ฌธ์ œ์˜ ๊ธ‰์†Œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ถœ๋ ฅ๋ถ€๋Š” N, dp, dq, qinv, encrypted flag ๋งŒ ์ฐ๋Š”๋‹ค. e ์™€ d ๋Š” ํ™”๋ฉด์— ์—†๋‹ค. output.txt ๊ฐ€ ์‹ค์ œ๋กœ ๋ฌด์—‡์„ ์ฃผ๋Š”์ง€ ํฌ๊ธฐ๋ถ€ํ„ฐ ํ™•์ธํ•ด ๋ดค๋‹ค.

# inspect_params.py โ€” output.txt ๊ฐ€ ์ฃผ๋Š” ๊ฐ’์˜ ์ •์ฒด ํ™•์ธ
import re
raw = open("extracted/output.txt").read()
for k in ("N", "dp", "dq", "qinv"):
    v = int(re.search(rf"{k}\s*=\s*(\d+)", raw).group(1))
    print(f"{k:>4} : {v.bit_length():>4} bits")
c = int(re.search(r"encrypted flag\s*=\s*(\d+)", raw).group(1))
print(f"{'c':>4} : {c.bit_length():>4} bits  (encrypted flag)")

inspect_params.py ์‹คํ–‰ โ€” N 2048๋น„ํŠธ, dp/dq/qinv ๊ฐ 1024๋น„ํŠธ๊ธ‰, e ์™€ d ๋Š” ์—†์Œ
inspect_params.py ์‹คํ–‰ โ€” N 2048๋น„ํŠธ, dp/dq/qinv ๊ฐ 1024๋น„ํŠธ๊ธ‰, e ์™€ d ๋Š” ์—†์Œ

N ์€ 2048๋น„ํŠธ, dpยทdqยทqinv ๋Š” ์†Œ์ˆ˜ ํฌ๊ธฐ(1024๋น„ํŠธ๊ธ‰). ๊ณต๊ฐœ ์ง€์ˆ˜๋„ ๊ฐœ์ธํ‚ค๋„ ์—†๋‹ค. ๋ฐฐ๊ฒฝ์—์„œ ์ •๋ฆฌํ•œ ๋Œ€๋กœ, ์ฃผ์–ด์ง„ ์„ธ ๊ฐ’์€ CRT ๋ณตํ˜ธ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ทธ ์ž์ฒด๋‹ค.


๐Ÿ› ์‚ฝ์งˆ

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” ๊ทธ๋ƒฅ ์ธ์ˆ˜๋ถ„ํ•ด๋ถ€ํ„ฐ ํ•˜๋ ค๋‹ค 2048๋น„ํŠธ ๋ฒฝ์— ๋ง‰ํž˜

CRT ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ณตํ˜ธ์— ์“ฐ์ธ๋‹ค๋Š” ๊ฑด ๊ธˆ๋ฐฉ ๋ณด์˜€์ง€๋งŒ, ๊ทธ๋Ÿฌ๋ ค๋ฉด pยทq ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ๊ทธ๋ž˜์„œ "์ผ๋‹จ N ์„ ์ธ์ˆ˜๋ถ„ํ•ดํ•˜์ž"๋กœ ๋‹ฌ๋ ค๋“ค์—ˆ๋‹ค. ๋ฌธ์ œ๋Š” N ์ด 2048๋น„ํŠธ ๋ฐ˜์†Œ์ˆ˜(semiprime)๋ผ๋Š” ๊ฒƒ. ์ž‘์€ ์†Œ์ธ์ˆ˜๋ผ๋„ ์žˆ๋‚˜ ํ›‘์–ด๋ดค๋‹ค.

# naive_factor.py โ€” ์ž‘์€ ์†Œ์ธ์ˆ˜ ์Šค์บ” ํ›„ ์ผ๋ฐ˜ ์ธ์ˆ˜๋ถ„ํ•ด๋กœ ๋„˜์–ด๊ฐ€๋ ค๋˜ ์‹œ๋„
import re, time
from sympy import primerange
N = int(re.search(r"N\s*=\s*(\d+)", open("extracted/output.txt").read()).group(1))
print(f"N : {N.bit_length()} bits")
t = time.time()
small = None
for pr in primerange(2, 300000):
    if N % pr == 0:
        small = pr
        break
print(f"์ž‘์€ ์†Œ์ธ์ˆ˜ (< 300000) : {small}")
print(f"์Šค์บ” ์‹œ๊ฐ„ : {time.time() - t:.2f}s")

naive_factor.py ์‹คํ–‰ โ€” ์ž‘์€ ์†Œ์ธ์ˆ˜ ์—†์Œ. ์ผ๋ฐ˜ ์ธ์ˆ˜๋ถ„ํ•ด๋กœ๋Š” 2048๋น„ํŠธ ๋ฐ˜์†Œ์ˆ˜๊ฐ€ ์•ˆ ๊ฐˆ๋ผ์ง„๋‹ค
naive_factor.py ์‹คํ–‰ โ€” ์ž‘์€ ์†Œ์ธ์ˆ˜ ์—†์Œ. ์ผ๋ฐ˜ ์ธ์ˆ˜๋ถ„ํ•ด๋กœ๋Š” 2048๋น„ํŠธ ๋ฐ˜์†Œ์ˆ˜๊ฐ€ ์•ˆ ๊ฐˆ๋ผ์ง„๋‹ค

์ž‘์€ ์†Œ์ธ์ˆ˜๋Š” ์—†๋‹ค. trial division ๋„, Pollard rhoยทp-1 ๋„ 2048๋น„ํŠธ ๋ฐ˜์†Œ์ˆ˜ ์•ž์—์„œ๋Š” ์‚ฌ์‹ค์ƒ ๋ฉˆ์ถ˜๋‹ค. ์—ฌ๊ธฐ์„œ "e ๊ฐ€ ์—†์œผ๋‹ˆ dpยทdq ๋กœ d ๋ฅผ ๋ณต์›ํ•œ ๋‹ค์Œ ํ‘œ์ค€ ๋ณตํ˜ธ๋ฅผ ํ•˜์ž"๋กœ ๋ฐฉํ–ฅ์„ ํ‹€์–ด ๋ดค์ง€๋งŒ, d ๋ฅผ ๋ณต์›ํ•˜๋ ค ํ•ด๋„ ๊ฒฐ๊ตญ p-1, q-1 ์„ ์•Œ์•„์•ผ ํ•˜๋‹ˆ ๋‹ค์‹œ ์ธ์ˆ˜๋ถ„ํ•ด๋กœ ๋˜๋Œ์•„์˜จ๋‹ค. ๋ฑ…๋ฑ… ๋Œ๋‹ค prob.py ์˜ p = nextprime(q + 1) ํ•œ ์ค„๋กœ ๋Œ์•„์™”๋‹ค โ€” ์†Œ์ˆ˜๊ฐ€ ๋ถ™์–ด ์žˆ์œผ๋ฉด ๊ตณ์ด ์ผ๋ฐ˜ ์ธ์ˆ˜๋ถ„ํ•ด๊ฐ€ ํ•„์š” ์—†๋‹ค.



๐Ÿ’ฃ ํ•ต์‹ฌ โ€” ์—ฐ์† ์†Œ์ˆ˜๋ผ Fermat์ด 0์Šคํ…์— ๋šซ๋ฆฐ๋‹ค

p ์™€ q ๊ฐ€ ๋ถ™์–ด ์žˆ๋‹ค๋Š” ๊ฑด Fermat ์ธ์ˆ˜๋ถ„ํ•ด๊ฐ€ ๋”ฑ ๋งž๋Š” ์ƒํ™ฉ์ด๋ผ๋Š” ๋œป์ด๋‹ค. Fermat ์ธ์ˆ˜๋ถ„ํ•ด๋Š” ํ™€์ˆ˜ N ์„ ๋‘ ์ œ๊ณฑ์ˆ˜์˜ ์ฐจ๋กœ ๋ณธ๋‹ค.

N = aยฒ โˆ’ bยฒ = (a + b)(a โˆ’ b)

์—ฌ๊ธฐ์„œ a = (p + q) / 2, b = (p โˆ’ q) / 2 ๋‹ค. ๋‘ ์†Œ์ˆ˜๊ฐ€ ๊ฐ€๊นŒ์šฐ๋ฉด b ๊ฐ€ ์•„์ฃผ ์ž‘๊ณ , a ๋Š” โˆšN ๋ฐ”๋กœ ์œ„์— ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ a ๋ฅผ โŒˆโˆšNโŒ‰ ๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ์˜ฌ๋ฆฌ๋ฉฐ aยฒ โˆ’ N ์ด ์™„์ „์ œ๊ณฑ(= bยฒ)์ด ๋˜๋Š” ์ˆœ๊ฐ„์„ ์ฐพ์œผ๋ฉด ๋œ๋‹ค. ์†Œ์ˆ˜๊ฐ€ ๋ถ™์–ด ์žˆ์„์ˆ˜๋ก ๊ทธ ์ˆœ๊ฐ„์ด ๋นจ๋ฆฌ ์˜จ๋‹ค.

Fermat ์ธ์ˆ˜๋ถ„ํ•ด โ€” ๋‘ ์†Œ์ˆ˜๊ฐ€ ๊ฐ€๊นŒ์šฐ๋ฉด a = ceil(sqrt N) ๋ถ€ํ„ฐ ๋ช‡ ์Šคํ… ์•ˆ์— a squared minus N ์ด ์™„์ „์ œ๊ณฑ์ด ๋œ๋‹ค
Fermat ์ธ์ˆ˜๋ถ„ํ•ด โ€” ๋‘ ์†Œ์ˆ˜๊ฐ€ ๊ฐ€๊นŒ์šฐ๋ฉด a = ceil(sqrt N) ๋ถ€ํ„ฐ ๋ช‡ ์Šคํ… ์•ˆ์— a squared minus N ์ด ์™„์ „์ œ๊ณฑ์ด ๋œ๋‹ค

์ด ๋ฌธ์ œ์—์„  ์–ผ๋งˆ๋‚˜ ๊ฐ€๊นŒ์šด์ง€ ์ง์ ‘ ํ™•์ธํ•ด ๋ดค๋‹ค. sympy ๋กœ ๋‚˜์˜จ ๋‘ ์†Œ์ˆ˜๊ฐ€ ์‹ค์ œ ์†Œ์ˆ˜์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  ์ •๋ง ์—ฐ์† ์†Œ์ˆ˜(p == nextprime(q + 1))์ธ์ง€๊นŒ์ง€ ๊ฒ€์ฆํ–ˆ๋‹ค.

# factor_check.py โ€” Fermat ์œผ๋กœ ๊ฐˆ๋ผ ๋ณด๊ณ  ์—ฐ์† ์†Œ์ˆ˜์ธ์ง€ ํ™•์ธ
from math import isqrt
from sympy import isprime, nextprime
import re
 
N = int(re.search(r"N\s*=\s*(\d+)", open("extracted/output.txt").read()).group(1))
a = isqrt(N)
if a * a < N:
    a += 1
steps = 0
while True:
    b2 = a * a - N
    b = isqrt(b2)
    if b * b == b2:
        break
    a += 1
    steps += 1
p, q = a + b, a - b
print(f"Fermat steps      : {steps}")
print(f"p * q == N        : {p * q == N}")
print(f"p, q ๊ฐ€ ์†Œ์ˆ˜์ธ๊ฐ€   : {isprime(p)}, {isprime(q)}")
print(f"p == nextprime(q+1): {p == nextprime(q + 1)}")
print(f"p - q             : {p - q}")

factor_check.py ์‹คํ–‰ โ€” Fermat steps 0, p*q==N True, ๋‘˜ ๋‹ค ์†Œ์ˆ˜, p==nextprime(q+1) True, p-q=672
factor_check.py ์‹คํ–‰ โ€” Fermat steps 0, p*q==N True, ๋‘˜ ๋‹ค ์†Œ์ˆ˜, p==nextprime(q+1) True, p-q=672

Fermat steps = 0. ์ฆ‰ a = โŒˆโˆšNโŒ‰ ๊ทธ ๊ฐ’์—์„œ ์ด๋ฏธ aยฒ โˆ’ N ์ด ์™„์ „์ œ๊ณฑ์ด์—ˆ๋‹ค. ๋‘ ์†Œ์ˆ˜ ์ฐจ์ด๋Š” ๊ฒจ์šฐ 672. 2048๋น„ํŠธ ๋ชจ๋“ˆ๋Ÿฌ์Šค๊ฐ€ ๋‹จ ํ•œ ๋ฒˆ์˜ ์ œ๊ณฑ๊ทผ ๊ณ„์‚ฐ์œผ๋กœ ๊ฐˆ๋ผ์ง„ ๊ฒƒ์ด๋‹ค. p == nextprime(q + 1) ๋„ True ๋ผ, ์šฐ๋ฆฌ๊ฐ€ ๋ณต์›ํ•œ ์†Œ์ˆ˜๊ฐ€ ์ถœ์ œ์ž๊ฐ€ ๋งŒ๋“  ๊ทธ ์†Œ์ˆ˜ ์Œ์ด ๋งž๋‹ค.

์ด์ œ ์†Œ์ธ์ˆ˜๋ฅผ ์–ป์—ˆ์œผ๋‹ˆ ๋ฐฐ๊ฒฝ์˜ CRT ๋ณตํ˜ธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋Œ๋ฆฌ๋ฉด ๋œ๋‹ค.

m1 = c^dp mod p
m2 = c^dq mod q
h  = qinv ยท (m1 โˆ’ m2) mod p     # qinv = qโปยน mod p
m  = m2 + h ยท q

๐ŸŽฏ Full Exploit

output.txt ์—์„œ ๊ฐ’์„ ํŒŒ์‹ฑํ•ด Fermat ์ธ์ˆ˜๋ถ„ํ•ด โ†’ CRT ๋ณตํ˜ธ๊นŒ์ง€ ํ•œ ๋ฒˆ์— ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋‹ค. ๊ฐ’์€ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ์•Š๊ณ  ๋ฌธ์ œ ํŒŒ์ผ์—์„œ ๊ทธ๋Œ€๋กœ ์ฝ๋Š”๋‹ค.

# solve.py
from math import isqrt
from Crypto.Util.number import long_to_bytes
import re, os
 
here = os.path.dirname(os.path.abspath(__file__))
raw = open(os.path.join(here, "extracted", "output.txt")).read()
vals = {}
for key in ("N", "dp", "dq", "qinv"):
    vals[key] = int(re.search(rf"{key}\s*=\s*(\d+)", raw).group(1))
c = int(re.search(r"encrypted flag\s*=\s*(\d+)", raw).group(1))
N, dp, dq, qinv = vals["N"], vals["dp"], vals["dq"], vals["qinv"]
 
# 1) Fermat factorization: N = a^2 - b^2 = (a+b)(a-b)
a = isqrt(N)
if a * a < N:
    a += 1
steps = 0
while True:
    b2 = a * a - N
    b = isqrt(b2)
    if b * b == b2:
        break
    a += 1
    steps += 1
p, q = a + b, a - b
assert p * q == N and p > q
print(f"[+] Fermat steps = {steps}   (p-q = {p - q})")
print(f"[+] p = {p}")
print(f"[+] q = {q}")
 
# 2) RSA-CRT ๋ณตํ˜ธ (e, d ๋ถˆํ•„์š”)
m1 = pow(c, dp, p)
m2 = pow(c, dq, q)
h = (qinv * (m1 - m2)) % p
m = m2 + h * q
 
flag = long_to_bytes(m)
print(f"[+] FLAG = {flag.decode()}")

solve.py ์‹คํ–‰ โ€” Fermat steps 0, p ์™€ q(๋ ์„ธ ์ž๋ฆฌ๋งŒ ๋‹ค๋ฅธ ์—ฐ์† ์†Œ์ˆ˜) ์ถœ๋ ฅ, ๋งˆ์ง€๋ง‰ ์ค„์— FLAG
solve.py ์‹คํ–‰ โ€” Fermat steps 0, p ์™€ q(๋ ์„ธ ์ž๋ฆฌ๋งŒ ๋‹ค๋ฅธ ์—ฐ์† ์†Œ์ˆ˜) ์ถœ๋ ฅ, ๋งˆ์ง€๋ง‰ ์ค„์— FLAG

์ถœ๋ ฅ๋œ p ์™€ q ๋ฅผ ๋ณด๋ฉด ์•ž์ž๋ฆฌ๊ฐ€ ์ „๋ถ€ ๊ฐ™๊ณ  ๋ ์„ธ ์ž๋ฆฌ๋งŒ ๋‹ค๋ฅด๋‹ค(...798109 vs ...797437). ๋ˆˆ์œผ๋กœ ๋ด๋„ ๋‘ ์†Œ์ˆ˜๊ฐ€ ๋ถ™์–ด ์žˆ๋‹ค๋Š” ๊ฒŒ ๋ณด์ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰ ์ค„์— ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋–จ์–ด์ง„๋‹ค.

DH{B45ic_Crt_R54_w1th_A_bit_0f_f3rmat_fact0r}

โœ… ๊ฒ€์ฆ

ํ”Œ๋ž˜๊ทธ ๋ฌธ์ž์—ด ์ž์ฒด๊ฐ€ ํ’€์ด๋ฅผ ๊ทธ๋Œ€๋กœ ์š”์•ฝํ•œ๋‹ค โ€” B45ic_Crt_R54_w1th_A_bit_0f_f3rmat_fact0r, ์ฆ‰ "์•ฝ๊ฐ„์˜ Fermat ์ธ์ˆ˜๋ถ„ํ•ด๋ฅผ ๊ณ๋“ค์ธ ๊ธฐ๋ณธ CRT-RSA". ์šฐ๋ฆฌ๊ฐ€ ์“ด ๋‘ ๋„๊ตฌ(์—ฐ์† ์†Œ์ˆ˜ Fermat ์ธ์ˆ˜๋ถ„ํ•ด + CRT ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณตํ˜ธ)๊ฐ€ ์˜๋„ํ•œ ์ •๋‹ต ๊ฒฝ๋กœ์˜€๋‹ค๋Š” ํ™•์ธ์ด๋‹ค. ์ด ๋ฌธ์ œ๋Š” needs_vm ์ด ์—†๋Š” ์˜คํ”„๋ผ์ธ ๋ฌธ์ œ๋ผ, ์„œ๋ฒ„ ์—†์ด ๋กœ์ปฌ์—์„œ ๊ฐ’์„ ๋ณต์›ํ•ด ๊ทธ๋Œ€๋กœ ์ œ์ถœํ–ˆ๋‹ค.



๐Ÿ“ ๊ฒฐ๋ก  โ€” ๋ฌด์—‡์ด ๋ฌธ์ œ์˜€๋‚˜

RSA์˜ ์•ˆ์ „์„ฑ์€ "ํฐ ๋ชจ๋“ˆ๋Ÿฌ์Šค๋Š” ์ธ์ˆ˜๋ถ„ํ•ด๊ฐ€ ์–ด๋ ต๋‹ค"์— ๊ธฐ๋Œ„๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๊ฑด ๋‘ ์†Œ์ˆ˜๊ฐ€ ๋ฌด์ž‘์œ„๋กœ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ์„ ๋•Œ ์–˜๊ธฐ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ๋‘ ๊ณณ์—์„œ ๊ทธ ์ „์ œ๋ฅผ ๋ฌด๋„ˆ๋œจ๋ ธ๋‹ค.

  • ์—ฐ์† ์†Œ์ˆ˜: p = nextprime(q + 1) ์€ ํŽธ์˜์ƒ ๊ทธ๋Ÿด๋“ฏํ•ด ๋ณด์ด์ง€๋งŒ, ๋‘ ์†Œ์ˆ˜๋ฅผ ๋ถ™์—ฌ ๋†“์œผ๋ฉด โˆšN ๊ทผ์ฒ˜์— ์†Œ์ธ์ˆ˜๊ฐ€ ๋ชฐ๋ ค Fermat ์ธ์ˆ˜๋ถ„ํ•ด๊ฐ€ ์ฆ‰์‹œ ํ†ตํ•œ๋‹ค. ๋น„ํŠธ ์ˆ˜(2048)๋Š” ๋ฐฉ์–ด๊ฐ€ ๋˜์ง€ ๋ชปํ•œ๋‹ค. ์†Œ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๋…๋ฆฝ์ ์œผ๋กœ, ์ถฉ๋ถ„ํžˆ ๋–จ์–ด์ง€๊ฒŒ ๋ฝ‘์•„์•ผ ํ•œ๋‹ค(๊ทธ๋ž˜์„œ ํ‘œ์ค€ ํ‚ค ์ƒ์„ฑ์€ |p โˆ’ q| ํ•˜ํ•œ์„ ๋‘”๋‹ค).
  • CRT ํŒŒ๋ผ๋ฏธํ„ฐ ๋…ธ์ถœ: dpยทdqยทqinv ๋Š” ๊ฐœ์ธํ‚ค์˜ ์ผ๋ถ€๋‹ค. ์ด ๊ฐ’๋“ค์€ ์†Œ์ธ์ˆ˜๋งŒ ํ™•๋ณด๋˜๋ฉด eยทd ์—†์ด๋„ ๊ณง์žฅ ๋ณตํ˜ธ๋กœ ์ด์–ด์ง„๋‹ค. CRT ์ตœ์ ํ™” ๊ฐ’์€ ๊ฐœ์ธํ‚ค์™€ ๋™๊ธ‰์œผ๋กœ ์ทจ๊ธ‰ํ•ด ์ ˆ๋Œ€ ๊ณต๊ฐœํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

๋‘ ์‹ค์ˆ˜ ์ค‘ ํ•˜๋‚˜๋งŒ ์žˆ์–ด๋„ ์œ„ํ—˜ํ•œ๋ฐ, ์ด ๋ฌธ์ œ๋Š” ๋‘˜์„ ๊ฒน์ณ ๋†จ๋‹ค. ๋ฐฉ์–ด์ž์˜ ๊ตํ›ˆ์€ ๋‹จ์ˆœํ•˜๋‹ค โ€” ์†Œ์ˆ˜๋Š” ๋…๋ฆฝยท์ถฉ๋ถ„ํ•œ ๊ฐ„๊ฒฉ์œผ๋กœ, CRT ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ฐœ์ธํ‚ค์ฒ˜๋Ÿผ.

์ด ๊ธ€์ด ๋„์›€์ด ๋๋‚˜์š”?

Comments

๋Œ“๊ธ€

0๊ฐœ

๋Œ“๊ธ€์„ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ด์š”. (๋„ค์ด๋ฒ„ ยท ๊ตฌ๊ธ€ ๊ณ„์ •)

๋Œ“๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅˆ Silver 4] e ๊ฐ€ (p-1) ์„ ๋‚˜๋ˆ„๋Š” RSA โ€” AMM ์œผ๋กœ e์ฐจ๊ทผ ๊ตฌํ•˜๊ธฐ โ€” DreamHack special_rsa_parameter ํ’€์ด
blog

[๐Ÿฅˆ Silver 4] e ๊ฐ€ (p-1) ์„ ๋‚˜๋ˆ„๋Š” RSA โ€” AMM ์œผ๋กœ e์ฐจ๊ทผ ๊ตฌํ•˜๊ธฐ โ€” DreamHack special_rsa_parameter ํ’€์ด

๊ณต๊ฐœ์ง€์ˆ˜ e=257 ์ด (p-1) ์„ ๋”ฑ ํ•œ ๋ฒˆ ๋‚˜๋ˆˆ๋‹ค. gcd(e, ฯ†(N)) ์ด 1 ์ด ์•„๋‹ˆ๋ผ d=eโปยน mod ฯ† ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„ ํ‰๋ฒ”ํ•œ RSA ๋ณตํ˜ธ๊ฐ€ ๋ง‰ํžŒ๋‹ค. pยทq ๊ฐ€ ์ด๋ฏธ ์ฃผ์–ด์กŒ์œผ๋‹ˆ CRT ๋กœ mod p / mod q ๋กœ ์ชผ๊ฐ  ๋’ค, e์ฐจ๊ทผ์ด ์œ ์ผํ•œ mod q ๋Š” ๊ทธ๋Œ€๋กœ ํ’€๊ณ , e์ฐจ๊ทผ์ด 257๊ฐœ์ธ mod p ๋Š” AMM(Adleman-Manders-Miller) ์œผ๋กœ ์ „๋ถ€ ๊ตฌํ•ด CRT ๋กœ ๋‹ค์‹œ ํ•ฉ์นœ๋‹ค. 257๊ฐœ ํ›„๋ณด ์ค‘ BISC ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ‰๋ฌธ์ด flag.
#dreamhack#ctf#crypto+6
2026-07-23#dreamhack +5
[๐Ÿฅ‰ Bronze 3] 8827๋น„ํŠธ RSA๊ฐ€ 0.004์ดˆ์— ๊ฐˆ๋ผ์ง€๋Š” ์ด์œ  โ€” DreamHack many primes ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 3] 8827๋น„ํŠธ RSA๊ฐ€ 0.004์ดˆ์— ๊ฐˆ๋ผ์ง€๋Š” ์ด์œ  โ€” DreamHack many primes ํ’€์ด

๋ชจ๋“ˆ๋Ÿฌ์Šค N ์ด 2658์ž๋ฆฌ(8827๋น„ํŠธ)๋ผ ๊ฒ์„ ์ฃผ์ง€๋งŒ, ์‹ค์€ 11๋ถ€ํ„ฐ 8293 ์‚ฌ์ด์˜ ์ž์ž˜ํ•œ ์†Œ์ˆ˜ 777๊ฐœ๋ฅผ ๊ณฑํ•ด ๋งŒ๋“  ๊ฐ’์ด๋‹ค. ์†Œ์ธ์ˆ˜๊ฐ€ ์ „๋ถ€ 8296 ๋ฏธ๋งŒ์ด๋ผ 8296๊นŒ์ง€ ์‹œํ–‰๋‚˜๋ˆ—์…ˆ๋งŒ ๋Œ๋ ค๋„ ํ†ต์งธ๋กœ ๊ฐˆ๋ผ์ง„๋‹ค. ์„œ๋กœ ๋‹ค๋ฅธ ์†Œ์ˆ˜์˜ ๊ณฑ์ด๋ผ ฯ†(N)=โˆ(pแตขโˆ’1) ๋กœ ๋ฐ”๋กœ ๊ตฌํ•ด์ง€๊ณ , d=eโปยน mod ฯ† ๋กœ ๊ฐœ์ธํ‚ค๋ฅผ ๋ณต์›ํ•ด ๋ณตํ˜ธํ•œ๋‹ค.
#dreamhack#ctf#crypto+5
2026-07-23#dreamhack +4
[๐Ÿฅˆ Silver 3] ๊ฐ’์„ ๋ฐ”๊พธ๋ฉด ๊ฒ€์‚ฌ๋ฅผ ํ”ผํ•ด๊ฐ„๋‹ค โ€” DreamHack Textbook-RSA ํ’€์ด
blog

[๐Ÿฅˆ Silver 3] ๊ฐ’์„ ๋ฐ”๊พธ๋ฉด ๊ฒ€์‚ฌ๋ฅผ ํ”ผํ•ด๊ฐ„๋‹ค โ€” DreamHack Textbook-RSA ํ’€์ด

์•”ํ˜ธํ™”๋œ ํ”Œ๋ž˜๊ทธ๋ฅผ ๊ทธ๋Œ€๋กœ ์„œ๋ฒ„์— ๋˜๋Œ๋ ค ๋ณตํ˜ธํ™”๋ฅผ ์š”์ฒญํ•˜๋Š” ๋ป”ํ•œ ์‹œ๋„๋Š” "Do not cheat !"๋กœ ๋ฐ”๋กœ ๋ง‰ํžŒ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ๊ฒ€์‚ฌ๋Š” ๋”ฑ ์ˆซ์ž ํ•˜๋‚˜๋งŒ ๋น„๊ตํ•  ๋ฟ์ด๋‹ค. RSA๋Š” ๊ณฑ์…ˆ์— ๋Œ€ํ•ด ์ค€๋™ํ˜•(homomorphic)์ด๋ผ๋Š” ์„ฑ์งˆ์ด ์žˆ์–ด์„œ, ์•”ํ˜ธ๋ฌธ์— ์•Œ๋ ค์ง„ ๊ฐ’์„ ๊ณฑํ•ด ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ˆซ์ž๋กœ ๋‘”๊ฐ‘์‹œํ‚ค๋ฉด ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•˜๋ฉด์„œ๋„ ์›๋ž˜ ๊ฐ’์„ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๋ฅผ ๊ทธ๋Œ€๋กœ ์–ป์–ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
#dreamhack#ctf#crypto+3
2026-07-20#dreamhack +4