Inhaltsverzeichnis:

Drahtlose verschlüsselte Kommunikation Arduino - Gunook
Drahtlose verschlüsselte Kommunikation Arduino - Gunook

Video: Drahtlose verschlüsselte Kommunikation Arduino - Gunook

Video: Drahtlose verschlüsselte Kommunikation Arduino - Gunook
Video: Funkmodul - Arduino Tutorial (Allgemeines, Verkabelung, Code & mehr) [1080p Full HD - german] 2024, November
Anonim
Drahtlose verschlüsselte Kommunikation Arduino
Drahtlose verschlüsselte Kommunikation Arduino

Hallo alle zusammen, In diesem zweiten Artikel erkläre ich Ihnen, wie Sie mit dem Chip Atecc608a Ihre drahtlose Kommunikation absichern. Dazu verwende ich den NRF24L01+ für den Wireless-Teil und den Arduino UNO.

Der Mikrochip ATECC608A wurde von MicroChip entwickelt und verfügt über mehrere Sicherheitstools. Dieser Chip kann beispielsweise ECC-Schlüssel, AES-Schlüssel (für AES 128) und SHA2-Hash speichern.

Der Artikel: NRF24L01 + Arduino UNO + ATECC608A

Während einer Kommunikation zwischen zwei IoT-Objekten kann es mehrere Angriffe geben: Mann der Milde, Kopie von Informationen und mehr.. Meine Idee ist also sehr einfach:

  1. Nutzung verschlüsselter Daten zwischen zwei oder mehr IoT-Objekten.
  2. Kostengünstige Verbrauchsmaterialien
  3. Kann mit einem Arduino UNO arbeiten

In meinem Fall verwende ich

  • den Atecc608a, um meinen AES-Schlüssel zu speichern und meine Daten zu verschlüsseln/entschlüsseln.
  • das Arduino Uno als Mikrocontroller
  • Der NRF24L01 zum Senden meiner Daten

Sie müssen diese Schritte für dieses Projekt ausführen:

  1. Richten Sie den Chip ATECC608A ein
  2. Machen Sie die Schaltung (Master-Knoten und Slave-Knoten)
  3. Codeteil
  4. Weiter gehen !

Für die ersten Schritte "Einrichten des Chips ATECC608A" habe ich einen weiteren Artikel geschrieben, der jeden Schritt der Reihe nach erklärt. Der Link ist hier:

Starte jetzt !

Lieferungen

Für dieses Projekt benötigen Sie:

  • 2 Arduino UNO oder Arduino NANO oder Arduino Mega
  • Etwas Draht
  • 2 Atecc608a (jeweils weniger als 0,60 $ kosten)
  • 2 NRF24L01+
  • 2 Kondensator (10 μF)
  • Steckbretter

Link zu meinem Artikel, der erklärt, wie man den Chip ATECC608A einrichtet -> Wie man Atecc608a einrichtet

Schritt 1: 1. Einrichten des Atecc608a

1. Einrichten des Atecc608a
1. Einrichten des Atecc608a
1. Einrichten des Atecc608a
1. Einrichten des Atecc608a

Ich werde nicht jeden Schritt zum Einrichten eines ATECC608A detailliert beschreiben, da ich einen vollständigen Artikel geschrieben habe, der alle Schritte erklärt, um dies zu tun. Um es einzurichten, müssen Sie den "Schritt 4" dieses Artikels namens " 2. Konfiguration des Chips (Atecc608a) " befolgen.

Der Link lautet: So richten Sie einen ATECC608A ein

Außerdem müssen Sie die gleiche Konfiguration für den Atecc608a, Master- und Slave-Seite, vornehmen, da Sie sonst Ihre Daten nicht entschlüsseln können

Warnung:

Um diesen Chip einzurichten, müssen Sie alle Schritte des obigen Artikels der Reihe nach ausführen. Wenn ein Schritt fehlt oder der Chip nicht gesperrt ist, können Sie dieses Projekt nicht durchführen

Rest:

Schritt dazu:

  • Erstellen Sie eine Konfigurationsvorlage
  • Schreiben Sie diese Vorlage auf den Chip
  • Sperren Sie die Konfigurationszone
  • Schreiben Sie Ihren AES-Schlüssel (128 Bits) in einen Steckplatz
  • Sperren Sie die Datenzone

Schritt 2: 2. Schaltungsdesign (Master und Slave)

2. Schaltungsdesign (Master und Slave)
2. Schaltungsdesign (Master und Slave)
2. Schaltungsdesign (Master und Slave)
2. Schaltungsdesign (Master und Slave)

In diesem Projekt haben Sie einen Master-Knoten und einen Slave-Knoten.

Der Master-Knoten druckt die vom Slave-Knoten gesendeten Daten in Klarschrift. Es fordert jedes X Mal Daten vom Slave-Knoten an.

Der Slave-Knoten hört das "Netzwerk" und wenn er "Anforderungsdaten" empfängt, wird er diese generieren, verschlüsseln und an den Master-Knoten senden.

Für beide Seiten, Master und Slave ist die Schaltung gleich:

  • Ein Arduino-Nano
  • Ein ATECC608A
  • Ein NRF24L01

Ich habe die Schaltung an diesen Schritt angeschlossen (siehe Bild oben).

Für den ATECC608A zum Arduino UNO ist dies ein Soic 8-Pin. Ich habe oben die "Draufsicht" hinzugefügt:

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

Für den NRF24L01 zum 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) -> nur für Slave-Knoten, nicht im Master-Modus verwendet

Warum den IRQ-Pin des NRF24L01 verwenden?

Der IRQ-Pin ist sehr nützlich, dieser Pin ermöglicht es, (LOW) zu sagen, wenn ein Paket vom NRF24L01 empfangen wird, sodass wir einen Interrupt an diesen Pin anhängen können, um den Slave-Knoten aufzuwecken.

Schritt 3: 3. der Code (Slave und Master)

3. der Code (Slave und Master)
3. der Code (Slave und Master)

Slave-Knoten

Ich verwende Energiesparmodus für den Slave-Knoten, da er nicht die ganze Zeit zuhören muss.

So funktioniert es: Der Slave-Knoten hört und wartet auf den Empfang eines "Wake-UP-Pakets". Dieses Paket wird vom Master-Knoten gesendet, um Daten vom Slave abzufragen.

In meinem Fall verwende ich ein Array von zwei int:

// Wake-UP-Paket

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

Wenn mein Knoten ein Paket empfängt,

  1. es aufwacht, dieses Paket lesen, wenn das Paket ein "Wake UP" ist,
  2. es generiert die Daten,
  3. die Daten verschlüsseln,
  4. Sende die Daten an den Master, warte auf ein ACK-Paket,
  5. Schlaf.

Für die AES-Verschlüsselung verwende ich einen Schlüssel im Slot Nummer 9.

Dies ist mein Code für den Slave-Knoten

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

#include "SPI.h"

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

#include "Wire.h"

// ATECC608A-Bibliothek

#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-Status;

RF24-Funk (9, 10);

const uint64_t Masteradresse = 0x1111111111;

const uint64_t Slaveadresse = 0x1111111100;

/**

* \brief Funktion wird ausgeführt, wenn der Interrupt gesetzt ist (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; Schwimmerbrummen = 16,4;

uint8_t-Daten[16];

uint8_t Verschlüsselungsdaten[16];

// Erstellen Sie einen String, um alle meine Werte zu setzen

// Jeder Wert wird durch ein "|" getrennt und das "$" bedeutet das Ende der Daten // WARNUNG: Muss kürzer als 11 sein String tmp_str_data = String(ID_NODE) + "|" + String(temp, 1) + "|" + String(brumm, 1) + "$"; // Größe von 11 Serial.println ("tmp_str_data: " + tmp_str_data);

tmp_str_data.getBytes(Daten, Größe(Daten));

// Daten verschlüsseln

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

// Generiere eine UUID basierend auf den drei ersten Zahlen = ID node

String uuid = String(ID_NODE) + String(rand); // Größe von 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), Verschlüsselungsdaten, Größevon(Verschlüsselungsdaten)); // Hör auf Radio zu hören.stopListening();

bool rslt;

// Daten senden rslt = radio.write(&data_to_send, sizeof(data_to_send)); // Hören radio.startListening(); if (rslt) {// Beenden und Ruhemodus Serial.println (F ("Fertig")); } } } } }

Void-Setup ()

{ Serial.begin (9600);

// Initiere den Konstruktor für die Bibliothek

cfg.iface_type = ATCA_I2C_IFACE; // Kommunikationsart -> I2C-Modus cfg.devtype = ATECC608A; // Chiptyp cfg.atcai2c.slave_address = 0XC0; // I2C-Adresse (Standardwert) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Weckverzögerung (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(Masteradresse);

radio.openReadingPipe(1, Slaveadresse); // Interrupt an Pin 3 anhängen // 1 durch O ändern, wenn Sie den Interrupt an Pin 2 wollen // FALLING MODE = Pin auf LOW attachInterrupt (1, wakeUpIRQ, FALLING); }

Leere Schleife ()

{ // Das ist nicht nötig }

Master-Knoten

Der Master-Knoten wacht alle 8 Sekunden auf, um Daten vom Slave-Knoten abzufragen

Wie es funktioniert: Der Master-Knoten sendet ein "WakeUP"-Paket an den Slave und wartet darauf eine Antwort des Slaves mit Daten.

In meinem Fall verwende ich ein Array von zwei int:

// Wake-UP-Paket

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

Wenn der Slave-Knoten ein ACK-Paket sendet, nachdem der Master ein WakeUp-Paket gesendet hat:

  1. Master im Listen-Modus einrichten und auf eine Kommunikation warten
  2. Wenn Kommunikation
  3. Extrahieren Sie die ersten 8 Bytes, plündern Sie die drei ersten Bytes der 8 Bytes, wenn dies der ID-Knoten ist
  4. Extrahiere die 16 Byte Verschlüsselung
  5. Entschlüsseln Sie die Daten
  6. Drucken Sie die Daten in Serie
  7. Schlafmodus

Für die AES-Verschlüsselung verwende ich einen Schlüssel im Slot Nummer 9.

Dies ist mein Code für den Master-Knoten

#include "Arduino.h"

#include "avr/sleep.h" #include "avr/wdt.h" #include "SPI.h" #include "nRF24L01.h" #include "RF24.h" #include "Wire.h" // ATECC608A Bibliothek #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-Status; RF24-Funk (9, 10); const uint64_t Masteradresse = 0x1111111111; const uint64_t Slaveadresse = 0x1111111100; // Wake-UP-Paket const int wake_packet[2] = {20, 02}; // Watchdog-Interrupt ISR (WDT_vect) { wdt_disable (); // Watchdog deaktivieren aufrechtzuerhalten. Void sleepmode () {// ADC deaktivieren ADCSRA = 0; // verschiedene "Reset"-Flags löschen MCUSR = 0; // Änderungen zulassen, Reset deaktivieren WDTCSR = bit(WDCE) | bit(WDE); // setze den Interrupt-Modus und ein Intervall WDTCSR = bit(WDIE) | bit(WDP3) | bit(WDP0); // setze WDIE und 8 Sekunden Verzögerung wdt_reset(); // den Watchdog zurücksetzen set_sleep_mode (SLEEP_MODE_PWR_DOWN); noInterrupts(); // zeitgesteuerte Sequenz folgt sleep_enable(); // Brown‐Out aktivieren in Software ausschalten MCUCR = bit(BODS) | bit(BODS); MCUCR = bit(BODS); unterbricht(); // garantiert, dass die nächste Anweisung ausgeführt wird sleep_cpu(); // Schlaf vorsichtshalber abbrechen sleep_disable(); aufrechtzuerhalten. Void setup () { Serial.begin (9600); // Init des Konstruktors für die Bibliothek cfg.iface_type = ATCA_I2C_IFACE; // Kommunikationsart -> I2C-Modus cfg.devtype = ATECC608A; // Chiptyp cfg.atcai2c.slave_address = 0XC0; // I2C-Adresse (Standardwert) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Weckverzögerung (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(Slaveadresse); radio.openReadingPipe(1, Masteradresse); aufrechtzuerhalten. Void Schleife () { bool rslt; // Daten senden rslt = radio.write(&wake_packet, sizeof(wake_packet)); if (rslt) {// Beginnen Sie mit dem Hören radio.startListening(); while (radio.available ()) { uint8_t answer[32]; radio.read(&Antwort, sizeof(Antwort)); uint8_t Knoten_ID[3]; uint8_t-Verschlüsselung[16]; memcpy(node_id, answer, 3); memcpy(Cypher, Antwort + 3, 16); if ((int)node_id == ID_NODE) { uint8_t Ausgabe[16]; ATCA_STATUS-Status = aes_basic_decrypt(&cfg, Verschlüsselung, 16, Ausgabe, AES_KEY); if (status == ATCA_SUCCESS) { Serial.println ("Entschlüsselte Daten: "); für (size_t i = 0; i < 16; i++) {Serial.print ((char)output); aufrechtzuerhalten. } // Schlafmodus 8 Sekunden sleepmode (); }

Wenn Sie Fragen haben, bin ich hier, um sie zu beantworten

Schritt 4: 4. Gehen Sie weiter

Dieses Beispiel ist einfach, damit Sie dieses Projekt verbessern können

Verbesserungen:

  • Der AES 128 ist einfach und Sie können einen anderen AES-Algorithmus als AES CBC verwenden, um sicherer zu sein.
  • Wechseln Sie das Funkmodul (der NRF24L01 ist durch eine Nutzlast von 23 Bytes begrenzt)

Wenn Sie Verbesserungsbedarf sehen, erklären Sie dies im Diskussionsbereich

Schritt 5: Fazit

Ich hoffe, dass dieser Artikel für Sie nützlich ist. Es tut mir leid, wenn ich einen Fehler in meinem Text gemacht habe, aber Englisch ist nicht meine Hauptsprache und ich spreche besser als ich schreibe.

Danke, dass du alles gelesen hast.

Genieß es.

Empfohlen: