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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.