Недавно я обрадовался, когда прочитал новость о том, что британский математик Алан Тьюринг представит новую банкноту Банка Англии за 50 фунтов стерлингов . Тьюринг занимает особое место в сердцах компьютерных ботаников для эффективного написания чертежей для компьютера. Он также помог взломать общеизвестно сложный военно-морской код загадки, используемый нацистскими подводными лодками во Второй мировой войне. В честь этого я решил создать краткое руководство по созданию машины шифрования с использованием навыков JavaScript, которые описаны в моей книге « JavaScript новичок для ниндзя» .
Шифр, который мы будем использовать, — это шифр Цезаря, названный в честь римского императора Юлия Цезаря. Это один из самых простых шифров, который существует и просто сдвигает каждую букву на определенное количество мест. Например, фраза «Hello World» станет «KHOOR ZRUOG» с использованием сдвига 3 (который, как полагают, использовал Юлий Цезарь).
Вы можете увидеть пример готового кода здесь . Поиграйте в написание некоторых секретных сообщений, чтобы понять, как это работает.
Для начала запустите ваш любимый текстовый редактор и сохраните следующее как caesar.html
:
<!doctype html> <html lang='en'> <head> <meta charset='utf-8'> <title>Caesar Cipher</title> </head> <body> <h1>Caesar Cipher</h1> <form> <label>Plaintext:</label> <textarea name='plaintext'>Top Secret</textarea> <label>Shift:</label> <input type='number' name='shift' value='5' min='1' max='26'> <input type='submit' value='encrypt'> </form> <h2>Output</h2> <div id='output'> </div> <script src='main.js'></script> </body> </html>
Это стандартная HTML-страница, которая содержит форму с текстовой областью для ввода нашего сообщения. Также имеется поле ввода с атрибутом типа number
которое большинство браузеров будет отображать с помощью шаговых стрелок, что позволяет пользователям увеличивать или уменьшать значение. Мы также можем ограничить значения от 1 до 26 и установить значение по умолчанию 3 (в честь Цезаря). Внизу также есть пустой элемент div
с id
output
который мы будем использовать для отображения зашифрованного сообщения.
Формы описаны в главе 8 книги.
Теперь давайте начнем и напишем код JavaScript для шифрования!
Создайте файл с именем main.js
и сохраните его в той же папке, что и файл caesar.html
.
Мы начнем с создания глобальной переменной с названием alphabet
. Это будет массив, в котором хранятся все буквы алфавита:
const alphabet = [ 'A','B','C','D','E','F', 'G','H','I','J','K','L', 'M','N','O','P','Q','R', 'S','T','U','V','W','X', 'Y','Z' ];
Этот массив будет полезен для определения местоположения букв в алфавите и их перемещения по заданному числу мест. Это также означает, что мы можем использовать альтернативные алфавиты, просто обновляя эту переменную.
Переменные описаны в главе 1 книги, а массивы — в главе 3.
Теперь нам нужен способ доступа к различным частям страницы. Для этого мы будем использовать объектную модель документа или DOM:
const form = document.forms[0]; const output = document.getElementById('output');
Этот код использует глобальные переменные для ссылки на элемент формы и элемент div
который будет отображать зашифрованное сообщение. Это облегчит нам обращение к этим элементам в коде позже.
DOM рассматривается в главе 6 книги.
Когда кто-то вводит сообщение, которое он хочет зашифровать, он нажимает кнопку отправки, и оно отображает зашифрованное сообщение. Нам нужно использовать обработчик событий, который будет срабатывать при нажатии кнопки отправки и давать нам доступ к тому, что было написано в textarea
.
form.addEventListener ('submit',event => { event.preventDefault(); output.innerHTML = [... form.plaintext.value ].map(char => encrypt(char)).join(''); } );
События освещены в главе 7 книги.
Внутри этого обработчика событий происходит довольно много, поэтому давайте более подробно рассмотрим каждую строку:
event.preventDefault();
Это используется для предотвращения поведения по умолчанию при отправке формы, так как мы не хотим, чтобы она была отправлена на сервер.
output.innerHTML = [... form.plaintext.value ].map(char => encrypt(char)).join('');
Эта строка обновляет свойство innerHTML
выходного элемента div
с зашифрованным сообщением. К сообщению, содержащемуся в textarea
можно получить доступ с помощью form.plaintext.value
. Это строка, содержащая различные символы, которые были введены пользователем. Мы преобразуем эту строку в зашифрованное сообщение, объединяя несколько методов в цепочку.
Прежде всего, мы используем оператор распространения ...
чтобы превратить строку в массив. Затем мы используем метод map
для итерации каждого символа и применяем функцию encrypt для преобразования его в другой символ.
Наконец, мы используем метод join('')
для преобразования массива обратно в строку, которая может быть отображена в выходном div.
Нам осталось только написать функцию encrypt()
которая используется методом map в обработчике событий выше. Вот код, который будет применять шифр Цезаря:
function encrypt(char) { const shift = Number(form.shift.value); if (alphabet.includes(char.toUpperCase())) { const position = alphabet.indexOf(char.toUpperCase()); const newPosition = (position + shift)%26; return alphabet[newPosition] } else { return char } }
Эта функция принимает символ в качестве аргумента, а затем возвращает зашифрованный символ.
Функции описаны в главе 4 книги.
Он начинается с присвоения значения поля ввода сдвига из формы переменной shift
. Это можно получить с помощью кода form.shift.value
. Все значения, введенные в форму, передаются в виде строк, поэтому нам нужно изменить тип этой переменной на число с помощью функции Number()
. Это позволит нам затем выполнять арифметические и другие числовые методы.
Далее у нас есть условный оператор, который проверяет, является ли аргумент частью алфавита. При этом используется метод массива include includes()
, который возвращает значение true, если аргумент находится в массиве. Обратите внимание, что мы также используем метод toUpperCase()
чтобы гарантировать, что символ является заглавной буквой, так как все буквы в массиве алфавита являются заглавными.
Если символ находится в массиве alphabet
, мы можем продолжить и зашифровать его. Если это не так, тогда мы просто возвращаем символ как есть (это позволяет нам работать с пробелами и знаками препинания).
Код шифрования возвращает элемент из массива alphabet
:
{ const position = alphabet.indexOf(char.toUpperCase()); const newPosition = (position + shift)%26; return alphabet[newPosition] }
Прежде всего, мы используем метод массива indexOf()
чтобы узнать индекс символа в alphabet
массиве. Это хранится в переменной позиции. Далее мы находим позицию зашифрованного символа, добавляя значение shift
к индексу. Мы также используем модульный оператор %
, чтобы использовать арифметику ‘mod 26’. Это означает, что любое значение, превышающее 25, будет «возвращаться назад» к началу массива, 26 — к 0, 27 к 1, 28 к 2 и т. Д. Это означает, что буква «X» со сдвигом 3 вернусь к началу алфавита и сопоставим с «A». Это значение хранится в переменной newPosition
.
Затем мы просто возвращаем символ в массиве алфавита, который соответствует этой новой позиции, предоставляя переменную newPosition
в качестве индекса массива alphabet
.
И это весь код, который нам нужен! Попробуйте ввести сообщение в текстовое поле, нажмите «отправить», и вы увидите, что ваше секретное сообщение появилось ниже.
Прелесть использования отдельной функции encrypt()
состоит в том, что мы можем обновить ее, чтобы в любой момент использовать другой метод шифрования без необходимости изменения какой-либо другой части кода.
Шифр Цезаря, вероятно, является одним из самых основных шифров, хотя он был основой кода Enigma. Возможно, вы могли бы поэкспериментировать с использованием различных шифров в функции encrypt()
и, возможно, даже обновить их, чтобы имитировать машину Enigma?