Обработка текста, Разработка

Python 3+ и окончания строк в файлах

Столкнулся одного теста, который был перенесен с python 2+ на python 3+.

Тест делал следующее:

скачивал файл через python.requests и сравнивал его с эталонным содержимым на диске (посимвольно).

Выглядело приблизительно так

import requests
import sys
response = requests.get(sys.argv[1])
if response.code == 200:
  with open(sys.argv[2]) as f:
    from_storage = f.read()
    from_web = response.text
    assert from_web == from_storage

Да. Все верно. Этот тест не проходил.

И тут была замечена одна странность: файл на диске содержал последовательность crlf, а в coдержимом from_storage этой последовательности не оказало.

А дело все в том, что в python 3+ было введено соглашение на обработку символов перевода строки. И управление работой осуществляется манипулированием параметром newline.

  • On input, if newline is None, universal newlines mode is enabled. Lines in the input can end in ‘\n’, ‘\r’, or ‘\r\n’, and these are translated into ‘\n’ before being returned to the caller. If it is '', universal newline mode is enabled, but line endings are returned to the caller untranslated. If it has any of the other legal values, input lines are only terminated by the given string, and the line ending is returned to the caller untranslated.
  • On output, if newline is None, any ‘\n’ characters written are translated to the system default line separator, os.linesep. If newline is '', no translation takes place. If newline is any of the other legal values, any ‘\n’ characters written are translated to the given string.

В итоге достаточно было указать newline='' как CRLF появились.

Обработка текста, JFF

Шифр XOR: практика взлома.

В книге «Головоломки для хакера» в самой первой главе есть задача в которой читателю предлагается декодировать текст зашифрованный простым xor. При этом ключ неизвестен.

В качестве текста предлагается некий манифест «The Conscience of a Hacker.txt«.

Приступим 🙂

Для начала нам нужно определить длину ключа.

  • циклически смещаем текст на i (от 1 до len(text)/2) символов вправо
  • для каждой итерации сравниваем количество совпадений символов оригинального (не смещенного) и нового текстов)
  • смещение i при котором количество совпадений будет максимальным и есть искомая длина ключа

И кстати, почему len(text)/2? Правильнее конечно проверять все смещения вплоть до len(text) — 1, но эксперименты показали, что процент совпадений для сдвига i и n-i будет одинаков на больших текстах. Да и кто будет делать ключи длиною больше половины текста?

На практике это выглядит так:

  • У нас есть шифротекст «abcdea»
  • циклически сдвигаем его на i = 1 символов
  • Получаем «aabcde»
  • Ищем количество совпадений символов в строках «abcdea» и «aabcde»
  • У нас есть одно совпадение в нулевом символе.
  • Процент совпадений для сдвига 1 равен ~16,7%
  • Повторяем для всех сдвигов и выбираем тот, у которого процент наибольший

Круто. Длина ключа нам известна.

Теперь надо найти сам ключ.

Для этого поступим таким образом:

  • Разбиваем текст на группы символов
  • Количество групп равно длине ключа
    Если у нас шифротекст "ciphertext" и ключ длиной 3 символа, то в первую группу попадут буквы c,h,t,t; во вторую: i, e, e; а в третью - p, r, x
  • В каждую группу входят символы, которые кодируются i-м символом ключа
  • В каждой из групп ксорим символы с наиболее распространенным в алфавите символом (для английского языка это пробел)
  • Считаем частоты каждого полученного символа среди группы
  • Выбираем в качестве i-й буквы ключа элемент с наибольшей частотой вхождения

Отлично. Потому что этот алгоритм успешно нашел ключ к шифротексту из задачи. Правда автор в решениях рекомендовал поксорить текст с фразой «The Conscience of a Hacker», а потом глазами искать что-то похожее на ключ…

Исходники на гитхабе. Вместе с исходником загадки.

Обработка текста

Практический криптоанализ: дилетант и афинные шифры

Дело было вечером. Но делать было чего.

Возьмем некоторый текст и зашифруем его. А шифровать-то чем? Афинными шифрами конечно. Они-то самые простые. Залезем в педивикию и посмотрим, что это за зверь. В множество афинных шифров входит атбаш и шифр цезаря.

Не будем сильно усложнять и возмем атбаш. Благо у него самый простой алфавит замены.

Исходный текст:      abcdefghijklmnopqrstuvwxyz
Зашифрованный текст: ZYXWVUTSRQPONMLKJIHGFEDCBA

И константы a и b равны соотвестенно 25. Почему так — хорошо показано в вики.

Но сейчас не об этом. Шифровать мы будем Стругацких: «Полдень XXII Век» на английском. Шифроваться ьудет только текст. Без html-разметки.

А после шифрования мы потеряем ключ и попробуем раскодировать.

Читать далее