Table des matières:

Communication cryptée sans fil Arduino : 5 étapes
Communication cryptée sans fil Arduino : 5 étapes

Vidéo: Communication cryptée sans fil Arduino : 5 étapes

Vidéo: Communication cryptée sans fil Arduino : 5 étapes
Vidéo: 1 - Les Systèmes De Communication Sans Fil 2024, Novembre
Anonim
Communication cryptée sans fil Arduino
Communication cryptée sans fil Arduino

Bonjour à tous, Dans ce deuxième article, je vais vous expliquer comment utiliser la puce Atecc608a pour sécuriser votre communication sans fil. Pour cela, j'utiliserai le NRF24L01+ pour la partie Wireless et l'Arduino UNO.

La micropuce ATECC608A a été conçue par MicroChip et dispose de plusieurs outils de sécurité. Par exemple, cette puce peut stocker des clés ECC, des clés AES (pour AES 128) et du hachage SHA2.

L'article: NRF24L01 + Arduino UNO + ATECC608A

Lors d'une communication entre deux objets IoT, plusieurs attaques peuvent exister: Man Of the mild, Copy of information et plus.. Donc mon idée est très simple:

  1. Utilisation de données cryptées entre deux ou plusieurs objets IoT.
  2. Fournitures à faible coût
  3. Peut fonctionner avec un Arduino UNO

Dans mon cas, j'utilise

  • l'Atecc608a pour stocker ma clé AES et crypter/décrypter mes données.
  • l'Arduino Uno comme microcontrôleur
  • Le NRF24L01 pour envoyer mes données

Vous devez suivre ces étapes pour ce projet:

  1. Configurer la puce ATECC608A
  2. Faire le circuit (nœud maître et nœud esclave)
  3. Partie de code
  4. Aller plus loin !

Pour les premières étapes "Configurer la puce ATECC608A", j'ai écrit un autre article qui explique chaque étape dans l'ordre. Le lien est ici:

Commencez maintenant !

Fournitures

Pour ce projet il vous faut:

  • 2 Arduino UNO ou Arduino NANO ou Arduino Mega
  • du fil
  • 2 Atecc608a (chacun coûtant moins de 0.60$)
  • 2 NRF24L01+
  • 2 condensateurs (10 F)
  • Planches à pain

Lien vers mon article qui explique comment paramétrer la puce ATECC608A -> Comment paramétrer Atecc608a

Étape 1: 1. Configurer l'Atecc608a

1. Configurer l'Atecc608a
1. Configurer l'Atecc608a
1. Configurer l'Atecc608a
1. Configurer l'Atecc608a

Je ne détaillerai pas toutes les étapes à suivre pour mettre en place un ATECC608A car j'ai écrit un article complet qui explique toutes les étapes pour le faire. Pour le mettre en place, vous devez suivre l'« Étape 4 » de cet article intitulé « 2. Configuration de la puce (Atecc608a) »

Le lien est: Comment configurer un ATECC608A

De plus, vous devez mettre la même configuration pour l'Atecc608a, côté maître et côté esclave, sinon vous ne pourrez pas déchiffrer vos données

Avertissement:

Pour configurer cette puce, vous devez suivre toutes les étapes de l'article ci-dessus dans l'ordre. S'il manque une étape ou si la puce n'est pas verrouillée, vous ne pourrez pas réaliser ce projet

Reste:

Etape à suivre pour cela:

  • Créer un modèle de configuration
  • Écrivez ce modèle sur la puce
  • Verrouiller la zone de configuration
  • Écrivez votre clé AES (128 bits) dans un emplacement
  • Verrouiller la zone de données

Étape 2: 2. Conception du circuit (maître et esclave)

2. Conception du circuit (maître et esclave)
2. Conception du circuit (maître et esclave)
2. Conception du circuit (maître et esclave)
2. Conception du circuit (maître et esclave)

Dans ce projet, vous aurez un nœud maître et un nœud esclave.

Le nœud maître imprimera les données envoyées par le nœud esclave en clair. Il demandera des données au nœud esclave à chaque fois X.

Le nœud esclave écoutera le "réseau" et lorsqu'il recevra une "Demande de données", il la générera, la cryptera et l'enverra au nœud maître.

Pour les deux côtés, maître et esclave le circuit est le même:

  • Un arduino Nano
  • Un ATECC608A
  • Un NRF24L01

J'ai attaché le circuit à cette étape (cf photo ci-dessus).

Pour l'ATECC608A vers l'Arduino UNO, il s'agit d'un soic 8 broches. J'ai ajouté la "vue de dessus" ci-dessus:

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

Pour le NRF24L01 à l'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) -> uniquement pour le nœud esclave, non utilisé en mode maître

Pourquoi utiliser la broche IRQ du NRF24L01

La broche IRQ est très utile, cette broche permet de dire (LOW) quand un paquet est reçu par le NRF24L01, on peut donc attacher une interruption à cette broche pour réveiller le nœud esclave.

Étape 3: 3. le Code (Esclave et Maître)

3. le Code (Esclave et Maître)
3. le Code (Esclave et Maître)

Nœud esclave

J'utilise l'économie d'énergie pour le nœud esclave car il n'a pas besoin d'écouter tout le temps.

Comment ça marche: le nœud esclave écoute et attend de recevoir un "Wake UP packet". Ce paquet est envoyé par le nœud maître pour demander des données à l'esclave.

Dans mon cas, j'utilise un tableau de deux int:

// Paquet de réveil

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

Si mon nœud reçoit un paquet,

  1. il se réveille, lisez ce paquet, si le paquet est un "Wake UP",
  2. il génère les données,
  3. crypter les données,
  4. envoyer les données au maître, attendre un paquet ACK,
  5. dormir.

Pour le cryptage AES, j'utilise une clé dans le slot numéro 9.

Ceci est mon code pour le nœud esclave

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

#include "SPI.h"

#inclure "nRF24L01.h" #inclure "RF24.h"

#include "Fil.h"

// Bibliothèque ATECC608A

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

#define ID_NODE 255

#define AES_KEY (uint8_t)9

ATCAIfaceCfg cfg;

état ATCA_STATUS;

radio RF24 (9, 10);

const uint64_t adresse maître = 0x1111111111;

const uint64_t adresse esclave = 0x1111111100;

/**

* \brief Fonction exécutée lorsque l'interruption est définie (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; bourdonnement flottant = 16,4;

uint8_t données[16];

uint8_t cypherdata[16];

// Construire une chaîne pour définir toute ma valeur

// Chaque valeur est séparée par un "|" et le "$" signifie la fin des données // ATTENTION: Doit être inférieur à 11 String tmp_str_data = String(ID_NODE) + "|" + Chaîne(temp, 1) + "|" + Chaîne(hum, 1) + "$"; //taille de 11 Serial.println("tmp_str_data: " + tmp_str_data);

tmp_str_data.getBytes(data, sizeof(data));

// Crypter les données

ATCA_STATUS status = aes_basic_encrypt(&cfg, data, sizeof(data), cypherdata, AES_KEY); if (statut == ATCA_SUCCESS) { long rand = random((long)10000, (long)99999);

// générer un UUID basé sur les trois premiers nombres = nœud ID

Chaîne uuid = Chaîne(ID_NODE) + Chaîne(rand); // Taille de 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)); // Arrête d'écouter radio.stopListening();

bool rslt;

// Envoi des données rslt = radio.write(&data_to_send, sizeof(data_to_send)); // Commencer à écouter radio.startListening(); if (rslt) { // Fin et mode veille Serial.println(F("Done")); } } } } }

void setup()

{ Serial.begin(9600);

// Initialisation du constructeur de la librairie

cfg.iface_type = ATCA_I2C_IFACE; // Type de communication -> Mode I2C cfg.devtype = ATECC608A; // Type de puce cfg.atcai2c.slave_address = 0XC0; // Adresse I2C (valeur par défaut) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Délai de réveil (1500 ms) cfg.rx_retries = 20;

radio.begin();

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

radio.openWritingPipe(adresse principale);

radio.openReadingPipe(1, adresse esclave); // Attachez l'interruption à la broche 3 // Modifiez 1 par O si vous voulez l'interruption à la broche 2 // FALLING MODE = Pin at LOW attachInterrupt(1, wakeUpIRQ, FALLING); }

boucle vide()

{ // Ce n'est pas nécessaire }

Nœud maître

Le nœud maître se réveille toutes les 8 secondes pour demander des données au nœud esclave

Comment ça marche: Le nœud maître envoie un paquet "WakeUP" à l'esclave et attend une réponse de l'esclave avec des données.

Dans mon cas, j'utilise un tableau de deux int:

// Paquet de réveil

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

Si le nœud esclave envoie un paquet ACK après que le maître ait envoyé un paquet WakeUp:

  1. Le maître s'installe en mode écoute et attend une communication
  2. Si la communication
  3. Extraire les 8 premiers octets, piller les trois premiers octets des 8 octets, s'il s'agit du nœud ID
  4. Extraire les 16 octets de chiffrement
  5. Décrypter les données
  6. Imprimer les données en série
  7. Mode veille

Pour le cryptage AES, j'utilise une clé dans le slot numéro 9.

Ceci est mon code pour le nœud maître

#include "Arduino.h"

#include "avr/sleep.h" #include "avr/wdt.h" #include "SPI.h" #include "nRF24L01.h" #include "RF24.h" #include "Wire.h" // bibliothèque ATECC608A #include "ATECCX08A_Arduino/cryptoauthlib.h" #include "AES BASIC/aes_basic.h" #define ID_NODE 255 #define AES_KEY (uint8_t)9 ATCAIfaceCfg cfg; état ATCA_STATUS; radio RF24 (9, 10); const uint64_t adresse maître = 0x1111111111; const uint64_t adresse esclave = 0x1111111100; // Wake UP packet const int wake_packet[2] = {20, 02}; // interruption du chien de garde ISR(WDT_vect) { wdt_disable(); // désactiver le chien de garde } void sleepmode() { // désactiver l'ADC ADCSRA = 0; // efface divers drapeaux "reset" MCUSR = 0; // autoriser les modifications, désactiver la réinitialisation WDTCSR = bit(WDCE) | bit(WDE); // définit le mode d'interruption et un intervalle WDTCSR = bit(WDIE) | bits(WDP3) | bit(WDP0); // définit WDIE et retarde de 8 secondes wdt_reset(); // réinitialiser le chien de garde set_sleep_mode(SLEEP_MODE_PWR_DOWN); noInterrupts(); // la séquence chronométrée suit sleep_enable(); // désactiver l'activation du brown-out dans le logiciel MCUCR = bit(BODS) | bit(BODSE); MCUCR = bit(BODS); interruptions(); // garantit la prochaine instruction exécutée sleep_cpu(); // annule le sommeil par précaution sleep_disable(); } void setup() { Serial.begin(9600); // Init le constructeur pour la bibliothèque cfg.iface_type = ATCA_I2C_IFACE; // Type de communication -> Mode I2C cfg.devtype = ATECC608A; // Type de puce cfg.atcai2c.slave_address = 0XC0; // Adresse I2C (valeur par défaut) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Délai de réveil (1500 ms) cfg.rx_retries = 20; radio.begin(); radio.setDataRate(RF24_250KBPS); radio.maskIRQ(1, 1, 0); radio.enableAckPayload(); radio.setRetries(5, 5); radio.openWritingPipe(slaveaddress); radio.openReadingPipe(1, adresse principale); } boucle vide() { bool rslt; // Envoi des données rslt = radio.write(&wake_packet, sizeof(wake_packet)); if (rslt) { // Démarrer l'écoute radio.startListening(); while (radio.available()) { uint8_t answer[32]; radio.read(&answer, sizeof(answer)); uint8_t node_id[3]; uint8_t cypher[16]; memcpy(node_id, réponse, 3); memcpy(chiffre, réponse + 3, 16); if ((int)node_id == ID_NODE) { uint8_t sortie[16]; ATCA_STATUS status = aes_basic_decrypt(&cfg, cypher, 16, sortie, AES_KEY); if (status == ATCA_SUCCESS) { Serial.println("Decrypted Data: "); for (size_t i = 0; i < 16; i++) { Serial.print((char)output); } } } } } else{ Serial.println("Ack not receive for Wakup Packet"); } // Mode veille 8 secondes mode veille(); }

Si vous avez une question, je suis là pour y répondre

Étape 4: 4. Allez plus loin

Cet exemple est simple donc vous pouvez améliorer ce projet

Améliorations:

  • L'AES 128 est basique et vous pouvez utiliser un autre algorithme d'AES comme AES CBC pour être plus sûr.
  • Changer le module sans fil (le NRF24L01 est limité par une charge utile de 23 octets)

Si vous voyez des améliorations à faire, expliquez-les sur l'espace de discussion

Étape 5: Conclusion

J'espère que cet article vous sera utile. Désolé si je me suis trompé dans mon texte mais l'anglais n'est pas ma langue principale et je parle mieux que j'écris.

Merci d'avoir tout lu.

Profitez-en.

Conseillé: