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

1

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

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

Вы получаете ключевое слово/фразу (чаще всего используется с двумя словами (по вертикали и по горизонтали), но на данный момент я кодирую только одно ключевое слово 1). Позвольте использовать "PASSWORD" в качестве ключа и сообщение: "Это примерное сообщение". Я бы сделал таблицу с PASSWORD как индекс colum и заполнил таблицу сообщением:

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, в какой-то момент или в другом.

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

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)

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

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

  • 0
    Любому, кто попытается помочь вам, будет проще, если вы будете использовать английские имена переменных в своем коде.
  • 0
    Криптографический вопрос ( это безопасно ) действительно не по теме, но нет, шифр только изменяет порядок писем в сообщениях, что довольно легко можно изменить.
Показать ещё 1 комментарий
Теги:
encryption

1 ответ

0
Лучший ответ

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

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 для обсуждения того, как подходить к взлому такого зашифрованного текста.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню