Статьи

Как создать шифровальную машину с помощью JavaScript

Недавно я обрадовался, когда прочитал новость о том, что британский математик Алан Тьюринг представит новую банкноту Банка Англии за 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?