Невзламываемый шифр за 4 строчки кода.
На прошлой неделе мы показали вам невзламываемый шифр Вернама. Теперь напишем собственную реализацию этого шифра на JavaScript.
Принцип работы шифра Вернама
- Нам нужно исходное сообщение и ключ шифрования. Ключ должен быть таким же по размеру, как исходное сообщение, или больше.
- Каждый бит исходного сообщения сопоставляется с битом ключа шифрования. Производится специальная операция XOR, которая отвечает за кодирование
- На выходе получается зашифрованный текст, расшифровать который можно только имея под рукой секретный ключ.
Алгоритм
Сделаем классическую реализацию шифра Вернама:
- Спрашиваем текст исходного сообщения и ключ.
- Если ключ короче сообщения — говорим об этом и сразу генерируем новый ключ нужной длины.
- Шифруем сообщение и выводим результат в консоль.
Единственное отличие нашего алгоритма от классического — принудительная проверка длины ключа. Чтобы шифр нельзя было взломать, ключ должен быть как минимум той же длины, что и исходное сообщение.
Подготовка
Заведём нужные переменные:
Ещё нам понадобится функция, которая возвращает случайное число в указанном диапазоне. Её мы будем использовать для создания нового ключа, если ключ пользователя будет слишком короткий.
Последнее, что нам осталось сделать, — запросить у пользователя сообщение, которое будем шифровать, и ключ:
Проверяем ключ
Теперь, когда у нас есть сообщение и ключ, проверим, хватит ли длины ключа или нет. Если не хватит — выведем сообщение и сгенерируем новый ключ.
👉 Обратите внимание на второй параметр в функции, которая возвращает случайное значение. В нашем примере мы взяли число 66535, потому что в первом регистре кодировки Unicode 66536 символов — от 0 до 66535, а JavaScript возвращает коды символов строки как раз в Unicode. Попробуйте поставить число поменьше, например 9999, и посмотрите, как меняются символы в ключе и в готовой шифровке.
Само генерирование ключа очень простое: мы берём случайное число, переводим его в строку функцией String.fromCharCode() и добавляем результат к строке с ключом.
Шифруем сообщение
В основе алгоритма Вернама лежит XOR — исключающее ИЛИ. Его особенность в том, что если его применить к зашифрованному тексту снова с тем же ключом, то мы получим расшифрованное исходное сообщение. Это значит, что этим алгоритмом мы можем и шифровать, и расшифровывать.
Логика работы алгоритма такая:
- Берём очередной символ сообщения и ключа.
- Получаем их числовой код.
- Применяем к ним XOR (в JavaScript эта операция обозначается крышечкой: ^) и получаем новое число.
- Это число переводим в символ и прибавляем к строке с зашифрованным текстом.
Если хотите проверить, как работает алгоритм, расшифруйте это сообщение
ඣߎಃ␗ᯄ᧕Ⴛඥ¢.ᵾ௧ᓐेࠬ௦ዐ⒦ਐ►༈ᕄ
вот этим ключом:
়Ύࢻ‥ᶗ႗අӯ࿓Аᵞ࿑႓ഇ࿖᛫⒆ชↄ଼ᕥ
Это может показаться удивительным, но в нашем примере длина ключа и сообщения совпадают. Это связано с особенностью кодировки Unicode — один код может одновременно кодировать несколько визуальных символов, поэтому длина кажется разной.
Что дальше
В нашей реализации шифра есть несколько минусов:
- в настоящей криптографии не используют функцию Math.random() в таком явном виде. Есть методы подбора и взлома этой псевдослучайной последовательности, по которой можно восстановить, казалось бы, случайные символы.
- Если мы хотим отправить длинное сообщение, то нам нужно его и ключ копировать и вставлять в поле ввода. Намного проще сделать чтение из файла — и сообщения, и ключа.
- Чтобы пользоваться этим алгоритмом, нужно постоянно передавать ключ, а это — проблема. Намного проще сделать так: сгенерировать очень длинную случайную последовательность и использовать её части при каждом шифровании или расшифровке. А использованные фрагменты сразу удалять, чтобы не снижать стойкость шифра.
- И да, у нас нет в явном виде функции расшифровки 🙂
Когда-нибудь мы соберёмся с силами и исправим все три пункта.