В этой статье мы попробуем обобщить знания об устройстве и функционировании микросхемы ATSHA204A, полученные на предыдущих уроках, и создать прототип системы аутентификации «база — датчик». Мы разработаем крипто-архитектуру этой системы, создадим её структурную схему и напишем прикладной код, который вы сможете использовать как основу для своих собственных проектов.
Постановка задачи
Нам нужно разработать систему в которой «база» (базовый контроллер) при общении с «датчиком» (любой вид датчиков или дочерний контроллер) сможет однозначно распознать, что ответ на запрос пришёл именно от «родного» датчика (принадлежащего нашей экосистеме, а не поддельного).
На реализации конкретного транспорта (среды и способа передачи сообщений между контроллерами) мы останавливаться не будем — это может быть любой из нужных вам способов, например, беспроводные nRF24, LoRa, Wi-Fi и т. п. или проводные Ethernet, RS-485, CAN и т. д.
Базовый контроллер будет посылать запрос на датчик, а датчик будет формировать ответ по которому база однозначно сможет определить, что он пришёл от «легитимного» устройства нашей экосистемы. Нужно, используя микросхему ATSHA204A, обеспечить невозможность формирования правильного ответа чужим (поддельным) датчиком на запрос нашей базы.
Обратите внимание: пример, рассматриваемый в данной статье, может использоваться в реальных проектах, но только как одна из частей крипто-архитектуры системы. В реальных проектах, параллельно с задачей аутентификации устройств, нужно решать ещё множество других задач по обеспечению безопасного обмена информацией.
Крипто-архитектура
На блок-схеме ниже представлена крипто-архитектура нашей будущей системы. Базовый блок и датчик содержат в своём составе идентично запрограммированные микросхемы ATSHA204A. Сам процесс работы с микросхемами ATSHA204A и их программирования подробно описан в этом цикле статей.
Для нас в данном случае являются важными следующие этапы:
- Мы настроили конфигурационную зону (Configuration Zone) микросхемы ATSHA204A
- Затем провели блокировку (Lock) конфигурационной зоны
- Далее мы записали 32-байтовые ключи в зону данных (Data Zone) ATSHA204A
- Провели блокировку Data и OTP зон ATSHA204A
Крипто-архитектура нашего проекта:
Теперь немного подробнее об аутентификации «база — датчик». Базовый блок и датчик имеют у себя на борту чипы ATSHA204A и в каждый чип заранее зашит одинаковый секретный ключ.
Микросхемы ATSHA204A имеют встроенный генератор случайных чисел. В нашем примере чип ATSHA204A базового блока генерирует случайное число и подаёт его на вход как своего блока вычисления хеш-функции SHA-256, так и передаёт контроллеру для отсылки удалённому датчику, который имеет такой же блок хеширования и такой же секретный ключ внутри своего чипа ATSHA204A.
В результате обе микросхемы ATSHA204A вычисляют хеш на основе случайного числа и секретного ключа (зашитого в микросхемы и недоступного для чтения извне) и датчик отсылает его (хеш) обратно базовому блоку для сравнения. Далее на базовом блоке происходит сравнение хешей и принимается решение о верификации («легитимности») или не верификации датчика.
Поскольку секретный ключ хранится в микросхемах ATSHA204A, недоступен злоумышленнику и не передаётся по сети, то злоумышленник не может подделать ответ датчика на произвольное случайное число, присылаемое базовым блоком. Таким образом происходит проверка на «легитимность» удалённого датчика.
Базовый блок
Наш мини-проект мы разобьём на две части и в этой статье мы подробно опишем работу базового контроллера системы, а работу датчика мы разберём в следующей статье.
Итак, мы имеем запрограммированную нами микросхему ATSHA204A (2 экземпляра — один для базы, а другой для датчика) в Data зоне которой содержатся секретные 32-байтовые ключи, 13 из которых недоступны для чтения извне (подробности см. в предыдущих статьях этого цикла).
В этом проекте мы будем использовать нулевой слот зоны данных, который содержит 32 байта со значениями 0x00. Разумеется, в вашем реальном проекте этот ключ может содержать любую нужную вам информацию. Напомним также, что нулевой слот в нашей конфигурации ATSHA204A недоступен для чтения извне и, даже украв ваш датчик, злоумышленник не сможет извлечь из ATSHA204A ваш секретный ключ и не сможет клонировать датчики.
В качестве исходных мы возьмём два скетча из наших предыдущих статей — один для генерации случайного 32-байтового числа, а другой для вычисления SHA хеша при помощи команды MAC. И далее мы создадим скетч который генерирует случайное 32-байтовое число при помощи соответствующей функции микросхемы ATSHA204A и вычисляет его SHA хеш, используя секретный ключ из нулевого слота Data зоны нашей (заранее запрограммированной, см. предыдущие статьи) микросхемы ATSHA204A.
В целом, весь алгоритм работы нашей системы аутентификации можно описать следующим образом.
На стороне базы:
- База генерирует случайное 32-байтовое число при помощи микросхемы ATSHA204A
- База вычисляет SHA хеш на основе случайного числа и секретного ключа из Data зоны
- База отсылает сгенерированное случайное число датчику (любым удобным способом)
На стороне датчика:
- Датчик принимает от базы тестовое случайное число
- Датчик вычисляет SHA хеш на основе полученного числа и ключа из своего экземпляра ATSHA204A
- Датчик отсылает вычисленный хеш обратно на базу
Снова на стороне базы:
- База сравнивает хеши и принимает решение о «легитимности» датчика
Теперь код базы, который генерирует случайное число и вычисляет хеш (как уже было отмечено выше, без функций реализации транспорта).
/* ATSHA204A Project (Base) */ #include <sha204_library.h> const int sha204Pin = A3; byte challenge[MAC_CHALLENGE_SIZE]; byte hash[MAC_CHALLENGE_SIZE]; byte retCode = 0; atsha204Class sha204(sha204Pin); void setup() { Serial.begin(115200); Serial.println("ATSHA204 Project (Base) start..."); makeRandom(); Serial.println("Random:"); printArray(challenge, 32); Serial.println(); macChallenge(); Serial.println("Hash:"); printArray(hash, 32); Serial.println(); } // Print void printArray(byte arr[], byte len) { for (byte i = 0; i < len; i++) { if (arr[i] < 16) {Serial.print('0');} Serial.print(arr[i], HEX); Serial.print(' '); } } // Random void makeRandom() { uint8_t response[RANDOM_RSP_SIZE]; uint8_t tx_buffer[12] = {0}; retCode = sha204.sha204m_random(tx_buffer, response, RANDOM_NO_SEED_UPDATE); for (byte i = 0; i < 32; i++) { challenge[i] = response[i]; } } // MAC void macChallenge() { uint8_t command[MAC_COUNT_LONG]; uint8_t response[MAC_RSP_SIZE]; retCode = sha204.sha204m_execute(SHA204_MAC, 0, 0, MAC_CHALLENGE_SIZE, (uint8_t *) challenge, 0, NULL, 0, NULL, sizeof(command), &command[0], sizeof(response), &response[0]); for (byte i = 0; i < 32; i++) { hash[i] = response[i]; } } void loop() { }
И подробный разбор его работы. Вначале объявляем два массива для хранения случайного 32-байтового числа и SHA хеша.
byte challenge[MAC_CHALLENGE_SIZE]; byte hash[MAC_CHALLENGE_SIZE];
Затем при помощи функции makeRandom() генерируем 32-байтовое случайное число.
void makeRandom() { uint8_t response[RANDOM_RSP_SIZE]; uint8_t tx_buffer[12] = {0}; retCode = sha204.sha204m_random(tx_buffer, response, RANDOM_NO_SEED_UPDATE); for (byte i = 0; i < 32; i++) { challenge[i] = response[i]; } }
И заполняем им массив challenge.
for (byte i = 0; i < 32; i++) { challenge[i] = response[i]; }
В вашем реальном проекте вам нужно будет любым удобным вам способом передать этот массив (challenge) на датчик. Как уже было отмечено выше, проводных и беспроводных способов передачи данных существует великое множество и конкретная реализация процедуры обмена ими зависит от специфики вашего проекта.
Далее на основе сгенерированного случайного числа (находящегося в массиве challenge) и секретного ключа из нулевого слота Data зоны нашей микросхемы ATSHA204A мы вычисляем SHA хеш.
void macChallenge() { uint8_t command[MAC_COUNT_LONG]; uint8_t response[MAC_RSP_SIZE]; retCode = sha204.sha204m_execute(SHA204_MAC, 0, 0, MAC_CHALLENGE_SIZE, (uint8_t *) challenge, 0, NULL, 0, NULL, sizeof(command), &command[0], sizeof(response), &response[0]); for (byte i = 0; i < 32; i++) { hash[i] = response[i]; } }
И помещаем его в массив hash.
for (byte i = 0; i < 32; i++) { hash[i] = response[i]; }
Который нам понадобится позже для сравнения его с хешем, полученным нами от датчика, а пока мы выводим результат генерации случайного числа и вычисленный хеш на печать.
makeRandom(); Serial.println("Random:"); printArray(challenge, 32); Serial.println(); macChallenge(); Serial.println("Hash:"); printArray(hash, 32); Serial.println();
Вот результат работы нашего скетча:
Итак, ещё раз озвучим алгоритм работы базового контроллера: первое число (Random или массив challenge) вы отсылаете датчику любым удобным вам способом, в соответствии с реализацией вашего проекта, а второе число (Hash или массив hash) вы будете сравнивать с 32-я байтами хеша, которые получите от вашего датчика.
Если хеши совпадут, то удалённый датчик можно считать «легитимным» потому, что вычислить правильный хеш в ответ на случайное число можно только имея доступ к секретному ключу в Data зоне вашей (датчика) микросхемы ATSHA204A.
Заключение
В этой статье мы рассмотрели вопрос аутентификации удалённых контроллеров (датчиков) вашей экосистемы при помощи специализированной микросхемы ATSHA204A и дали пример кода, реализующего этот функционал на стороне базового контроллера. В следующей статье мы продолжим рассмотрение этого вопроса и разберём работу системы на стороне датчика (или дочернего контроллера) и приведём код, реализующий соответствующие функции.
Ссылки по теме
ATSHA204 - Библиотека и примеры
ATSHA204A - Чтение зоны конфигурации 1
ATSHA204A - Чтение зоны конфигурации 2
ATSHA204A - Чтение зоны конфигурации 3
ATSHA204A - Запись конфигурации 1
ATSHA204A - Запись конфигурации 2
ATSHA204A - Запись конфигурации 3
ATSHA204A - Запись конфигурации 4
ATSHA204A - Работа в режиме Config Lock
ATSHA204A - Работа с зонами памяти
ATSHA204A - Чтение Data и OTP зон памяти
ATSHA204A - Аутентификация. Датчик
ATSHA204A - Криптография и команды
ATSHA204A - nRF24 аутентификация. База
ATSHA204A - nRF24 аутентификация. Датчик