Загрузка данных


import urllib.request
import json
import sys

BASE = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:5000"

def get(path):
    with urllib.request.urlopen(BASE + path, timeout=10) as resp:
        return json.loads(resp.read().decode())

info = get("/public_key")
n = int(info["n"])
e = int(info["e"])
c = int(info["ciphertext"])
print(f"[+] n bits = {n.bit_length()}")
print(f"[+] e = {e}")

def oracle(ct):
    r = get(f"/oracle?ciphertext={ct}")
    return r["even"]

# Атака Блейхенбахера
lower = 0
upper = n
current_c = c

# Количество итераций: n.bit_length() + запас
MAX_ITER = n.bit_length() + 10

for i in range(MAX_ITER):
    current_c = (current_c * pow(2, e, n)) % n
    is_even = oracle(current_c)
    mid = (lower + upper) // 2
    if is_even:
        upper = mid
    else:
        lower = mid
    
    # Каждые 100 итераций пробуем восстановить
    if i % 100 == 0 or i == MAX_ITER - 1:
        k = i + 1
        # m ≈ upper * n / 2^k
        m_approx = (upper * n) >> k
        if m_approx > 0:
            try:
                b = m_approx.to_bytes((m_approx.bit_length() + 7) // 8, 'big')
                if all(32 <= x < 127 for x in b):
                    print(f"[{i}] m ≈ {b}")
            except:
                pass

# Финальное восстановление
k = MAX_ITER
m_final = (upper * n) >> k
b = m_final.to_bytes((m_final.bit_length() + 7) // 8, 'big')
print(f"\n[+] Recovered: {b}")