Найти в Дзене
ZDG

Проект Эйлер 59: XOR-шифровка

Задача Каждый символ в компьютере имеет уникальный код, предпочитаемым является стандарт ASCII (American Standard Code for Information Interchange - Американский стандартный код для обмена информацией). Для примера, A верхнего регистра = 65, звёздочка (*) = 42, а k нижнего регистра = 107. Современный метод шифровки состоит в том, что берётся текстовый файл, конвертируется в байты по ASCII, а потом над каждым байтом выполняется операция XOR с определённым значением, взятым из секретного ключа. Преимущество функции XOR состоит в том, что применяя тот же ключ к зашифрованному тексту, получаем исходный; к примеру, 65 XOR 42 = 107, тогда 107 XOR 42 = 65. Для невзламываемого шифрования ключ должен быть такой же длины, что и сам текст, и ключ должен быть составлен из случайных байтов. Тогда, если пользователь хранит зашифрованное сообщение и ключ шифрования в разных местах, то без обеих "половинок" расшифровать сообщение просто невозможно. К сожалению, этот метод непрактичен для боль
Оглавление

Задача

Каждый символ в компьютере имеет уникальный код, предпочитаемым является стандарт ASCII (American Standard Code for Information Interchange - Американский стандартный код для обмена информацией). Для примера, A верхнего регистра = 65, звёздочка (*) = 42, а k нижнего регистра = 107.

Современный метод шифровки состоит в том, что берётся текстовый файл, конвертируется в байты по ASCII, а потом над каждым байтом выполняется операция XOR с определённым значением, взятым из секретного ключа. Преимущество функции XOR состоит в том, что применяя тот же ключ к зашифрованному тексту, получаем исходный; к примеру, 65 XOR 42 = 107, тогда 107 XOR 42 = 65.

Для невзламываемого шифрования ключ должен быть такой же длины, что и сам текст, и ключ должен быть составлен из случайных байтов. Тогда, если пользователь хранит зашифрованное сообщение и ключ шифрования в разных местах, то без обеих "половинок" расшифровать сообщение просто невозможно.

К сожалению, этот метод непрактичен для большинства пользователей, поэтому упрощённый метод использует в качестве ключа пароль. Если пароль короче текстового сообщения, что наиболее вероятно, то ключ циклично повторяется на протяжении всего сообщения. Идеальный пароль для этого метода достаточно длинный, чтобы быть надёжным, но достаточно короткий, чтобы его можно было запомнить.

У вас лёгкая задача, так как пароль состоит из трех символов нижнего регистра. Используя файл cipher1.txt, содержащий зашифрованные коды ASCII, а также тот факт, что сообщение должно содержать распространенные английские слова, расшифруйте сообщение и найдите сумму всех значений ASCII в исходном тексте.

Решение

Исходя из того, что это английский текст, надо подсчитывать частоты встречаемых символов. Наиболее часто встречаемым символом является 'E', но забегая вперёд, скажу, что это не пригодилось.

Так как ключ состоит из трёх кодов, то каждый i*3 символ в тексте будет закодирован первым кодом. Следовательно, можно посчитать количество одинаковых каждых третьих символов и найти тот, который наиболее часто повторяется. Затем посчитать количество каждых i*3+1 и каждых i*3+2 символов, которые закодированы соответственно вторым и третьим кодом.

Так как символы в тексте распределены более-менее равномерно, то наиболее часто встречающиеся будут наиболее часто встречаться во всех трёх группах. Приняв, что это один и тот же символ, и он нам эмпирически известен, можно вычислить первый, второй и третий коды ключа.

Сам файл я не стал читать и просто перенёс его содержимое в программу:

Функция, которая находит наиболее часто повторяющийся код:

-2

Она запускается со смещением 0, 1 или 2 относительно начала текста, перебирает каждый третий символ, накапливает 256 счётчиков для каждого возможного кода (на деле их всего 100) и запоминает код с текущим максимальным счётчиком.

Получив наиболее часто повторяющийся код, мы предполагаем, что это буква 'e'... Нет, на самом деле наиболее часто повторяется пробел :) Просто изначально я не знал ничего о природе текста, например, содержит ли он пробелы вообще. Но буква 'e' не дала результата, поэтому попробовал пробел и угадал.

Таким образом, мы имеем код пробела, над которым совершён XOR с каким-то кодом. Чтобы узнать код шифрования, надо над зашифрованным пробелом сделать ещё один XOR с обычным пробелом. Это кстати тот самый приём обмена значений двух переменных, о котором писалось здесь:

Я получил три кода шифрования в массиве codes:

-3

Дальше всё тривиально: пройти по тексту и циклически применить XOR с кодами шифрования к символам текста.

-4

Задача требует найти сумму символов текста, но я распечатал и сам текст, естественно, чтобы убедиться, что результат правильный.

-5

Ссылка на онлайн-компилятор языка C с текстом программы

Подборка всех задач:

Проект Эйлер | ZDG | Дзен

Наука
7 млн интересуются