Создание простого кода шифрования в Python и проблемы со словарем / логикой - PullRequest
0 голосов
/ 15 октября 2018

Я - студент питона (сам по себе), и в качестве упражнения я решил попробовать написать скрипт для «шифрования / дешифрования» сообщения.«Алгоритм шифрования», который я использую, очень прост, я узнал во время военной службы, и он использовался для полевых войск для шифрования только радиосообщений.Я предполагаю, что это не безопасный способ зашифровать вещи.(Если кто-то может прокомментировать это, я хотел бы узнать больше) В любом случае, я делаю это как упражнение для программирования логики, но я застрял на некоторое время.

Вот как этоworks:

Вы получаете ключевое слово / фразу (чаще используется с 2 словами (вертикальное и горизонтальное), но сейчас я кодирую только 1 ключевое слово).Давайте используем «ПАРОЛЬ» в качестве ключа и сообщение: «Это пример сообщения».Я бы составил таблицу с ПАРОЛЕМ в качестве индекса столбца и заполнил таблицу сообщением:

P   A   S   S   W   O   R   D
t   h   i   s   i   s   a   s
a   m   p   l   e   m   e   s
s   a   g   e   x   y   z   x

[Поскольку сообщение не заполняло все столбцы, мы заполнили его буквами, которые не вызовут проблем]
Затем мы определяем порядок скремблирования, выводя его в алфавитном порядке по ключу:

4   1   6   7   8   3   5   2
P   A   S   S   W   O   R   D
[a,d,o,p,r,s,s,w]

Таким образом, строка за строкой, буква за буквой, мы будем брать буквы из сообщения в соответствии спорядок ключей и сформируйте зашифрованное сообщение: «hsstaisi» для первой строки, «msmaeple» и «axyszgex» для второй и третьей строки.Таким образом, сообщение будет «hsstaisimsmaepleaxyszgex» [Обычно передается как «hssta isims maepl eaxys zgex», чтобы облегчить работу оператора радиосвязи]

Теперь код: Мне удается заставить его работать(вроде ...), вот как:

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

{'p': 0, a ': 1,' s ': 2, ...} # [Вот моя проблема]

После этого мыотсортировать ключ (список) по алфавиту и использовать его в качестве итератора для вызова ключа (dict), который будет вызывать номер, который будет индексом из списка сообщений.(Мое объяснение сбивает с толку, может быть легче понять, проверяя код ниже).Буквенно за буквой сообщение шифруется и добавляется в новый список, а затем представляется как «зашифрованный».

Работает!За исключением случаев, когда ключевая фраза содержит повторяющиеся буквы (например, наш «пароль»).В этой ситуации соответствующее значение повторяющегося ключа словаря перезаписывается, потому что ключи dict являются уникальными.

Я написал несколько разных версий для одного и того же кода, но я всегда зацикливаюсь на проблеме dict, в тот или иной момент.

Вот фрагмент кода:

key = ['p','a','s','s','w','o','r','d']
msg = ['t','h','i','s','i','s','a','s','a','m','p','l','e','m','e','s','s','a','g','e']
def encrypt(key_list,msg_list):
       while len(msg_list) % len(key_list) != 0:
           rest = len(key_list) - (len(msg_list) % len(key_list))
           for i in range(rest):
               if msg_list[-1] == 'z':
                   msg_list.append('x')
               else:
                   msg_list.append('z')
       key_dict = {}
       for i in range(len(key_list)):
           key_dict[key_list[i]] = i
       key_list.sort() 
       qnty_rows = len(msg_list) // len(key_list)
       cloop = 0
       scramble_list = []
       while cloop < qnty_rows:
           for i in range(len(key_list)):
               scramble_list.append(msg_list[key_dict[key_list[i]]+(cloop*len(key_list))])
           cloop +=1
       encrypted_msg = "".join(scramble_list)
       print(encrypted_msg)

Может кто-нибудь помочь мне найти решение или указать мне правильное направление?

Учитывая то, что я все еще учусь кодировать, любая конструктивная критика кода в целом приветствуется.

1 Ответ

0 голосов
/ 16 октября 2018

Ваша ошибка заключается в том, как вы назначаете номера столбцов для каждого из ключевых символов, используя словарь:

for i in range(len(key_list)):
    key_dict[key_list[i]] = i

Для повторяющихся букв остается только последний индекс;s из password отображается сначала на 2, затем на 3, поэтому key_dict['s'] в конечном итоге становится 3:

i = 0, key_list[i] == 'p', key_dict['p'] = 0
i = 1, key_list[i] == 'a', key_dict['a'] = 1
i = 2, key_list[i] == 's', key_dict['s'] = 2
i = 3, key_list[i] == 's', key_dict['s'] = 3  # replacing 2
i = 4, key_list[i] == 'w', key_dict['w'] = 4
# etc.

Не используйте словарь;создать список парных индексных и символьных значений, отсортировать их по буквам, а затем извлечь только индексы:

indices = [i for i, c in sorted(enumerate(key_list, key=lambda p: p[1]))]

Я использовал функцию enumerate() для генерации индексов;он выполняет то же самое, что и ваш цикл range(len(key_list)) в более компактной форме.

Поскольку enumerate() создает (index, value) пар, и мы хотим отсортировать значения (символы), в приведенном выше коде используется ключ сортировки извлечение значений (p[1]).

Обратите внимание, что вам не нужен ваш ключ, чтобы быть списком даже , вышеописанное будет работать напрямуюстрока тоже;Строки - это последовательности, точно так же как списки.

Вот как это работает:

>>> keyphrase = 'password'
>>> list(enumerate(keyphrase))  # add indices
[(0, 'p'), (1, 'a'), (2, 's'), (3, 's'), (4, 'w'), (5, 'o'), (6, 'r'), (7, 'd')]
>>> sorted(enumerate(keyphrase), key=lambda p: p[1])  # sorted on the letter
[(1, 'a'), (7, 'd'), (5, 'o'), (0, 'p'), (6, 'r'), (2, 's'), (3, 's'), (4, 'w')]
>>> [i for i, c in sorted(enumerate(keyphrase), key=lambda p: p[1])]  # just the indices
[1, 7, 5, 0, 6, 2, 3, 4]

Теперь вы можете использовать эти индексы для перераспределения фрагментов ввода в виде открытого текста в зашифрованный вывод.

То, что у вас есть, называется столбчатый шифр транспонирования .Для современных компьютеров такой шифр достаточно тривиален.См. https://crypto.stackexchange.com/questions/40119/how-to-solve-columnar-transposition-cipher-without-a-key для обсуждения того, как подходить к взлому такого зашифрованного текста.

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