В этой статье мы поговорим об использовании AES шифрования на микроконтроллерах и, в частности, разберём устройство и работу специализированной библиотеки AESLib, реализующую это шифрование на Arduino.
Назначение библиотеки AESLib
Библиотека AESLib реализует четыре типа шифрования по алгоритму AES, это:
- Шифрование (и расшифровка) одиночных (single) блоков по 128 бит с ключами 128 или 256 бит.
- Шифрование (и расшифровка) нескольких (multiple) блоков по 128 бит с ключами 128 или 256 бит.
- Шифрование (и расшифровка) нескольких блоков в режиме CBC (Cipher Block Chaining) «сцепления блоков шифротекста» по 128 бит с ключами 128 или 192 бит.
- Потоковое шифрование (и расшифровка) блоков в режиме 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: Библиотека AESLib