Шифр Цезаря

Дата: 28th Март 2011. Автор: Maxsbelt. Рубрика: C#, Java, Алгоритмы, ООП, Шифрование

Одним из древнейших шифров является шифр Цезаря. Этот шифр назван в честь римского императора Гая Юлия Цезаря, использовавшего его для секретной переписки со своими генералами. Идея данного шифрования заключается в замене всех букв послания на буквы, находящиеся на n позиций от текущей в алфавите. Наглядно этот процесс можно изобразить следующим образом:

 

Шифрование методом Цезаря

Шифрование методом Цезаря

К слову сказать, Цезарь использовал этот шифр со сдвигом 3. Что ж, рассмотрим теперь математическую модель данного шифра. Она не представляет ничего сложного:

Мат модель шифра Цезаря 1Мат модель шифра Цезаря 2

Здесь X представляет собой позицию исходной буквы в алфавите, K — сдвиг, которым шифруется сообщение, n — количество букв в алфавите и Y — положение зашифрованной буквы в алфавите. Данная процедура выполняется для каждой буквы послания. Переходим к реализации данного алгоритма шифрования. Весь процесс реализации алгоритма можно разбить на 3 части:

  1. Написание класса Alphabet, предоставляющего различные алфавиты.
  2. Написание класса Caesar, предоставляющего методы шифрования и дешифрования.
  3. Проверка работы на тестовых данных.

Итак, приступим.

Класс Alphabet

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

Пример некорректной работы программы по шифрованию методом Цезаря

С чем связано то, что все символы, не входящие в алфавит заменились на буквы я? Вернемся к математической форме и остановим наше внимание на X — позицию исходной буквы в алфавите. А в нашем алфавите нет ни заглавных букв, ни пробелов, ни знаков препинания. Следовательно, определить положение данных символов в алфавите попросту невозможно! В таком случае, если вы пользуетесь методом IndexOf класса String, то получаете -1. Можно конечно запретить пользователю использовать иные символы или же удалять эти символы при считывании, но в это случае либо пользователь будет очень зол, что может использовать только строчные буквы, либо послание при расшифровке может получиться обрывочным. Во-вторых, все-таки мы живем в развивающимся мире, где программы должны быть гибкими (кроссплатформенными, мультиязычными, настраиваемыми), на случай, если вы например решили зашифровать сообщение на английском. Довольно слов, давайте рассмотрим реализацию данного класса:

Класс Alphabet на C#

Класс Alphabet на Java

Как вы можете заметить, это статический класс, членами которого являются свойства, доступные только для чтения. Каждое свойство содержит в себе некоторый алфавит или другой однотипный набор символов. Данный данный класс довольно просто расширяется. Итак, этот этап закончен.

Класс Ceasar

Теперь давайте обсудим из чего должен состоять класс Caesar предоставляющий шифрование методом цезаря. Очевидно, что у данного класса должно быть два метода: зашифровать и дешифровать, соответственно. На вход первого метода подаются исходный текст и величина сдвига, на которую будет производится шифрование. На вход второго — зашифрованный текст и величина сдвига, на которую текст был зашифрован. Очевидно, для того, чтобы шифрование-дешифрование произошло успешно, необходимо, что бы величина сдвига при дешифровании была такой же как и при шифровании. Сами методы представляют собой простую реализацию математической модели для каждой буквы послания (шифра). Это реализовано в форме цикла.  Вот так выглядит готовый класс:

Класс Caesar на C#

Класс Caesar на Java

Следующее изображение дает отличное пояснение, что есть что:

Шифр Цезаря

Осталось только пояснить условие, находящееся в методе дешифрования. Дело в том, что положение буквы зашифрованного послания в алфавите может оказаться гораздо меньше величины сдвига. Таким образом, величина, представленная в математической модели, как Y — K может принимать сколь угодно большое отрицательное значение. Однако, если значение отрицательное, то мы можем уверенно сказать, что его абсолютная величина обозначает положение буквы в алфавите относительно его конца. Следовательно нам только остается прибавить величину алфавите и мы получим положение необходимой буквы.

Тестовый запуск

Теперь нам только проверить работу нашего класса. Что ж, прописываем следующий код в главном методе программы:

Тестирование на C#

Тестирование на Java

Запускаем и убеждаемся, что программа работает корректно. Правда, все равно можно найти такой символ, который не попадет в наш алфавит, т. к. существует еще множество символов, которые мы не учли. Но это просто сделать, добавив в классе Alphabet метод, который будет возвращать все возможные символы. Я этого не делаю, т. к. считаю, что это не относится к теме данной статьи, а для нормальной передачи сообщений достаточно и предоставленных алфавитов.

Выводы

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

Итак мы рассмотрели один из самых простейших методов шифрования: шифр Цезаря. Следует сказать, что на практике данный метод не используется уже очень давно в силу следующих причин:

  • Легко взламывается методом анализа по частоте;
  • Легко взламывается методом тотального перебора.

Однако его модификация еще недавно активно использовалась на практике. Это шифр Виженера. О нем и пойдет речь в нашей следующей статье. Спасибо за внимание и не стесняйтесь оставлять комментарии, так как именно они заставляют совершенствовать контент и добиваться полного понимания материала.

  1. coder13:

    Статья класс! Хочу почитать продолжение!

  2. andriy9191:

    я чет не понял особо понял что например привет то оно шифруется рсйгеу типа здвиг всех букв на одно вправо …… я правильно понял ?

  3. Anna:

    Просто здорово! Очень красивый сайт, описано-объянено-разжовано и в рот положено! Спасиб огромное! Сама реализовывала программку шифратор-дешифратор на основе шифра Цезаря, но было приятно посмотреть на ваше исполнение..)

  4. Anna:

    Единственное, что некоторые спец символы оно не распознает, на и перенос каретки вместе табуляцией он не разбирает..

  5. Ксения:

    В классе Дешифратора есть лишние строчки, которые в принципе не нужны.)) Это условие нужно выкинуть, тк оно роли не играет и оставить вот так:

    public string getDecryption(string cipher, int position)
    {
    string text = «»;
    for (int i = 0; i < cipher.Length; i++)
    {
    text += alphabet[(alphabet.Length +
    (alphabet.IndexOf(cipher[i]) — position)) % alphabet.Length];
    }
    return text;
    }

    У меня лично работает без этого if ))) Хотя и не тестила эту прогу, но думаю, что ничего не поменяется.

  6. Илья:

    Проверил программу, к сожалению заметил, что одну ошибочку.
    Если в тексте выбрать написать, например, автор, сдвиг сделать минус 2, то программа закроется с ошибкой, хотя должно получиться юармо

    • Спасибо за обнаруженную ошибку. Действительно, будет выброшено исключение, т. к. значение выражения (alphabet.IndexOf(text[i]) + position) % alphabet.Length будет отрицательным. Проблема решается очень просто. Что бы индекс (это выражение) не принимал отрицательное значение, необходимо в скобках прибавить размер алфавита (т. е. (alphabet.Length + alphabet.IndexOf(text[i]) + position) % alphabet.Length). Текст статьи с соответствующими корректировками будет обновлен в ближайшее время.

  7. Gorets:

    еще одна поправочка кода, так как это шифрование и это процесс не из быстрых, относительно, то код существенно ускорит использование вместо String — StringBilder, а вместо += — .append();

    PS подскажите как называется плагин комментариев на сайте