Шифрование сообщений в Python. От простого к сложному. Шифр Цезаря
Мне, лично, давно была интересна тема шифрования информации, однако, каждый раз погрузившись в эту тему, я осознавал насколько это сложно и понял, что лучше начать с чего-то более простого. Я, лично, планирую написать некоторое количество статей на эту тему, в которых я покажу вам различные алгоритмы шифрования и их реализацию в Python, продемонстрирую и разберу свой проект, созданный в этом направлении. Итак, начнем.
Для начала, я бы хотел рассказать вам какие уже известные алгоритмы мы рассмотрим, в моих статьях. Список вам представлен ниже:
- Шифр Цезаря
- Шифр Виженера
- Шифр замены
- Омофонический шифр
- RSA шифрование
Шифр Цезаря
Итак, после небольшого введения в цикл, я предлагаю все-таки перейти к основной теме сегодняшней статьи, а именно к Шифру Цезаря.
Что это такое?
Шифр Цезаря — это простой тип подстановочного шифра, где каждая буква обычного текста заменяется буквой с фиксированным числом позиций вниз по алфавиту. Принцип его действия можно увидеть в следующей иллюстрации:
Какими особенностями он обладает?
У Шифра Цезаря, как у алгоритма шифрования, я могу выделить две основные особенности. Первая особенность — это простота и доступность метода шифрования, который, возможно поможет вам погрузится в эту тему, вторая особенность — это, собственно говоря, сам метод шифрования.
Программная реализация
В интернете существует огромное множество уроков, связанных с криптографией в питоне, однако, я написал максимально простой и интуитивно понятный код, структуру которого я вам продемонстрирую.
Начнем, пожалуй, с создания алфавита. Для этого вы можете скопировать приведенную ниже строку или написать все руками.
alfavit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ' # Создаем алфавит
Далее, нам нужно обозначить программе шаг, то есть смещение при шифровании. Так, например, если мы напишем букву «а» в сообщении, тот при шаге «2», программа выведет нам букву «в».
Итак, создаем переменную smeshenie, которая будет вручную задаваться пользователем, и message, куда будет помещаться наше сообщение, и, с помощью метода upper(), возводим все символы в нашем сообщении в верхний регистр, чтобы у нас не было ошибок. Потом создаем просто пустую переменную itog, куда мы буем выводить зашифрованное сообщение. Для этого пишем следующее:
smeshenie = int(input('Шаг шифровки: ')) #Создаем переменную с шагом шифровки message = input("Сообщение для шифровки: ").upper() #создаем переменнную, куда запишем наше сообщение itog = '' #создаем переменную для вывода итогового сообщения
Итак, теперь переходим к самому алгоритму шифровки. Первым делом создаем цикл for , где мы определим место букв, задействованных в сообщении, в нашем списке alfavit, после чего определяем их новые места (далее я постараюсь насытить код с пояснениями):
for i in message: mesto = alfavit.find(i) #Вычисляем места символов в списке new_mesto = mesto + smeshenie #Сдвигаем символы на указанный в переменной smeshenie шаг
Далее, мы создаем внутри нашего цикла условие if , в нем мы записываем в список itog мы записываем наше сообщение уже в зашифрованном виде и выводим его:
for i in message: mesto = alfavit.find(i) new_mesto = mesto + smeshenie if i in alfavit: itog += alfavit[new_mesto] # Задаем значения в итог else: itog += i print (itog)
Модернизация
Вот мы и написали программу, однако она имеет очень большой недостаток: «При использовании последних букв(русских), программа выведет вам английские буквы. Давайте это исправим.
Для начала создадим переменную lang, в которой будем задавать язык нашего шифра, а так же разделим английский и русский алфавиты.
alfavit_EU = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ' alfavit_RU = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ' smeshenie = int(input('Шаг шифровки: ')) message = input("Сообщение для шифровки: ").upper() itog = '' lang = input('Выберите язык RU/EU: ') #Добавляем возможность выбора языка
Теперь нам надо создать условие, которое проверит выбранный язык и применит его, то есть обратится к нужному нам алфавиту. Для этого пишем само условие и добавляем алгоритм шифрования, с помощью которого будет выполнено шифрование:
if lang == 'RU': for i in message: mesto = alfavit_RU.find(i) # Алгоритм для шифрования сообщения на русском new_mesto = mesto + smeshenie if i in alfavit_RU: itog += alfavit_RU[new_mesto] else: itog += i else: for i in message: mesto = alfavit_EU.find(i) # Алгоритм для шифрования сообщения на английском new_mesto = mesto + smeshenie if i in alfavit_EU: itog += alfavit_EU[new_mesto] else: itog += i
Дешифровка сообщения
Возможно это прозвучит несколько смешно, но мы смогли только зашифровать сообщение, а насчет его дешифровки мы особо не задумывались, но теперь дело дошло и до неё.
По сути, дешифровка — это алгоритм обратный шифровке. Давайте немного переделаем наш код (итоговый вид вы можете увидеть выше).
Для начала, я предлагаю сделать «косметическую» часть нашей переделки. Для этого перемещаемся в самое начало кода:
alfavit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ' smeshenie = int(input('Шаг шифровки: ')) message = input("Сообщение для ДЕшифровки: ").upper() #заменяем слово шифровка, на дешифровка itog = ''
Остальное можно оставить так же, но если у вас есть желание, то можете поменять названия переменных.
По большому счету, самые ‘большие’ изменения у нас произойдут в той части кода, где у нас находится алгоритм, где нам нужно просто поменять знак «+» на знак «-«. Итак, переходим к самому циклу:
if lang == 'RU': for i in message: mesto = alfavit_RU.find(i) new_mesto = mesto + smeshenie # Меняем знак + на знак - if i in alfavit_RU: itog += alfavit_RU[new_mesto] else: itog += i else: for i in message: mesto = alfavit_EU.find(i) # Меняем знак + на знак - new_mesto = mesto + smeshenie if i in alfavit_EU: itog += alfavit_EU[new_mesto] else: itog += i
Итоговый вид программы
Итак, вот мы и написали простейшую программу для шифрования методом Цезаря. Ниже я размещу общий вид программы без моих комментариев, чтобы вы еще раз смогли сравнить свою программу с моей:
alfavit_EU = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ' alfavit_RU = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ' smeshenie = int(input('Шаг шифровки: ')) message = input("Сообщение для ДЕшифровки: ").upper() itog = '' lang = input('Выберите язык RU/EU: ') if lang == 'RU': for i in message: mesto = alfavit_RU.find(i) new_mesto = mesto + smeshenie if i in alfavit_RU: itog += alfavit_RU[new_mesto] else: itog += i else: for i in message: mesto = alfavit_EU.find(i) new_mesto = mesto + smeshenie if i in alfavit_EU: itog += alfavit_EU[new_mesto] else: itog += i print (itog)
Итог
Вы успешно написали алгоритм шифровки и дешифровки сообщения на Python с помощью метода Цезаря. В следующей статье мы с вами рассмотрим Шифр Виженера, а также разберем его реализацию на Python, а пока я предлагаю вам написать в комментариях варианты модернизации программы(код или просо предложения и пожелания). Я обязательно учту ваше мнение.
- Python
- Программирование
Шифр Цезаря¶
Шифр Цезаря — это вид шифра подстановки, в котором каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите. Например, в шифре со сдвигом вправо на 3, A была бы заменена на D, B станет E, и так далее.
Для кодирования одного символа используется формула:
encoded_symbol = first + (symbol — first + key) % (last — first + 1)
- encoded_symbol — код зашифрованного символа
- symbol — код исходного символа
- key — ключ шифрования
- first — код первого символа алфавита
- last — код последнего символа алфавита.
Для преобразования символа в код и обратно используются функции:
Возвращает код символа с .
Возвращает символ, соответствующий коду i .
Задание¶
Каждая задача — отдельный этап реализации приложения для шифрования.
- Напишите функцию encode_symbol . Функция принимает символ и число, на которое его нужно сдвинуть, а также первую и последнюю буквы алфавита.
- Используя функцию из предыдущего задания, доработайте программу, чтобы она могла шифровать строки, введённые пользователем. Для удобства можно написать функцию encode_str . Функция принимает строку и ключ шифрования и возвращает зашифрованную строку.
- Добавьте возможность шифрования текстовых файлов. Для этого напишите функцию encode_file(input_file_path, output_file_path, key) .
- Напишите для приложения графический интерфейс с помощью easygui . Для открытия шифруемого файла используйте функцию easygui.fileopenbox(msg=None, title=None) . Для сохранения зашифрованного файла используйте easygui.filesavebox(msg=None, title=None) . Для ввода ключа — easygui.integerbox(msg=»», title=» «) .
© Copyright Revision d00c0df4 .
Built with Sphinx using a theme provided by Read the Docs.
Read the Docs v: latest
Versions latest Downloads html On Read the Docs Project Home Builds Free document hosting provided by Read the Docs.
Шифр Цезаря в Python – руководство по шифрованию
В этом руководстве мы рассмотрим один из методов шифрования в Python, называемый Caesar Cipher. Это часть криптографии.
Вступление
В этом методе каждый символ заменяется буквой с определенной фиксированной числовой позицией, которая находится после или перед буквой. Например, буква B заменяется на стоящую двумя позициями дальше D. D становится F и так далее. Этот метод назван в честь Юлия Цезаря, который использовал его для общения с официальными лицами.
Для реализации шифра Цезаря в Python используется алгоритм. Давайте в нем разберемся.
Особенность алгоритма шифрования Цезаря
Этот алгоритм состоит из нескольких функций, которые приведены ниже.
- Метод довольно прост в применении.
- Каждый текст заменяется фиксированным номером позиции вниз или вверх по алфавиту.
- Это простой тип заменяющего шифра.
Для определения каждой последней части текста, который был перемещен вниз, требуется целочисленное значение. Это целочисленное значение также известно как сдвиг.
Мы можем представить эту концепцию с помощью модульной арифметики, сначала преобразовав букву в числа в соответствии со схемой: A = 0, B = 1, C = 2, D = 3 …… .. Z = 25.
Следующая математическая формула может использоваться для сдвига буквы n.
Как расшифровать?
Расшифровка такая же, как и шифрование. Мы можем создать функцию, которая выполнит сдвиг по противоположному пути, чтобы расшифровать исходный текст. Однако мы можем использовать циклическое свойство шифра под модулем.
Эту же функцию можно использовать для расшифровки. Вместо этого мы изменим значение сдвига так, чтобы сдвиг = 26 – сдвиг.

Давайте разберемся в следующем примере –
def encypt_func(txt, s): result = "" # transverse the plain txt for i in range(len(txt)): char = txt[i] # encypt_func uppercase characters in plain txt if(char.isupper()): result += chr((ord(char) + s - 64) % 26 + 65) # encypt_func lowercase characters in plain txt else: result += chr((ord(char) + s - 96) % 26 + 97) return result # check the above function txt = "CEASER CIPHER EXAMPLE" s = 4 print("Plain txt : " + txt) print("Shift pattern : " + str(s)) print("Cipher: " + encypt_func(txt, s))
Plain txt : CEASER CIPHER EXAMPLE Shift pattern : 4 Cipher: HJFXJWsHNUMJWsJCFRUQJ
Приведенный выше код проходил символ за раз. Он передавал каждый символ по правилу в зависимости от процедуры шифрования и дешифрования текста.
Мы определили несколько конкретных наборов позиций, которые генерируют зашифрованный текст.
Нарушение алгоритма шифрования Цезаря
Взломать зашифрованный текст можно разными способами. Один из способов – это метод грубой силы, который включает в себя проверку всех возможных ключей дешифрования. Этот прием не такой сложный и не требует больших усилий.
msg = 'rGMTLIVrHIQSGIEWIVGIEWIV' #encrypted msg LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' for k in range(len(LETTERS)): transformation = '' for s in msg: if s in LETTERS: n = LETTERS.find(s) n = n - k if n < 0: n = n + len(LETTERS) transformation = transformation + LETTERS[n] else: transformation = transformation + s print('Hacking k #%s: %s' %(k, transformation))
Hacking k #25: rHNUMJWrIJRTHJFXJWHJFXJW
Транспонирующий шифр
Алгоритм шифрования транспонирования – это метод, при котором алфавитный порядок в открытом тексте перестраивается для формирования зашифрованного текста. Этот алгоритм не поддерживает настоящие текстовые алфавиты.
Давайте разберемся с этим алгоритмом на примере.
Мы возьмем простой пример под названием столбчатый шифр транспозиции, в котором мы пишем каждый символ текста по горизонтали с указанной шириной алфавита. Вертикально написанные тексты являются зашифрованными, что создает совершенно непохожий на зашифрованный текст.
Давайте возьмем простой текст и применим технику простого столбчатого транспонирования, как показано ниже.

Мы разместили простой текст по горизонтали, и зашифрованный текст создается с вертикальным форматом: hotnejpt.lao.lvi. Чтобы расшифровать это, получатель должен использовать ту же таблицу для расшифровки текста.
def split_len(sequence, length): return [sequence[i:i + length] for i in range(0, len(sequence), length)] def encode(k, plaintxt): order = < int(val): n for n, val in enumerate(k) >ciphertext = '' for index in sorted(order.ks()): for part in split_len(plaintxt, len(k)): try:ciphertext += part[order[index]] except IndexError: continue return ciphertext print(encode('3214', 'HELLO'))
В приведенном выше коде мы создали функцию с именем split_len(), которая выдавала текстовый символ, размещенный в формате столбцов или строк.
Метод encode() создал зашифрованный текст с ключом, определяющим количество столбцов, и мы распечатали каждый зашифрованный текст, прочитав каждый столбец.
Примечание. Техника транспонирования призвана значительно улучшить криптобезопасность. Криптоаналитики замечают, что повторное шифрование зашифрованного текста с использованием того же шифра транспозиции показывает лучшую безопасность.
Шифр Цезаря

Шифр Цезаря — это вид шифра подстановки, в котором каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите.
Шифр назван в честь римского полководца Гая Юлия Цезаря, использовавшего его для секретной переписки со своими генералами.
Например, в шифре со сдвигом вправо на 3, A была бы заменена на D, B станет E, Z станет C, и так далее.
Алгоритм шифрования можно выразить следующими формулами:
y = (x + k) mod n
x = (y - k) mod n
где x — символ открытого текста, y — символ шифрованного текста, n — мощность алфавита, а k — ключ.
Напишем программу на языке программирования Python которая использует шифр Цезаря.
Для начала создадим строку со всеми буквами русского алфавита. Используя эту строку мы будем находить порядковый номер буквы из нашего сообщения, чтобы сделать смещение для шифрования.
alphabet = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
Затем запросим ввод строки которую будем шифровать и ключ для шифрования.
message = input('Введите строку: ').lower() key = int(input('Введите ключ: '))
В переменной message будем хранить исходное сообщение, которое хотим зашифровать. В key будет храниться число, секретный ключ сдвига нашего алфавита.
Для удобства шифрования все введенные символы преобразуем в строчный регистр используя при вводе метод .lower(). При вводе ключа преобразуем введенный символ в целое число используя функцию int().
encrypted = ''
Так же создадим пустую переменную encrypted для хранения зашифрованного сообщения.
Используя цикл for будем перебирать наше исходное сообщение, чтобы получить по каждой букве из фразы.
for letter in message:
Цикл на каждой итерации будет получать в переменную letter по одному символу из сообщения message. Затем мы проверим, является ли полученный символ буквой.
if letter in alphabet:
Для упрощения мы будем шифровать только буквы русского алфавита, символы препинания и пробелы будем оставлять без изменения. Для этого проверим полученный символ на вхождение в нашу строку с алфавитом используя оператор in. Если искомый символ будет буквой, то in вернет True, если любым другим символом, то получим False.
Если символ входит в наш алфавит, то сделаем следующее. Методом .find() найдем позицию буквы из сообщения в нашем алфавите и запишем в переменную t. Затем вычислим новое значение с учетом смещения на значение нашего ключа и запишем в переменную new_key. Добавим в строку encrypted букву с индексом new_key.
t = alphabet.find(letter) new_key = (t + key) % len(alphabet) encrypted += alphabet[new_key]
Иначе, если символ из исходной строки не найден в строке с алфавитом, просто добавим его в строку encrypted.
else: encrypted += letter print('Зашифрованное сообщение:', encrypted)
И выведем строку encrypted с нашим зашифрованным сообщением.
Теперь соберем все в цельную программу.
alphabet = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя' message = input('Введите строку: ').lower() key = int(input('Введите ключ: ')) encrypted = '' for letter in message: if letter in alphabet: t = alphabet.find(letter) new_key = (t + key) % len(alphabet) encrypted += alphabet[new_key] else: encrypted += letter print('Зашифрованное сообщение:', encrypted)
Чтобы расшифровать сообщение достаточно в нашей программе в строке, где мы вычисляем значение нового символа от его значения отнять значение ключа.
new_key = (t - key) % len(alphabet)
Чтобы зашифровать сообщение со сдвигом влево достаточно указать отрицательное значение ключа.
Как мы видим, что наши алгоритмы шифрования и дешифрования отличаются лишь тем, как мы находим новое значение смещения, либо складывая позицию символа с ключом или отнимая. Напишем универсальную программу, которая будет выполнять оба действия.
Для начала создадим меню, в котором будем выбирать операцию: шифрование или дешифрование. А чтобы иметь возможность выполнять эти действия многократно, поместим все в бесконечный цикл while.
while True:
Выведем сообщение для пользователя, чтобы он мог выбрать нужную ему операцию. Затем в переменную menu поместим ответ пользователя. Так же ответ приведем к нижнему регистру методом .lower(), чтобы не было разницы каким регистром буквы задавать выполняемую операцию.
Проверим условие, если пользователь выбрал В – выход, кто прервем наш цикл командой break. Иначе, если пользователь ошибочно ввел любой символ кроме Ш и Р запустим наш цикл заново командой continue, все команды и операции ниже будут проигнорированы.
print('Введите Ш чтобы зашифровать сообщение, Р чтобы расшифровать и В чтобы выйти') menu = input('>>> ').lower() if menu == 'в': break elif not (menu == 'ш' or menu == 'р'): continue
Проверим условием, если пользователь решил расшифровать сообщение, тогда значение ключа key умножим на -1, чтобы оно стало противоположным по знаку.
if menu == 'р': key *= -1
Далее идет алгоритм разобранный нами ранее. Попробовать зашифровать или расшифровать свое сообщение алгоритмом Цезаря можно в блоке ниже.
