Python: Есть ли хороший способ проверить, зашифрован ли текст? - PullRequest
5 голосов
/ 09 августа 2011

Я играл с cryptocat , который представляет собой интересный сервис онлайн-чата, который позволяет вам шифровать ваши сообщения ключом, так что только люди с одинаковым ключом могут прочитать ваше сообщение. Интересным аспектом службы (на мой взгляд) является тот факт, что текст, зашифрованный с использованием ключа, отличного от того, который вы используете, отображается просто как «[зашифрованный]», а не как набор зашифрованного текста. Мой вопрос, в Python, есть ли хороший способ определить, является ли данный фрагмент текста зашифрованным текстом? Я использую RC4 для этого примера, потому что это была самая быстрая вещь, которую я мог реализовать (на основе псевдокода в Википедии . Спасибо.

Ответы [ 3 ]

13 голосов
/ 09 августа 2011

нет гарантированного способа сказать, но на практике вы можете сделать две вещи:

  1. проверьте наличие множества не-ascii символов (если вы ожидаете, что люди будут отправлять текст на английском языке).

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

простой способ сделать последнее - посмотреть, встречается ли какой-либо символ более (N / 256) + 5 * sqrt (N / 256) раз (где у вас всего N символов), и в этом случае вероятно естественный язык (незашифрованный).

в python (изменяя логику выше, чтобы дать "истину" при шифровании):

def encrypted(text):
    scores = defaultdict(lambda: 0)
    for letter in text: scores[letter] += 1
    largest = max(scores.values())
    average = len(text) / 256.0
    return largest < average + 5 * sqrt(average)

математика исходит из среднего числа, представляющего собой гауссовское распределение вокруг среднего, с дисперсией, равной среднему - она ​​не идеальна, но, вероятно, достаточно близка. по умолчанию (с небольшим количеством текста, когда это ненадежно) это вернет false (извините; раньше у меня была неправильная версия с "max ()", в которой логика для маленьких чисел была неправильной).

4 голосов
/ 09 августа 2011

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

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

С другой стороны, вы также можетесравните статистические данные на диграммах и триграммах вашего конкретного языка, представляющего интерес, с вхождениями в данные, которые вы наблюдаете (см. также здесь ).Если ваши данные ведут себя одинаково, то, скорее всего, вы наблюдаете простой текст.

0 голосов
/ 10 августа 2011

Один из способов сказать это заполнение.Добавьте стандартные отступы в конец сообщения.Если дешифрованное сообщение не заканчивается стандартным заполнением, то оно было расшифровано неправильным ключом.Обратное не гарантируется, но часто верно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...