Оглавление:

Беспроводное шифрованное соединение Arduino: 5 шагов
Беспроводное шифрованное соединение Arduino: 5 шагов

Видео: Беспроводное шифрованное соединение Arduino: 5 шагов

Видео: Беспроводное шифрованное соединение Arduino: 5 шагов
Видео: Уроки Arduino #5 - работа с цифровыми портами и подключение кнопки 2024, Ноябрь
Anonim
Беспроводная зашифрованная связь Arduino
Беспроводная зашифрованная связь Arduino

Всем привет, Во второй статье я объясню вам, как использовать чип Atecc608a для защиты беспроводной связи. Для этого я буду использовать NRF24L01 + для беспроводной части и Arduino UNO.

Микрочип ATECC608A был разработан MicroChip и имеет несколько инструментов безопасности. Например, этот чип может хранить ключи ECC, ключи AES (для AES 128) и хэш SHA2.

Артикул: NRF24L01 + Arduino UNO + ATECC608A

Во время обмена данными между двумя объектами Интернета вещей может происходить несколько атак: «Человек из легких», «Копирование информации» и т. Д. Итак, моя идея очень проста:

  1. Использование зашифрованных данных между двумя или более объектами IoT.
  2. Недорогие расходные материалы
  3. Может работать с Arduino UNO

В моем случае я использую

  • Atecc608a для хранения моего ключа AES и для шифрования / дешифрования моих данных.
  • Arduino Uno как микроконтроллер
  • NRF24L01 для отправки моих данных

Для этого проекта вам необходимо выполнить следующие действия:

  1. Настроил микросхему ATECC608A
  2. Сделайте схему (главный узел и подчиненный узел)
  3. Часть кода
  4. Идти дальше !

Для первых шагов «Настройка микросхемы ATECC608A» я написал другую статью, в которой по порядку объясняется каждый шаг. Ссылка здесь:

А теперь начнем!

Запасы

Для этого проекта вам понадобятся:

  • 2 Arduino UNO или Arduino NANO или Arduino Mega
  • Какой-то провод
  • 2 Atecc608a (менее 0,60 $ каждый)
  • 2 NRF24L01 +
  • 2 конденсатора (10 мкФ)
  • Макеты

Ссылка на мою статью, в которой объясняется, как настроить микросхему ATECC608A -> Как настроить Atecc608a

Шаг 1: 1. Настройте Atecc608a

1. Настройте Atecc608a
1. Настройте Atecc608a
1. Настройте Atecc608a
1. Настройте Atecc608a

Я не буду подробно описывать каждый шаг, который нужно выполнить для настройки ATECC608A, потому что я написал полную статью, в которой объясняются все шаги для этого. Чтобы настроить его, вам необходимо выполнить «Шаг 4» этой статьи под названием «2. Конфигурация чипа (Atecc608a)».

Ссылка: Как настроить ATECC608A

Кроме того, вам необходимо установить одинаковую конфигурацию для Atecc608a, главной и подчиненной стороны, иначе вы не сможете расшифровать свои данные

Предупреждение:

Чтобы настроить этот чип, вам необходимо выполнить все шаги, указанные в статье выше. Если один шаг отсутствует или чип не заблокирован, вы не сможете выполнить этот проект

Остаток:

Шаг для этого:

  • Создать шаблон конфигурации
  • Запишите этот шаблон в чип
  • Заблокировать зону конфигурации
  • Запишите свой ключ AES (128 бит) в слот
  • Заблокировать зону данных

Шаг 2: 2. Дизайн схемы (ведущий и ведомый)

2. Конструкция схемы (ведущий и ведомый)
2. Конструкция схемы (ведущий и ведомый)
2. Конструкция схемы (ведущий и ведомый)
2. Конструкция схемы (ведущий и ведомый)

В этом проекте у вас будет главный узел и подчиненный узел.

Главный узел распечатает данные, отправленные подчиненным узлом, в открытом виде. Он будет запрашивать данные у подчиненного узла каждый X раз.

Подчиненный узел будет прослушивать «сеть», и когда он получит «данные запроса», он сгенерирует их, зашифрует и отправит на главный узел.

Для обеих сторон, ведущего и ведомого, схема одинакова:

  • Один Arduino Nano
  • Один ATECC608A
  • Один NRF24L01

Я прикрепил схему к этому шагу (см. Рисунок выше).

Для ATECC608A к Arduino UNO это 8-контактный разъем soic. Я добавил "вид сверху" выше:

  • ARDUINO 3.3V -> PIN 8 (Atecc608a)
  • ARDUINO GND -> PIN 4 (Atecc608a)
  • ARDUINO A4 (SDL) -> PIN 5 (Atecc608a)
  • ARDUINO A5 (SCL) -> PIN 6 (Atecc608a)

Для NRF24L01 на Arduino:

  • ARDUINO 3.3V -> VCC (nrf24l01)
  • ARDUINO GND -> GND (nrf24l01)
  • ARDUINO 9 -> CE (nrf24l01)
  • ARDUINO 10 -> CSN (nrf24l01)
  • ARDUINO 11 -> MOSI (nrf24L01)
  • ARDUINO 12 -> MISO (nrf24l01)
  • ARDUINO 13 -> SCK (nrf24l01)
  • ARDUINO 3 -> IRQ (nrf24l01) -> только для ведомого узла, не используется в режиме ведущего

Зачем использовать вывод IRQ NRF24L01

Вывод IRQ очень полезен, этот вывод позволяет сказать (LOW), когда пакет получен NRF24L01, поэтому мы можем прикрепить прерывание к этому выводу, чтобы разбудить подчиненный узел.

Шаг 3: 3. Код (Ведомый и Главный)

3. Код (Ведомый и Ведущий)
3. Код (Ведомый и Ведущий)

Ведомый узел

Я использую энергосбережение для подчиненного узла, потому что ему не нужно постоянно слушать.

Как это работает: подчиненный узел слушает и ожидает получения «пакета Wake UP». Этот пакет отправляется главным узлом для запроса данных у ведомого.

В моем случае я использую массив из двух int:

// Пакет пробуждения

const int wake_packet [2] = {20, 02};

Если мой узел получит пакет,

  1. он просыпается, прочитайте этот пакет, если пакет - "Пробуждение",
  2. он генерирует данные,
  3. зашифровать данные,
  4. отправить данные мастеру, дождаться пакета ACK,
  5. спать.

Для шифрования AES я использую ключ в слоте № 9.

Это мой код для подчиненного узла

#include "Arduino.h" #include "avr / sleep.h" #include "avr / wdt.h"

#include "SPI.h"

#include "nRF24L01.h" #include "RF24.h"

#include "Wire.h"

// Библиотека ATECC608A

#include "ATECCX08A_Arduino / cryptoauthlib.h" #include "AES BASIC / aes_basic.h"

#define ID_NODE 255

#define AES_KEY (uint8_t) 9

ATCAIfaceCfg cfg;

Статус ATCA_STATUS;

Радиостанция РФ24 (9, 10);

const uint64_t masteraddresse = 0x1111111111;

const uint64_t slaveaddresse = 0x1111111100;

/**

* / short Функция, выполняемая, когда установлено прерывание (IRQ LOW) * * * / void wakeUpIRQ () {while (radio.available ()) {int data [32]; radio.read (& data, 32); if (data [0] == 20 && data [1] == 02) {float temp = 17.6; гул поплавка = 16,4;

uint8_t data [16];

uint8_t cypherdata [16];

// Создаем строку для установки всего моего значения

// Каждое значение разделяется знаком "|" а "$" означает конец данных // ВНИМАНИЕ: длина должна быть меньше 11 String tmp_str_data = String (ID_NODE) + "|" + String (temp, 1) + "|" + Строка (гул, 1) + «$»; // размер 11 Serial.println ("tmp_str_data:" + tmp_str_data);

tmp_str_data.getBytes (данные, sizeof (данные));

// Шифровать данные

ATCA_STATUS status = aes_basic_encrypt (& cfg, data, sizeof (данные), cypherdata, AES_KEY); если (статус == ATCA_SUCCESS) {длинный ранд = случайный ((длинный) 10000, (длинный) 99999);

// генерируем UUID на основе трех первых чисел = ID узла

Строка uuid = Строка (ID_NODE) + Строка (ранд); // Размер 8

uint8_t tmp_uuid [8];

uint8_t data_to_send [32];

uuid.getBytes (tmp_uuid, sizeof (tmp_uuid) + 1);

memcpy (data_to_send, tmp_uuid, sizeof (tmp_uuid));

memcpy (data_to_send + sizeof (tmp_uuid), cypherdata, sizeof (cypherdata)); // Прекращаем слушать радио.stopListening ();

bool rslt;

// Отправка данных rslt = radio.write (& data_to_send, sizeof (data_to_send)); // Начинаем слушать радио. StartListening (); if (rslt) {// Конец и режим ожидания Serial.println (F ("Готово")); }}}}}

установка void ()

{Serial.begin (9600);

// Инициируем конструктор библиотеки

cfg.iface_type = ATCA_I2C_IFACE; // Тип связи -> режим I2C cfg.devtype = ATECC608A; // Тип микросхемы cfg.atcai2c.slave_address = 0XC0; // Адрес I2C (значение по умолчанию) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Задержка пробуждения (1500 мс) cfg.rx_retries = 20;

radio.begin ();

radio.setDataRate (RF24_250KBPS); radio.maskIRQ (1, 1, 0); radio.enableAckPayload (); radio.setRetries (5, 5);

radio.openWritingPipe (мастерская);

radio.openReadingPipe (1, slaveaddresse); // Присоединение прерывания к выводу 3 // Измените 1 на O, если вы хотите, чтобы прерывание было на выводе 2 // РЕЖИМ ПАДЕНИЯ = Вывод на НИЗКОМ attachInterrupt (1, wakeUpIRQ, FALLING); }

пустой цикл ()

{ // Нет надобности }

Главный узел

Главный узел просыпается каждые 8 секунд, чтобы запросить данные у ведомого узла.

Как это работает: главный узел отправляет подчиненному пакет «WakeUP» и после этого ожидает ответа подчиненного с данными.

В моем случае я использую массив из двух int:

// Пакет пробуждения

const int wake_packet [2] = {20, 02};

Если ведомый узел отправляет пакет ACK после того, как ведущий отправил пакет WakeUp:

  1. Мастер настраивается в режиме прослушивания и ждет сообщения
  2. Если общение
  3. Извлеките 8 первых байтов, возьмите три первых байта из 8 байтов, если это узел идентификатора
  4. Извлечь 16 байт шифра
  5. Расшифровать данные
  6. Распечатать данные в последовательном
  7. Спящий режим

Для шифрования AES я использую ключ в слоте № 9.

Это мой код для главного узла

#include "Arduino.h"

#include "avr / sleep.h" #include "avr / wdt.h" #include "SPI.h" #include "nRF24L01.h" #include "RF24.h" #include "Wire.h" // библиотека ATECC608A #include "ATECCX08A_Arduino / cryptoauthlib.h" #include "AES BASIC / aes_basic.h" #define ID_NODE 255 #define AES_KEY (uint8_t) 9 ATCAIfaceCfg cfg; Статус ATCA_STATUS; Радиостанция РФ24 (9, 10); const uint64_t masteraddresse = 0x1111111111; const uint64_t slaveaddresse = 0x1111111100; // Пакет пробуждения const int wake_packet [2] = {20, 02}; // сторожевое прерывание ISR (WDT_vect) {wdt_disable (); // отключаем сторожевой таймер} void sleepmode () {// отключаем АЦП ADCSRA = 0; // сбросить различные флаги "сброса" MCUSR = 0; // разрешить изменения, запретить сброс WDTCSR = bit (WDCE) | бит (WDE); // устанавливаем режим прерывания и интервал WDTCSR = bit (WDIE) | бит (WDP3) | бит (WDP0); // устанавливаем WDIE и задержку 8 секунд wdt_reset (); // сбросить сторожевой таймер set_sleep_mode (SLEEP_MODE_PWR_DOWN); noInterrupts (); // синхронизированная последовательность следует за sleep_enable (); // выключаем включение отключения питания в программном обеспечении MCUCR = bit (BODS) | бит (BODSE); MCUCR = бит (BODS); прерывания (); // гарантирует выполнение следующей инструкции sleep_cpu (); // в качестве меры предосторожности отменяем сон sleep_disable (); } void setup () {Serial.begin (9600); // Запускаем конструктор библиотеки cfg.iface_type = ATCA_I2C_IFACE; // Тип связи -> режим I2C cfg.devtype = ATECC608A; // Тип микросхемы cfg.atcai2c.slave_address = 0XC0; // Адрес I2C (значение по умолчанию) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Задержка пробуждения (1500 мс) cfg.rx_retries = 20; radio.begin (); radio.setDataRate (RF24_250KBPS); radio.maskIRQ (1, 1, 0); radio.enableAckPayload (); radio.setRetries (5, 5); radio.openWritingPipe (slaveaddresse); radio.openReadingPipe (1, masteraddresse); } void loop () {bool rslt; // Отправка данных rslt = radio.write (& wake_packet, sizeof (wake_packet)); if (rslt) {// Начинаем слушать радио. startListening (); в то время как (radio.available ()) {uint8_t answer [32]; radio.read (& answer, sizeof (ответ)); uint8_t node_id [3]; uint8_t cypher [16]; memcpy (node_id, ответ, 3); memcpy (шифр, ответ + 3, 16); if ((int) node_id == ID_NODE) {uint8_t output [16]; ATCA_STATUS status = aes_basic_decrypt (& cfg, cypher, 16, вывод, AES_KEY); if (status == ATCA_SUCCESS) {Serial.println ("Расшифрованные данные:"); for (size_t i = 0; i <16; i ++) {Serial.print ((char) output ); }}}}} else {Serial.println («Подтверждение не получено для пакета Wakup»); } // Спящий режим 8 секунд sleepmode (); }

Если у вас есть вопросы, я здесь, чтобы на них ответить

Шаг 4: 4. Двигайтесь дальше

Это простой пример, поэтому вы можете улучшить этот проект.

Улучшения:

  • AES 128 является базовым, и вы можете использовать другой алгоритм AES в качестве AES CBC для большей безопасности.
  • Замените беспроводной модуль (NRF24L01 ограничен полезной нагрузкой 23 байта)

Если вы видите, что нужно сделать, объясните это в области обсуждения.

Шаг 5: Заключение

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

Спасибо, что все прочитали.

Наслаждайся этим.

Рекомендуемые: