Skip to content
Back to skills

Rsa Close Primes

ASecurity

RSA'da p ve q birbirine çok yakınsa Fermat factorization ile N çarpanlarına ayrılır

  • 4 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 8, 2026
securitypythongogit

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add MustafaKemal0146/fetih --skill rsa-close-primes --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rsa Close Primes?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Rsa Close Primes
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mustafakemal0146-rsa-close-primes/badge)](https://www.skillsdirectory.com/skills/mustafakemal0146-rsa-close-primes)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: rsa-close-primes
description: RSA'da p ve q birbirine çok yakınsa Fermat factorization ile N çarpanlarına ayrılır
tags: [ctf, crypto, rsa, fermat, close-primes, factorization, yakın-asal]
triggers:
  - "yakın asal sayılar"
  - "p ve q yakın"
  - "fermat factorization"
  - "N'in karekökü yakınında"
  - "p-q küçük"
  - "factordb bulamıyor"
  - "üç asal çarpım N=p*q*r"
difficulty: medium
category: crypto
solved_challenges:
  - "LACTF 2024 - very-hot (N=p*q*r, p,q,r ardışık aralıkta)"
  - "CryptoCTF 2023 - closeprimes"
adapted_for: fetih
---

# RSA Close Primes — Fermat Factorization

## Ne Zaman Kullan

Aşağıdaki belirtilerden biri varsa bu tekniği dene:

- N sayısı FactorDB, yatools, SageMath `factor()` ile çözülemiyor
- Chall kaynağı mevcut ve asal sayılar şöyle üretilmiş:
  ```python
  p = getPrime(512)
  q = getPrime(512)   # p'den bağımsız, ama her ikisi de getStrongPrime ile üretilmişse yakın olmayabilir
  ```
- Challenge açıklamasında "very close primes", "nearby primes", "p ≈ q" gibi ipuçları var
- `|p - q|` değeri 2^(bitlen/2) civarında veya daha küçük
- N = p * q * r şeklinde üç çarpan var ve aralarındaki fark küçük (LACTF very-hot vakası)
- msieve / yafu çok yavaş ya da sonuç vermiyor

**Altın kural:** `sqrt(N)` 'i integer alıp kare mı diye bak. Değilse Fermat iteration başlat.

---

## Fermat Factorization Mantığı

Her tek sayı N, iki kare farkı olarak yazılabilir:

```
N = a² - b²  =  (a+b)(a-b)
```

Dolayısıyla:
```
p = a + b
q = a - b
```

p ve q birbirine yakınsa `a ≈ sqrt(N)` ve b çok küçük olur — iterasyon hızla çalışır.

**Yakınsama koşulu:** `|p - q| < N^(1/4)` olduğunda pratik süreler içinde çözülür.
`|p - q| < N^(1/3)` için makul sürede sonuç alınır.
`|p - q| > N^(1/2)` ise artık Fermat verimsizleşir, Pollard rho veya ECM tercih edilmeli.

---

## Çözüm Adımları

1. `a = ceil(sqrt(N))` hesapla (integer square root — gmpy2.isqrt kullan)
2. `b² = a² - N` hesapla
3. `b²` tam kare mi diye bak
4. Değilse `a += 1`, tekrar et
5. Tam kare bulunduğunda: `p = a + b`, `q = a - b`
6. `assert p * q == N` ile doğrula
7. `phi = (p-1)*(q-1)`, `d = pow(e, -1, phi)`, `m = pow(c, d, n)`

---

## Exploit Kodu

### Standart 2-Asal Fermat (N = p * q)

```python
import gmpy2
from Crypto.Util.number import long_to_bytes

def fermat_factor(n):
    """
    Fermat factorization: N = a^2 - b^2 = (a+b)(a-b)
    p ve q birbirine yakınsa hızla çalışır.
    """
    a = gmpy2.isqrt(n)
    if a * a < n:
        a += 1  # ceil(sqrt(n))

    b2 = a * a - n

    iterations = 0
    while True:
        b, is_perfect = gmpy2.isqrt_rem(b2)
        if is_perfect == 0:   # b2 tam kare
            break
        a += 1
        b2 = a * a - n
        iterations += 1
        if iterations % 100_000 == 0:
            print(f"[*] iteration {iterations}, a = {a}")
        if iterations > 5_000_000:
            print("[-] Fermat başarısız — p ve q yeterince yakın değil")
            return None, None

    p = int(a + b)
    q = int(a - b)
    assert p * q == n, "Çarpanlara ayırma hatalı!"
    print(f"[+] p = {p}")
    print(f"[+] q = {q}")
    return p, q


# --- Challenge değişkenlerini buraya koy ---
n = 0xDEADBEEF  # örnek — gerçek N buraya
e = 65537
c = 0xCAFEBABE  # şifreli metin

p, q = fermat_factor(n)

if p and q:
    phi = (p - 1) * (q - 1)
    d = pow(e, -1, phi)
    m = pow(c, d, n)
    flag = long_to_bytes(m)
    print(f"[+] Flag: {flag.decode(errors='replace')}")
```

---

### 3-Asal Fermat: N = p * q * r (LACTF 2024 very-hot)

LACTF 2024 "very-hot" challenge'ında `p`, `q`, `r` ardışık küçük aralıkta seçilmişti.
Kaynak koda göre:

```python
# Orijinal challenge üretimi (LACTF very-hot)
from Crypto.Util.number import getPrime
import random

bits = 256
p = getPrime(bits)
q = p + random.randint(1, 2**24)   # p'ye çok yakın
r = q + random.randint(1, 2**24)   # q'ya çok yakın
n = p * q * r
```

Saldırı stratejisi:
- `cbrt(N)` ≈ p ≈ q ≈ r olduğu için küp kökten başla
- Her potansiyel `p` için `N % p == 0` kontrol et (kaba kuvvet, ama aralık küçük)

```python
import gmpy2
from Crypto.Util.number import long_to_bytes

def factor_three_close_primes(n, e, c, search_range=2**25):
    """
    N = p * q * r, p < q < r ve r - p < search_range varsayımı.
    Küp kökten itibaren arama yapar.
    """
    cbrt_n, _ = gmpy2.iroot(n, 3)

    print(f"[*] Küp kök aramasi basliyor: cbrt(N) ≈ {cbrt_n}")
    print(f"[*] Arama araligi: {search_range} adim")

    # cbrt(N) civarina git — p bu civarda olmali
    start = int(cbrt_n) - search_range // 2

    for candidate in range(start, start + search_range):
        if n % candidate == 0:
            p = candidate
            remaining = n // p
            # remaining = q * r — bunu da iki asal olarak coz
            q, r = fermat_two(remaining)
            if q and r:
                print(f"[+] p = {p}")
                print(f"[+] q = {q}")
                print(f"[+] r = {r}")
                assert p * q * r == n
                phi = (p - 1) * (q - 1) * (r - 1)
                d = pow(e, -1, phi)
                m = pow(c, d, n)
                flag = long_to_bytes(m)
                print(f"[+] Flag: {flag.decode(errors='replace')}")
                return flag
            # Eger q*r asal degilse, dogrudan bolelim
            # remaining'i kontrol et
            q2 = gmpy2.isqrt(remaining)
            for offset in range(-search_range, search_range):
                cand_q = int(q2) + offset
                if cand_q > 1 and remaining % cand_q == 0:
                    r2 = remaining // cand_q
                    if gmpy2.is_prime(cand_q) and gmpy2.is_prime(r2):
                        print(f"[+] p={p}, q={cand_q}, r={r2}")
                        phi = (p-1)*(cand_q-1)*(r2-1)
                        d = pow(e, -1, phi)
                        m = pow(c, d, n)
                        return long_to_bytes(m)

    print("[-] Bulunamadi — arama araligini genislet")
    return None


def fermat_two(n, max_iter=2_000_000):
    """Standart iki-asal Fermat."""
    a = gmpy2.isqrt(n)
    if a * a < n:
        a += 1
    b2 = a * a - n
    for _ in range(max_iter):
        b, rem = gmpy2.isqrt_rem(b2)
        if rem == 0:
            return int(a + b), int(a - b)
        a += 1
        b2 = a * a - n
    return None, None


# --- LACTF very-hot cozumu ---
n = 0x...   # challenge N degeri
e = 65537
c = 0x...   # sifreli metin

flag = factor_three_close_primes(n, e, c)
if flag:
    print(flag)
```

---

## Gerçek Challenge Referansı: LACTF 2024 — very-hot

**Kategori:** Crypto
**Puan:** 488
**Açıklama:** "The primes are very hot right now!"

**Kilit ipucu:** Kaynak kodda `getStrongPrime` yerine standart `getPrime` kullanılmış ve üç asal birbirinin yakınında seçilmiştir. `N`'in bit uzunluğu üç asalın bit uzunluğundan çok daha büyük değil, bu da küp kök yaklaşımının doğru olduğunu gösteriyor.

**Çözüm özeti:**
1. `cbrt(N)` hesapla
2. Civarında kaba kuvvet ile `p`'yi bul (2^25 adım yeterli)
3. `N // p` üzerinde tekrar Fermat uygula
4. `phi(N) = (p-1)(q-1)(r-1)` ile private key hesapla
5. `m = pow(c, d, N)` ile mesajı çöz

**Çözüm süresi:** Yaklaşık 30-90 saniye (PyPy ile daha hızlı).

---

## Tuzaklar

| Tuzak | Çözüm |
|-------|-------|
| `gmpy2.isqrt` yerine `math.isqrt` kullanmak — büyük sayılarda taşabilir | Her zaman `gmpy2` kullan |
| `a * a - n` negatif çıkabilir ilk adımda | `a = ceil(sqrt(n))` garantile: `if a*a < n: a += 1` |
| N = p*q*r için `phi` hatalı hesaplamak | `(p-1)*(q-1)*(r-1)` — üç faktör için |
| Iteration sayısını çok düşük tutmak | `|p-q|` 2^24 civarındaysa milyonlarca iterasyon gerekebilir |
| FactorDB'ye güvenmek | Taze üretilmiş yakın asallar FactorDB'de yoktur — her zaman kendin dene |
| p veya q negatif çıkabilir | `assert p > 0 and q > 0` ekle |

---

## Hızlı Tanı Scripti

```python
import gmpy2, math

def hizli_tani(n):
    """N'in Fermat saldırısına yatkın olup olmadığını kontrol eder."""
    sqrt_n = gmpy2.isqrt(n)
    print(f"[*] N bit uzunlugu: {n.bit_length()}")
    print(f"[*] sqrt(N) = {sqrt_n}")

    # Ilk 1000 iterasyonu hizlica dene
    a = sqrt_n if sqrt_n * sqrt_n >= n else sqrt_n + 1
    b2 = a * a - n
    for i in range(1000):
        b, rem = gmpy2.isqrt_rem(b2)
        if rem == 0:
            p, q = int(a+b), int(a-b)
            print(f"[!!!] FERMAT BASARILI {i}. iterasyonda!")
            print(f"      p = {p}")
            print(f"      q = {q}")
            print(f"      |p-q| = {abs(p-q)}")
            return True
        a += 1
        b2 = a * a - n

    # Kaba kuvvet ile kucuk faktor ara
    for small in range(2, 100_000):
        if n % small == 0:
            print(f"[!!!] Kucuk faktor bulundu: {small}")
            return True

    print("[-] Ilk 1000 iterasyonda bulunamadi — daha derin arama gerekli")
    return False

# Kullanim:
# hizli_tani(N_degeri)
```

<!--
  ⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih
  Yetkisiz kullanim/kopyalama tespit edilebilir.
  hash: 7b27bdc648b6eb28
-->

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…