Найти тему
Журнал «Код»

Шифр Вернама на JavaScript

Оглавление

Невзламываемый шифр за 4 строчки кода.

На прошлой неделе мы показали вам невзламываемый шифр Вернама. Теперь напишем собственную реализацию этого шифра на JavaScript.

Принцип работы шифра Вернама

  1. Нам нужно исходное сообщение и ключ шифрования. Ключ должен быть таким же по размеру, как исходное сообщение, или больше.
  2. Каждый бит исходного сообщения сопоставляется с битом ключа шифрования. Производится специальная операция XOR, которая отвечает за кодирование
  3. На выходе получается зашифрованный текст, расшифровать который можно только имея под рукой секретный ключ.

Алгоритм

Сделаем классическую реализацию шифра Вернама:

  1. Спрашиваем текст исходного сообщения и ключ.
  2. Если ключ короче сообщения — говорим об этом и сразу генерируем новый ключ нужной длины.
  3. Шифруем сообщение и выводим результат в консоль.

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

Подготовка

Заведём нужные переменные:

Ещё нам понадобится функция, которая возвращает случайное число в указанном диапазоне. Её мы будем использовать для создания нового ключа, если ключ пользователя будет слишком короткий.

Последнее, что нам осталось сделать, — запросить у пользователя сообщение, которое будем шифровать, и ключ:

Проверяем ключ

Теперь, когда у нас есть сообщение и ключ, проверим, хватит ли длины ключа или нет. Если не хватит — выведем сообщение и сгенерируем новый ключ.

👉 Обратите внимание на второй параметр в функции, которая возвращает случайное значение. В нашем примере мы взяли число 66535, потому что в первом регистре кодировки Unicode 66536 символов — от 0 до 66535, а JavaScript возвращает коды символов строки как раз в Unicode. Попробуйте поставить число поменьше, например 9999, и посмотрите, как меняются символы в ключе и в готовой шифровке.

Само генерирование ключа очень простое: мы берём случайное число, переводим его в строку функцией String.fromCharCode() и добавляем результат к строке с ключом.

Шифруем сообщение

В основе алгоритма Вернама лежит XOR — исключающее ИЛИ. Его особенность в том, что если его применить к зашифрованному тексту снова с тем же ключом, то мы получим расшифрованное исходное сообщение. Это значит, что этим алгоритмом мы можем и шифровать, и расшифровывать.

Логика работы алгоритма такая:

  1. Берём очередной символ сообщения и ключа.
  2. Получаем их числовой код.
  3. Применяем к ним XOR (в JavaScript эта операция обозначается крышечкой: ^) и получаем новое число.
  4. Это число переводим в символ и прибавляем к строке с зашифрованным текстом.

Если хотите проверить, как работает алгоритм, расшифруйте это сообщение

ඣߎಃ␗ᯄ᧕Ⴛඥ¢஑.ᵾ௧ᓐेࠬ௦ዐ⒦ਐ►༈ᕄ

вот этим ключом:

়Ύࢻ‥῱ᶗ႗අӯ࿓Аᵞ࿑႓ഇ఑࿖᛫⒆ชↄ଼ᕥ

Это может показаться удивительным, но в нашем примере длина ключа и сообщения совпадают. Это связано с особенностью кодировки Unicode — один код может одновременно кодировать несколько визуальных символов, поэтому длина кажется разной.

Что дальше

В нашей реализации шифра есть несколько минусов:

  • в настоящей криптографии не используют функцию Math.random() в таком явном виде. Есть методы подбора и взлома этой псевдослучайной последовательности, по которой можно восстановить, казалось бы, случайные символы.
  • Если мы хотим отправить длинное сообщение, то нам нужно его и ключ копировать и вставлять в поле ввода. Намного проще сделать чтение из файла — и сообщения, и ключа.
  • Чтобы пользоваться этим алгоритмом, нужно постоянно передавать ключ, а это — проблема. Намного проще сделать так: сгенерировать очень длинную случайную последовательность и использовать её части при каждом шифровании или расшифровке. А использованные фрагменты сразу удалять, чтобы не снижать стойкость шифра.
  • И да, у нас нет в явном виде функции расшифровки 🙂

Когда-нибудь мы соберёмся с силами и исправим все три пункта.

Готовый код

Наука
7 млн интересуются