logo
+7 (951) 999-89-94
428003, г. Чебоксары, ул. Федора Гладкова, д.9, оф.319

AES: Библиотека AESLib

В этой статье мы поговорим об использовании AES шифрования на микроконтроллерах и, в частности, разберём устройство и работу специализированной библиотеки AESLib, реализующую это шифрование на Arduino.

Назначение библиотеки AESLib

Библиотека AESLib реализует четыре типа шифрования по алгоритму AES, это:

  1. Шифрование (и расшифровка) одиночных (single) блоков по 128 бит с ключами 128 или 256 бит.
  2. Шифрование (и расшифровка) нескольких (multiple) блоков по 128 бит с ключами 128 или 256 бит.
  3. Шифрование (и расшифровка) нескольких блоков в режиме CBC (Cipher Block Chaining) «сцепления блоков шифротекста» по 128 бит с ключами 128 или 192 бит.
  4. Потоковое шифрование (и расшифровка) блоков в режиме CBC (Cipher Block Chaining) «сцепления блоков шифротекста» по 128 бит с ключами 128 или 192 бит.

Несмотря на то, что существуют и более изощрённые режимы шифрования, функционала библиотеки AESLib должно хватить для реализации любых ваших «крипто» проектов на Arduino.

Все действия библиотеки AESLib и алгоритма AES производятся с блоками по 128 бит (16 uint8_t).

Режим Single block

Это самый простой режим работы, когда на вход функций библиотеки AESLib подаются данные по 128 бит (блоками по 16 байт) и ключ размером 128 бит (16 uint8_t) или 256 бит (32 uint8_t). Шифрование/расшифровка блока для ключа 128 бит:

void aes128_enc_single(const uint8_t* key, void* data);

void aes128_dec_single(const uint8_t* key, void* data);

Шифрование/расшифровка блока для ключа 256 бит:

void aes256_enc_single(const uint8_t* key, void* data);

void aes256_dec_single(const uint8_t* key, void* data);

Разумеется, шифрование с ключом 256 бит более надёжное, чем с ключом 128 бит, но требует больших ресурсов микроконтроллера.

Режим Multiple blocks

В этом режиме работы на вход функций библиотеки AESLib подаются данные сразу несколькими блоками по 16 байт и указывается их общая длина, которая должна быть кратна 16. Как и в первом случае, здесь также используются ключи размером 128 или 256 бит.

Шифрование/расшифровка нескольких блоков для ключа 128 бит:

void aes128_enc_multiple(const uint8_t* key, void* data, const uint16_t data_len);

void aes128_dec_multiple(const uint8_t* key, void* data, const uint16_t data_len);

Шифрование/расшифровка нескольких блоков для ключа 256 бит:

void aes256_enc_multiple(const uint8_t* key, void* data, const uint16_t data_len);

void aes256_dec_multiple(const uint8_t* key, void* data, const uint16_t data_len);

CBC (Cipher Block Chaining)

Как вы помните из нашей предыдущей статьи, CBC (Cipher Block Chaining) — это так называемый «режим сцепления блоков шифротекста», в котором:

  • Сообщение (данные) разбивается на блоки одинакового размера, в нашем случае это 128 бит.
  • Шифрование очередного блока выполняется с использованием предыдущего зашифрованного блока.
  • Для первого блока предыдущего блока не существует, поэтому он шифруется с использованием т. н. «вектора инициализации» (initialization vector, IV). Вектор инициализации — это случайное число. Размер (длина) IV равна размеру блока.
  • Расшифровка выполняется с использованием тех же ключа и вектора инициализации IV.

Режим Multiple CBC

В этом режиме работы на вход функций библиотеки AESLib подаются данные сразу несколькими блоками по 16 байт и указывается их общая длина, которая должна быть кратна 16. Здесь также используются ключи размером 128 или 192 бит (24 uint8_t).

CBC шифрование нескольких блоков для ключа и вектора инициализации (iv) 128/192 бит:

void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);

void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);

CBC расшифровка нескольких блоков для ключа и вектора инициализации (iv) 128/192 бит:

void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);

void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);

Режим потокового шифрования CBC

В этом режиме работа по шифрованию разбивается на несколько этапов «Start», «Continue» и «Finish», то есть работа по шифрованию производится не сразу, а постепенно. Здесь также используются ключи и iv размером 128 или 192 бит.

В так называемом «контексте» сохраняются временные данные.

typedef void* aes_context;

На первом этапе (Start) на вход функций библиотеки AESLib передаются ключ и вектор инициализации.

aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv);

aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv);

На втором этапе (Continue) на вход функций библиотеки AESLib передаются контекст, данные (блоками кратными 16 байт) и длина этих данных.

void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len);

void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len);

Завершается (Finish) работа по шифрованию данных вызовом соответствующих функций библиотеки.

void aes128_cbc_enc_finish(const aes_context ctx);

void aes192_cbc_enc_finish(const aes_context ctx);

Режим потоковой расшифровки CBC

Этом режим очень похож и является зеркальным по отношению к режиму «потокового шифрования CBC», здесь также присутствуют этапы «Start», «Continue» и «Finish» и также используются ключи и iv размером 128 или 192 бит.

На первом этапе (Start) на вход функций библиотеки AESLib передаются ключ и вектор инициализации 128/192 бит.

aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv);

aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv);

На втором этапе (Continue) на вход функций библиотеки AESLib передаются контекст, данные (блоками кратными 16 байт) и длина этих данных.

void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len);

void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len);

Завершается (Finish) работа по расшифровке данных вызовом соответствующих функций библиотеки.

void aes128_cbc_dec_finish(const aes_context ctx);

void aes192_cbc_dec_finish(const aes_context ctx);

Типовой пример использования AESLib

Теперь давайте на практическом примере рассмотрим работу функций библиотеки AESLib по шифрованию данных, используя стандарт AES.

Реализуем самый простой вариант работы — шифрование одиночного блока данных 16 байт (128 бит) по алгоритму AES с использованием 128-битного ключа.

/*
  AES Single block Encrypt test
*/

#include <AESLib.h>

uint8_t key[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
byte data[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

void setup() {
  Serial.begin(115200);
  Serial.println(F("AES Single block Encrypt test start..."));

  Serial.print(F("Data:    "));
  for (byte i = 0; i < 16; i++) {
    Serial.print(data[i]); Serial.print(F(" "));
  }
  Serial.println();
  
  aes128_enc_single(key, data);
  
  Serial.print(F("Encrypt: "));
  for (byte i = 0; i < 16; i++) {
    Serial.print(data[i]); Serial.print(F(" "));
  }
  Serial.println();

}

void loop() {
  
}

Здесь мы вначале подключаем библиотеку AESLib.

#include <AESLib.h>

Затем задаём 16-байтовый ключ шифрования (значение ключа было выбрано произвольно).

uint8_t key[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

Далее задаём блок данных (размером 128 бит). Тут значения байтов данных тоже выбраны произвольным образом.

byte data[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

Выводим на экран (для контроля) содержимое массива data.

  Serial.print(F("Data:    "));
  for (byte i = 0; i < 16; i++) {
    Serial.print(data[i]); Serial.print(F(" "));
  }
  Serial.println();

Шифруем данные по алгоритму AES, передавая функции aes128_enc_single() массивы с данными и ключом шифрования.

  aes128_enc_single(key, data);

Далее выводим на экран результат шифрования.

  Serial.print(F("Encrypt: "));
  for (byte i = 0; i < 16; i++) {
    Serial.print(data[i]); Serial.print(F(" "));
  }
  Serial.println();

И видим, что операция по шифрованию данных прошла успешно. Вот скриншот результата работы нашего скетча:

Заключение

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

Ссылки по теме

AES: Стандарт шифрования AES

AES: Библиотека AESLib

AES: Работа в режиме Single block

AES: Работа в режиме Multiple blocks