Включая немного истории, механическую теорию и примеры рабочего кода.

В этой статье рассматривается Advanced Encryption Standard (AES) в JavaScript. Статья обширна, включая основную историю, механику и примеры рабочего кода.

Вы можете свободно прокручивать вниз до кода, не читая остальную часть статьи, хотя я скажу, что изучение соответствующих шагов значительно улучшит ваше понимание!

Давай начнем.

Краткий урок истории по AES

Вы когда-нибудь слышали о Rijndael? Что ж, это не человек - это набор алгоритмов шифрования (но вы, конечно, это знали). В рамках Национального института стандартов и технологий (NIST) перед ведущими учеными и математиками была поставлена ​​задача разработать методы передачи данных, обеспечивающие целостность передачи данных.

Алгоритмы Rijndael были разработаны бельгийскими криптологами Винсентом Рейманом и Джоан Даемон - так или иначе, Rijman + Daemon = Rijndael.

Основные цели алгоритмов шифрования:

  1. Поддерживайте сопротивление всем известным атакам
  2. Скорость и производительность на различных вычислительных платформах
  3. Простота дизайна

В ноябре 2001 года министр торговли США одобрил алгоритмы Rijndael для легитимации в публикации федеральных стандартов обработки информации. Хотя с годами многие криптографические алгоритмы устарели, AES сохранила строгий стандарт, который обычно используется в промышленности, а также в государственной безопасности.

Учитывая, насколько мир изменился благодаря большим данным и машинному обучению, то, что AES по-прежнему является передовым стандартом шифрования, является впечатляющим достижением.

Понимание основных шагов по AES

Заявление об ограничении ответственности: многие из этих шагов сокращены и предназначены для реализации большой идеи. Если вам нужно математически строгое объяснение, в Википедии есть отличное объяснение по этой теме.

AES - это симметричный алгоритм, означающий, что вы можете как зашифровать, так и расшифровать информацию. AES состоит из 128-битных блоков данных, которые используются в качестве блочных шифров. Напомним, что биты - это отдельные единицы информации, обычно ноль или единица. Затем 128 бит группируются в 16 байтов (по 8 бит в каждом байте). Затем 16 байтов представляются в виде двумерного массива, также известного как матричное представление. Для AES это называется текущим «состоянием».

AES позволяет ключу иметь длину 128, 192 или 256 бит. Ключ - это просто случайно сгенерированное значение. Вы можете посвятить целую книгу тому, как случайным образом генерируются ключи, поэтому мы опустим детали.

Самый первый шаг - взять наше сообщение и преобразовать его в байтовое представление.

Открытый текст «Это секретное сообщение». будет представлен ниже стандартной байтовой кодировкой UTF-8. Это 25 символов, представленных 25 байтами.

54 68 69 73 20 69 73 20 61 20 73 65 63 72 65 74 20 6d 65 73 73 61 67 65 2e

Ключ шифрования также будет представлен в байтовом формате.

Алгоритм шифрования AES состоит из пяти основных этапов, перечисленных ниже.

  1. Расширение ключа - производное нашего секретного ключа, называемое ключами раунда, получается из ключа шифрования с использованием расписания ключей AES.
  2. Добавить ключ раунда - каждый байт матрицы комбинируется с байтом ключа раунда с помощью побитового xor.
  3. Замещающие байты - шаг замещения, на котором каждый байт заменяется другим в соответствии с таблицей поиска.
  4. Shift Rows - шаг транспонирования, при котором последние три строки состояния циклически сдвигаются на определенное количество шагов.
  5. Смешивание столбцов - операция смешивания, которая работает со столбцами матрицы, объединяя четыре байта в каждом столбце.

Первый шаг происходит только один раз при запуске алгоритма. AES требует отдельного 128-битного блока ключей раунда для каждого раунда плюс еще один.

Шаги со второго по пятый повторяются в течение нескольких раундов в зависимости от длины секретного ключа. Есть 10 раундов для 128-битных ключей, 12 раундов для 192-битных ключей и 14 раундов для ключей длиной 256 бит. В последнем раунде, независимо от размера ключа, шаг 5 пропускается, поскольку он не добавляет никакой случайности в вычисления (не спрашивайте меня, почему в этой части).

Это описывает, как AES работает на очень высоком уровне. Дальнейшие подробности по каждому шагу описаны ниже.

Если вы не знакомы с XOR: это побитовая операция «исключающее ИЛИ» между двумя наборами байтов. Если ТОЛЬКО один бит имеет значение 1 между сравнениями, то результирующий бит также имеет значение 1. В противном случае это значение 0. Например:

An example XOR operation
1 0 1 1 0 0 1 0
0 1 0 1 0 0 1 1 XOR
---------------
1 1 1 0 0 0 0 1 Result

Ключевое расширение

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

Учитывая наш секретный ключ шифрования, мы имеем его в матричной форме K с элементами от k (0,0) до k (3,3). Верхний индекс на диаграмме ниже показывает, в каком раунде мы находимся. Для первого раунда мы берем четвертый столбец ключевой матрицы с элементами от k (0,3) до k (3,3) и переворачиваем элемент k (0, 3) в нижнюю часть столбца (RotWord). Итак, наш результирующий столбец - это k (1,3), k (2,3), k (3,3), k (0,3).

Затем мы подставляем байты этого столбца из таблицы (SubWord, см. Замену байтов). У нас также есть таблица, называемая таблицей круглых констант (Rcon), которую мы будем выполнять XOR с ключевым столбцом. Наконец, мы выполняем операцию XOR с третьим столбцом слева, в данном случае содержащим от k (0,0) до k (3,0).

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

Этот процесс повторяется необходимое количество раундов.

Добавить круглый ключ

Сделайте вдох, потому что этот шаг легкий! Здесь мы берем ключ раунда, вычисленный на предыдущем шаге, и выполняем XOR с текущим блочным шифром. Это все!

Замещающие байты

Фух, легкий шаг! Все, что мы здесь делаем, это берем каждый отдельный блок в матрице состояний и подставляем его из таблицы. Учитывая 128-битный блочный шифр,

54 68 69 73 20 69 73 20 61 20 73 65 63 72 65 74 20 6d 65 73 73 61 67 65 2e

наш первый байт для замены будет 54. Согласно этой таблице, мы просто перейдем к строке 5 и столбцу 4, чтобы получить замену 4C.

Обоснование ориентации этой таблицы связано с некоторой вероятностной магией, которую мы пропустим. Мы бы заменили на этом шаге все 16 байтов нашей матрицы состояний.

Сдвиг рядов

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

Столбцы смешивания

На этом этапе мы используем небольшую матричную математику и арифметику по модулю. У нас есть матрица состояний A с элементами от a (0,0) до (3,3), и мы умножаем ее на нашу заданную матрицу, заполненную числами, предназначенными для того, чтобы все перемешать. Полученная матрица B будет окончательным результатом шага Mix Columns.

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

Реализация AES с использованием TypeScript и Crypto-JS

Хорошо, вот чего вы так долго ждали. Нет больше истории и теории, давайте перейдем к коду!

Начните новый проект Angular.

$ ng new aes-app

Удалите весь код шаблона из src / app / app.component.html. Вы можете просто поместить туда заполнитель, так как мы сосредоточимся на реализации сервиса. Мы будем выводить процесс на консоль. Я знаю, немного грязно, но мы просто сосредоточимся на AES.

Создайте новый сервис Angular и установите crypto-js.

$ ng generate service encryption
$ npm install crypto-js

Наша служба шифрования будет иметь следующий код:

После выполнения AES в байтовом формате мы должны преобразовать обратно в строку со стандартной кодировкой UTF-8 в строке 17.

Затем мы можем провести простой тест для вывода наших результатов в service.spec, включая:

Выполните наш тест и просмотрите шифрование AES в журнале консоли.

$ ng test --include='**/encryption.service.spec.ts'

Как видите, код очень прост! Вот почему я считаю, что стоит знать хотя бы базовую механику того, что происходит под капотом обычных библиотек шифрования. Библиотека crypto-js также включает возможный параметр для включения вектора инициализации (IV), хотя здесь он автоматически включается под капотом. Если вы хотите увидеть пример использования crypto-js с IV, оставьте комментарий ниже, и я буду рад опубликовать статью, в которой подробно описано, как это сделать. Спасибо за прочтение!