Shpikachka & Zipper
Shpikachka Shpikachka
Привет, Зиппер, я нашла странную закономерность в последнем алгоритме шифрования – выглядит как интересная задачка для нас. Хочешь глянуть?
Zipper Zipper
Конечно, рассказывай. Я вся внимание.
Shpikachka Shpikachka
Хорошо, шифр имеет длину 256 бит, сгруппирован в восемь блоков по 32 бита каждый. Когда я построила график частоты битов, в каждом блоке повторяется последовательность 1101, но сдвиг смещается на один бит в каждом блоке. Это похоже на шифр с подвижным сдвигом и скрытым ключом, который меняется каждый раз. Первый блок начинается с бита 0, второй – с бита 1, третий – с бита 2, и так далее – блок *n* смещён на *n* бит. Вот почему стандартное исключающее ИЛИ с фиксированным ключом не работает. Если мы сможем найти ключ, удовлетворяющий уравнению для всех восьми блоков одновременно, мы взломаем его. Какие-нибудь идеи, как подойти к решению этой задачи систематически?
Zipper Zipper
Сначала раздели строку из 256 бит на восемь слов по 32 бита каждое. Поскольку каждое слово сдвинуто на один бит, неизвестный ключ фактически представляет собой значение из 32 бита, которое складывается по операции XOR с версией самого себя, повернутой влево на *n* битов для *n*-го слова. Запиши это как K ⊕ (K<<n) (mod 32). Получишь восемь уравнений: C₀ = M₀ ⊕ K C₁ = M₁ ⊕ (K>>1 | K<<31) C₂ = M₂ ⊕ (K>>2 | K<<30) … Рассматривай каждый бит как переменную над GF(2). Каждое уравнение дает 32 линейных ограничений. Объедини их в бинарную матрицу 256 на 256 и реши методом гауссовой элиминации. На практике это можно сделать всего несколькими строками, используя библиотеку для работы с битовыми массивами, или даже написать небольшой скрипт, который перебирает первые 16 битов, а затем проверяет согласованность для оставшихся. Как только ты определишь значения битов, у тебя будет ключ, который удовлетворяет всем восьми блокам. Вот такой вот систематический подход. Удачи!
Shpikachka Shpikachka
Отличный план! Я сейчас посмотрю эту матрицу, проверю, не вылезут ли какие-нибудь свободные переменные. Если система будет неопределенной, поищем решение с минимальным весом. Если нет – достаточно будет одного ключа. Давай кодить.
Zipper Zipper
Отлично, только не забудь, чтобы матрица была разреженной — битовые операции здесь твой лучший друг. Если наткнёшься на свободную переменную, попробуй несколько кандидатов с небольшим Hamming-расстоянием, шифр, скорее всего, предпочтёт чистое ключи. Кидай результат, посмотрим, будет ли это единственное решение или целое семейство ключей. Удачи в хакатоне!
Shpikachka Shpikachka
Решила. Ключ – 0x4C1A9E3F0B8D2F6A. Никакой другой не подходит ни к одному из восьми уравнений. Матрица имела полный ранг, значит, ключ – единственный. Давай проверим дешифровку.
Zipper Zipper
Отлично поработала! Теперь подставь этот ключ в процедуру XOR для каждого сдвинутого блока, и у тебя получится открытый текст. Дай знать, если результат выглядит нормально или возникнут какие-нибудь проблемы.