2.6 KiB
2.6 KiB
Elliptic Enigma
В руках два файла:
| Файл | Что внутри |
|---|---|
public/server.py |
Код сервера подписи |
public/signatures.json |
Параметры кривой, публичный ключ, 30 подписей, шифротекст флага |
ECDSA на кастомной эллиптической кривой — смотрим генерацию nonce k, обычно вся соль в нём.
Решение
В коде сервера:
k = random.getrandbits(120)
Порядок группы n — 128 бит. У каждого k старшие 8 бит тупо равны нулю. Даже небольшая утечка нескольких бит nonce, размазанная по десяткам подписей, приводит прямиком к Hidden Number Problem, а HNP классически решается решёточной редукцией (LLL).
Стандартная ECDSA-подпись: для сообщения с хешем z считается
s = k^{-1}(z + r \cdot d) \pmod{n}
Откуда чистой алгеброй:
k = s^{-1} z + s^{-1} r d \pmod{n}
Обозначим t_i = s_i^{-1} r_i \pmod{n} и u_i = s_i^{-1} z_i \pmod{n}, и для каждой подписи получаем уравнение вида
k_i = u_i + t_i \cdot d \pmod{n}, \qquad k_i < 2^{120}
Получили классическую постановку HNP: много сравнений по модулю n, а сами скрытые числа маленькие.
Дальше — стандартный пайплайн:
- Загружаем подписи из
signatures.json. - Для каждого сообщения считаем
z_iтак же, как сервер:SHA-256, первые 16 байт. - Вычисляем
t_iиu_i. - Собираем из них решётку для LLL и запускаем редукцию.
- Из редуцированного базиса вытаскиваем кандидатов на приватный ключ
d. - С
dна руках расшифровываем флаг:AES-256-CBC(SHA256(d), iv=0, ciphertext).
Флаг
caplag{b14s3d_n0nc3_l4tt1c3_r3duc710n}