Учитывая этот конкретный дизайн шифра и корпус известного открытого текста, существует ли криптоаналитическая или структурная слабость, которая позволяет восстанавливать или дешифровать ключ быстрее, чем методом грубой силы?
Настройка следующая:
В mycipher.py реализован собственный шифр (8-байтовые блоки, 64-битный блочный шифр).
Секретный мастер-ключ утерян.
У нас есть файл данных, содержащий известные пары открытый текст-зашифрованный текст (по 16 байт каждая: 8 байт открытого текста + 8 байт зашифрованного текста).
Существует также отдельный зашифрованный текст, который мы должны расшифровать.
Известные пары открытый текст-зашифрованный текст генерируются с использованием необработанного блочного шифрования (
) без CBC или IV, в то время как целевой зашифрованный текст использует CBC со случайным IV.
Вот что я пробовал до сих пор:
Обнаружение ECB и CBC
Я запустил обнаружение ECB на зашифрованном тексте. Все 52 блока были уникальными.
Шаблоны ECB (повторяющиеся блоки) отсутствовали → зашифрованный текст нетривиально ECB.
Тесты обнаружения CBC вернули значение False для ECB.
Кодовая книга ECB атака
Загрузили все 65 536 известных пар открытый текст-зашифрованный текст из данных.
Пыталась сопоставить каждый блок зашифрованного текста → совсем нет.
Грубая сила/слабый ключ попыток
Проверены все правдоподобные 8-байтовые слабые ключи (все нули, все единицы, последовательности ASCII, общие шаблоны проверки).
Попытка частичного перебора первых 4 байтов + ограниченная вторая половина → нет совпадений ключей.
Подходы дифференциального/линейного криптоанализа
Построен S-box DDT, исследованы дифференциалы с высокой вероятностью.
Попытка упрощенной дифференциальной атаки на 1-2 раунда.
Построена таблица линейной аппроксимации (LAT) → ничего убедительно.
Другие наблюдения
Все блоки зашифрованного текста уникальны (без повторений).
Похоже, что файл данных использует внутренне ECB, но зашифрованный текст, который мы хотим расшифровать, может быть чем-то другим (возможно) CBC или IV).
Перебор всего 64-битного пространства ключей (2^64) невозможен даже при использовании высокопроизводительных графических процессоров.
На данный момент кажется, что восстановление ключей или полная расшифровка из предоставленных пар невозможны. Я подозреваю, что профессор намеренно спроектировал ее неразрешимой, или реальное решение может включать в себя скрытую подсказку (возможно, в структуре данных, шаблонах ASCII или в mycipher.py), а не криптоанализ.
Выглядит ли вообще возможным восстановить ключ или расшифровать зашифрованный текст с помощью имеющихся у нас данных?
есть ли какие-либо «хитрости» или распространенные ошибки в таких университетских задачах ECB/CBC, которые я могу упустить?
Может ли дать что-нибудь здесь атака «встреча посередине», дифференциальная или линейная, учитывая размер блока 8 байт и дизайн S-box?
Учитывая этот конкретный дизайн шифра и корпус известного открытого текста, существует ли криптоаналитическая или структурная слабость, которая позволяет восстанавливать или дешифровать ключ быстрее, чем методом грубой силы? Настройка следующая: [list] [*]В mycipher.py реализован собственный шифр (8-байтовые блоки, 64-битный блочный шифр).
[*]Секретный мастер-ключ утерян.
[*]У нас есть файл данных, содержащий [b]известные пары открытый текст-зашифрованный текст[/b] (по 16 байт каждая: 8 байт открытого текста + 8 байт зашифрованного текста).
[*]Существует также отдельный зашифрованный текст, который мы должны расшифровать.
[/list] Известные пары открытый текст-зашифрованный текст генерируются с использованием необработанного блочного шифрования ([code]_encrypt_block[/code]) без CBC или IV, в то время как целевой зашифрованный текст использует CBC со случайным IV. Вот что я пробовал до сих пор: [list] [*][b]Обнаружение ECB и CBC[/b] [list] Я запустил обнаружение ECB на зашифрованном тексте. Все 52 блока были уникальными.
[*]Шаблоны ECB (повторяющиеся блоки) отсутствовали → зашифрованный текст [b]нетривиально ECB[/b].
[*]Тесты обнаружения CBC вернули значение False для ECB.
[/list]
[*][b]Кодовая книга ECB атака[/b] [list] Загрузили все 65 536 известных пар открытый текст-зашифрованный текст из данных.
[*]Пыталась сопоставить каждый блок зашифрованного текста → [b]совсем нет[/b].
[/list]
[*][b]Грубая сила/слабый ключ попыток[/b] [list] Проверены все правдоподобные 8-байтовые слабые ключи (все нули, все единицы, последовательности ASCII, общие шаблоны проверки).
[*]Попытка частичного перебора первых 4 байтов + ограниченная вторая половина → [b]нет совпадений ключей[/b].
[/list]
[*][b]Подходы дифференциального/линейного криптоанализа[/b] [list] Построен S-box DDT, исследованы дифференциалы с высокой вероятностью.
[*]Попытка упрощенной дифференциальной атаки на 1-2 раунда.
[*]Построена таблица линейной аппроксимации (LAT) → ничего убедительно.
[/list]
[*][b]Другие наблюдения[/b] [list] Все блоки зашифрованного текста уникальны (без повторений).
[*]Похоже, что файл данных использует внутренне ECB, но зашифрованный текст, который мы хотим расшифровать, может быть чем-то другим (возможно) CBC или IV).
[*]Перебор всего 64-битного пространства ключей (2^64) невозможен даже при использовании высокопроизводительных графических процессоров.
[/list]
[/list] На данный момент кажется, что [b]восстановление ключей или полная расшифровка из предоставленных пар невозможны[/b]. Я подозреваю, что профессор намеренно спроектировал ее неразрешимой, или реальное решение может включать в себя скрытую подсказку (возможно, в структуре данных, шаблонах ASCII или в mycipher.py), а не криптоанализ. [list] [*]Выглядит ли вообще возможным восстановить ключ или расшифровать зашифрованный текст с помощью имеющихся у нас данных?
[*] есть ли какие-либо «хитрости» или распространенные ошибки в таких университетских задачах ECB/CBC, которые я могу упустить?
[*]Может ли дать что-нибудь здесь атака «встреча посередине», дифференциальная или линейная, учитывая размер блока 8 байт и дизайн S-box?
[/list] Код для mycipher.py следующий: следующее: [code]#!/usr/bin/env python # coding=utf-8 """ MyCipher - a toy 64-bit block cipher with a minimal CLI ======================================================
Included corpus --------------- Alongside the cipher code, a separate binary file named **`data`** is provided. It contains 65,536 plaintext-ciphertext pairs, generated by running:
$ python mycipher.py generate
Unfortunately, the original contents of **`secret`** (i.e., `secret.py`, which held the encryption key used during generation) have been **lost**. As a result, the *data* file remains a publicly accessible corpus of known plaintext-ciphertext pairs, but the private key that produced them is no longer available.
Quick start ----------- Encrypt or decrypt any file using the key stored in **`secret.py`**. If you've recovered a key, create `secret.py` with its contents:
def _encrypt_block(self, block: bytes) -> bytearray: if len(block) != self.key_size: raise ValueError("Plaintext block must be exactly one block in size") b = bytearray(block) for i in range(self.rounds): b = _addkey(b, self._rk(i)) b = _substitute(b) if i != self.rounds - 1: b = _permutation(b) b = _addkey(b, self._rk(self.rounds)) return b
def _decrypt_block(self, block: bytes) -> bytearray: if len(block) != self.key_size: raise ValueError("Ciphertext block must be exactly one block in size") b = bytearray(block) b = _addkey(b, self._rk(self.rounds)) for i in reversed(range(self.rounds)): if i != self.rounds - 1: b = _permutation_inv(b) b = _substitute_inv(b) b = _addkey(b, self._rk(i)) return b
def _pad(self, data: bytes) -> bytes: pad_len = self.key_size - (len(data) % self.key_size) if pad_len == 0: pad_len = self.key_size # always pad at least one block return data + bytes([pad_len] * pad_len)
def _unpad(self, data: bytes) -> bytes: if not data or len(data) % self.key_size: raise ValueError("Invalid padded data length") pad_len = data[-1] if pad_len == 0 or pad_len > self.key_size or data[-pad_len:] != bytes([pad_len] * pad_len): raise ValueError("Invalid padding") return data[:-pad_len]
for off in range(0, len(padded), self.key_size): block = bytearray(padded[off:off + self.key_size]) enc = self._encrypt_block(_addkey(block, prev)) out_blocks.append(enc) prev = enc
return b"".join(out_blocks)
def decrypt(self, ciphertext: bytes) -> bytes: if len(ciphertext) < self.key_size * 2 or len(ciphertext) % self.key_size: raise ValueError("Ciphertext is too short or not block-aligned")
iv, *c_blocks = [ciphertext[i:i + self.key_size] for i in range(0, len(ciphertext), self.key_size)]
prev = bytearray(iv) p_blocks: list[bytes] = []
for c in c_blocks: dec = _addkey(self._decrypt_block(c), prev) p_blocks.append(dec) prev = bytearray(c)
with open("data", "wb") as fh: for _ in range(65_536): plaintext = os.urandom(8) ciphertext = cipher._encrypt_block(plaintext) fh.write(struct.pack("8B", *plaintext)) fh.write(struct.pack("8B", *ciphertext)) print(f"Generated data file (65,536 plaintext/ciphertext pairs)")
def _read_file(path: str) -> bytes: with open(path, "rb") as fh: return fh.read()
def _write_file(path: str, data: bytes) -> None: with open(path, "wb") as fh: fh.write(data)
# generate p_gen = subparsers.add_parser("generate", help="Generate plaintext-ciphertext pairs and store them in the `data` file") p_gen.set_defaults(func=_cmd_generate)
# encrypt p_enc = subparsers.add_parser("encrypt", help="Encrypt a file") p_enc.add_argument("infile", help="Path to input file to encrypt") p_enc.add_argument("outfile", help="Path for encrypted output file") p_enc.set_defaults(func=_cmd_encrypt)
# decrypt p_dec = subparsers.add_parser("decrypt", help="Decrypt a file previously produced by this cipher") p_dec.add_argument("infile", help="Ciphertext file to decrypt") p_dec.add_argument("outfile", help="Destination for decrypted plaintext") p_dec.set_defaults(func=_cmd_decrypt)
args_ns = parser.parse_args() args_ns.func(args_ns) [/code] При необходимости я могу предоставить файл данных для справки. Заранее благодарим за любые рекомендации!