Эльфы серьезно относятся к кибербезопасности. Как и любая мода, она добралась и до детей. Одной из любимых игр маленьких эльфов является написание зашифрованных сообщений в школьные часы. Некоторые из них нашли страницу Шифра Цезаря в Википедии и теперь уже не останавливаются.
Головоломка: Секретные сообщения ✉️
Сегодняшняя проблема, выпуск 22 Адвент-календаря разработчиков 🎅 снова о паролях, кодах и способах их расшифровки. И переходим к классике: шифру Цезаря:
В криптографии шифр Цезаря, также известный как шифр Цезаря, шифр сдвига, код Цезаря или сдвиг Цезаря, является одним из самых простых и широко известных методов шифрования. Это тип шифра замены, в котором каждая буква в открытом тексте заменяется буквой на некоторое фиксированное количество позиций в алфавите.
Проще говоря, мы заменяем каждую букву той, которая следует за ней в x
позициях. Например, с shift = 1
буква A
становится B
. С shift = 2
буква A
становится C
. С shift = 3
буква A
становится D
. И так далее.
В Интернете есть несколько решений, но почти все они включают в себя явное написание алфавита плюс некоторые if
условия в сочетании с for
циклами. Мое решение задачи отличается и начинается с формулы
f(x) = x + k(mod. m)
С m = number of letters of the alphabet
и k = shift
.
Исходя из этой формулы, я могу получить функцию JavaScript, подобную этой:
Проблема в том, чтобы понять, как передать буквы. Наиболее распространенный метод включает преобразование символа в соответствующий числовой код. Затем мы добавляем сдвиг и конвертируем его обратно в символы.
Я решил сделать что-то другое. Ведь шифр Цезаря — это не что иное, как словарь, в котором каждая буква соответствует другой. Затем я могу создать объект JavaScript с различными буквами в качестве ключей.
Сначала я создаю два массива, один для прописных букв, другой для строчных:
Затем мне нужна функция для вычисления модуля числа:
Наконец-то что-то, что создает соответствие между ключом и решением.
Эта функция принимает на вход массив, содержащий алфавит, и возвращает объект с кодом шифрования.
Для каждого элемента массива, для каждой буквы алфавита вычисляется соответствующая зашифрованная буква. Длина алфавита определяется количеством элементов в массиве.
Чтобы упростить разрешение, я создаю вспомогательную функцию для обработки словаря как прописных, так и строчных букв.
Таким образом, я получаю такой объект:
Получив шифр, я могу перевести каждую букву:
Мы также можем игнорировать все неалфавитные символы очень простым способом: если соответствующий ключ не существует в шифре, то символ не преобразуется:
После создания всех различных функций поддержки решение короткое и простое:
В этом решении есть интересный аспект: та же самая функция, которая используется для расшифровки, также может быть использована для расшифровки. Просто используйте отрицательный сдвиг: таким образом буквы прокручиваются не вперед, а назад, что позволяет восстановить исходное сообщение.
Это полный код:
Решение Прашанта Ядава
Как я уже сказал в начале, в Интернете есть много решений этой проблемы. Прашант Ядав предлагает одни из самых распространенных.
Какие проблемы с этим подходом?
- этот код шифрует только с предопределенным сдвигом (в данном случае 13)
- работает только для строчных букв
- работает только со строками, которые не содержат пробелов или других символов, не содержащихся в переменной
decoded
- не расшифровывает сообщение
Его вторая идея более интересна:
Эта функция преобразует все буквы в верхний регистр, а затем заменяет их. Остается проблема обработки строчных букв. Для этого нужно изменить функцию:
Управление неалфавитными символами, включая пробелы, остается проблематичным.
Решение Мариана Ветеану
В Блоге Мариана Ветяну много интересных постов. Есть решение, как создать шифр Цезаря
Это решение работает, но мне не нравится иметь так много жестко запрограммированных значений. Но у него есть то преимущество, что не используются массивы или другие объекты. Как следующее решение.
Решение Эвана Хана
Эван Хан предлагает рабочее решение:
Однако это решение создает некоторые проблемы. Или, скорее, некоторые вещи, которые мне не нравятся. Во-первых, это наличие нескольких if
условий и for
цикла. Я все больше убеждаюсь, что они затрудняют чтение кода и затрудняют его сопровождение.
Во-вторых, алфавит для работы фиксируется в коде жестко заданными значениями. По возможности всегда лучше избегать ввода жестко запрограммированных значений. Наконец, если бы я захотел преобразовать эту функцию для использования другого набора символов, у меня возникли бы проблемы.
Но код работает.
Ну вот и все на сегодня. Очевидно, я предпочитаю решение, которое я предложил. Но самое замечательное в JavaScript и в программировании в целом то, что может быть несколько способов найти правильное решение. Часть удовольствия заключается в том, чтобы выяснить, какие пути возможны.
Спасибо за прочтение! Оставайтесь с нами, чтобы узнать больше.
Не пропустите мою следующую статью — подпишитесь на мой Список адресов электронной почты среднего уровня
Первоначально опубликовано на https://blog.stranianelli.com 23 декабря 2021 г.
Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку здесь.