Top.Mail.Ru

Python. Взлом шифров

В этой и нескольких последующих статьях я расскажу о том, как на языке Python написать программу взлома шифров. Для создания тестового шифра вам понадобиться программа шифратор, исходники которой на C++ прилагаю:

coder

В архиве прога, исходный не зашифрованный текст inp.txt, зашифрованный текст out.txt и ключ key1.txt. Кратко об этой проге.

Для создания ключа шифрования запустите coder.exe k <key_file>, для зашифровки текстового файла coder.exe c <output_file> <input_file> <key_file>, для расшифровки coder.exe в <output_file> <input_file> <key_file>. Если хотите расширить алфавит, то найдите строки:

char* create_alphabet()
{
	return("абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧЪЫЬЭЮЯ.,()+-*!?;: []\|/_0123456789");
}

И отредактируйте, а потом перекомпилируйте прогу.

Теперь о самой программе взлома шифра на Python. Шифр у нас довольно простой, это шифр замены: каждый символ заменен каким-то другим символом, например, вместо буквы «А» буква «Д», вместо «К» буква «Р». Программа шифратор генерирует ключи просто случайно перемешивая буквы. Как ломать такие шифры? Можно использовать частотный анализ символов. Берем какой-либо текст (нормальный, не зашифрованный), и считаем, сколько раз какой символ в нем встречается. Аналогичный подсчет делаем для зашифрованного текста и на основании этого создаем предполагаемое соответствие. Конечно, с первого раза, мы скорее всего, «не угадаем», но, давайте попробуем, посмотрим что получиться и дальше спланируем следующие шаги. Итак, вот наша программа на Python, которая делает вышеперечисленные действия:

f_templ = open('d:\9\шаблон.txt', 'r')
f_text = open('d:\9\out.txt', 'r')
f_result = open("d:\9\some.txt", "w")
f_matching = open("d:\9\match.txt", "w") #файл с сопоставлением словарей

#функция создания словаря
def create_dic(f):
    dic={}
    for line in f:
        str_len=len(line)
        i=0
        while i<str_len:
            c=line[i]
            if dic.get(c)==None:
                dic=1
            else:
                dic=dic+1
            i=i+1
    return dic

#Создадим словарь шаблона
dic_templ=create_dic(f_templ)

#превратим словарь шаблона в список и отсортируем его
#тип полученного списка - список кортежей (тьюплов)
list_templ=list(dic_templ.items())
list_templ.sort(key=lambda item: item[1], reverse=True)

#создадим словарь зашифрованного текста
dic_text=create_dic(f_text)

#превратим словарь шаблона в список и отсортируем его
list_text=list(dic_text.items())
list_text.sort(key=lambda item: item[1], reverse=True)

#пробежимся по словарям и выведем в файл сопоставление
i=0
len_dic=len(list_text)
if len_dic>len(list_templ):
    len_dic=len(list_templ)    
while i<len_dic:
    f_matching.write(str(list_text[i][0])+"^"+str(list_text[i][1])+"^"+str(list_templ[i][0])+"^"+str(list_templ[i][1])+"\n")
    i=i+1
if len_dic>len(list_text):
    while i<len(list_text):
        f_matching.write(str(list_text[i][0])+"^"+str(list_text[i][1])+"^^\n")
        i=i+1
        
f_matching.close()

#Сейчас мы будем перебирать файл, обрабатывать каждую его строку и писать в результатирующий файл
f_text.seek(0)
for line in f_text:
    i=0
    str_len=len(line)
    new_str=""
    while i<str_len:
        c=line[i]
        j=0        
        list_len=len(list_text)
        c_dist="@"+c+"@"
        while j<list_len:
            tp=list_text[j]
            if tp[0]==c:
                if j<len(list_templ):
                    c_dist=list_templ[j][0]
                else:
                    c_dist="#"+c+"#"
                break
            j=j+1
        new_str=new_str+c_dist
        i=i+1        
    f_result.write(new_str)
 
f_result.close()

Эта программа создает предварительно расшифрованный файл и файл предполагаемого соответствия. Прежде чем начать анализировать это полурасшифрованный файл, разберём саму программу.  Вначале мы открываем файлы командой open:

f_templ = open('d:\9\шаблон.txt', 'r')
f_text = open('d:\9\out.txt', 'r')
f_result = open("d:\9\some.txt", "w")
f_matching = open("d:\9\match.txt", "w") #файл с сопоставлением словарей

Как вы поняли, открыть можно как на запись, так и на чтение. Функция open возвращает объект файла, с которым можно работать, используя разные методы класса данного объекта, в частности, чтенеи и запись данных.

Далее, используя def мы создаем функцию, которой, в дальнейшем читаем сначала шаблон, а потом и зашифрованный файл. При чтении мы сразу анализируем частотный состав букв, используя такую структуру данных, как словарь.

Что такое словарь? Словарь — это структура данных, имеющая ряд значений, к которым осуществляется доступ по ключу. В нашем случае в качестве ключей используются буквы алфавита, а в качестве значений — посчитанное количество этих самых букв.

Итак, сначала мы сознаем пустой словарь:

dic={}

А дальше мы в цикле читаем файл, перебираем символы строки и, если такой символ встречается первый раз, добавляем в словарь, если уже не первый — увеличиваем счетчик этого символа на 1:

    for line in f:
        str_len=len(line)
        i=0
        while i<str_len:
            c=line[i]
            if dic.get(c)==None:
                dic=1
            else:
                dic=dic+1
            i=i+1

Созданный словарь нам надо отсортировать. Но так как в Python нет средств для сортировки словарей, мы конвертируем его в список, и уже список сортируем в обратном порядке (в порядке убывания количеств символов):

#Создадим словарь шаблона
dic_templ=create_dic(f_templ)

#превратим словарь шаблона в список и отсортируем его
#тип полученного списка - список кортежей (тьюплов)
list_templ=list(dic_templ.items())
list_templ.sort(key=lambda item: item[1], reverse=True)

Это мы сделали для шаблона. Для словаря зашифрованного файла все аналогично.  Затем, нам, во-первых, необходимо записать словари в файл, мы их еще будем использовать в будущих уроках. Для чтения из файла мы используем метод read, а для записи — write. Вот, посмотрите, как мы реализовали запись словарей в файл:

#пробежимся по словарям и выведем в файл сопоставление
i=0
len_dic=len(list_text)
if len_dic>len(list_templ):
    len_dic=len(list_templ)    
while i<len_dic:
    f_matching.write(str(list_text[i][0])+"^"+str(list_text[i][1])+"^"+str(list_templ[i][0])+"^"+str(list_templ[i][1])+"\n")
    i=i+1
if len_dic>len(list_text):
    while i<len(list_text):
        f_matching.write(str(list_text[i][0])+"^"+str(list_text[i][1])+"^^\n")
        i=i+1
        
f_matching.close()

После записи в файл закрываем его:

f_matching.close()

Теперь, что у нас в итоге получается? Давайте посмотрим зашифрованный файл:

А теперь после предобработки:

Как видим, расшифровать не удалось, но уже не так страшно как было. Пусть текст напоминаем «нетленку» обкуренного наркомана, но, тем не менее,  из него уже можно выудить какую-то информацию, например, мы видим слово «систеке», и, не трудно догадаться, что надо «к» заменить на «м», тогда будет существующее слово «системе». У нас уже есть выгруженные словари, мы их может открыть и отредактировать:

Но об этом в следующем уроке.

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar