Cuprins:
2025 Autor: John Day | [email protected]. Modificat ultima dată: 2025-01-13 06:58
Bună ziua tuturor, În acest al doilea articol, vă voi explica cum să utilizați cipul Atecc608a pentru a vă asigura comunicația fără fir. Pentru aceasta, voi folosi NRF24L01 + pentru partea Wireless și Arduino UNO.
Microcipul ATECC608A a fost proiectat de MicroChip și are mai multe instrumente de securitate. De exemplu, acest cip poate stoca chei ECC, chei AES (pentru AES 128) și SHA2 Hash.
Articolul: NRF24L01 + Arduino UNO + ATECC608A
În timpul unei comunicări între două obiecte IoT, pot exista atacuri multiple: Omul celor blânzi, Copie de informații și multe altele.. Deci ideea mea este foarte simplă:
- Utilizarea datelor criptate între două sau mai multe obiecte IoT.
- Aprovizionare cu cost redus
- Poate funcționa cu un Arduino UNO
În cazul meu, folosesc
- Atecc608a pentru a stoca cheia mea AES și pentru a cripta / decripta datele mele.
- Arduino Uno ca microcontroler
- NRF24L01 pentru a-mi trimite datele
Trebuie să urmați acești pași pentru acest proiect:
- Configurați cipul ATECC608A
- Faceți circuitul (nodul principal și nodul sclav)
- Cod parte
- Mergi mai departe !
Pentru primii pași „Configurarea cipului ATECC608A”, am scris un alt articol care explică fiecare pas în ordine. Link-ul este aici:
Acum începe!
Provizii
Pentru acest proiect aveți nevoie de:
- 2 Arduino UNO sau Arduino NANO sau Arduino Mega
- Niște sârmă
- 2 Atecc608a (fiecare costă mai puțin de 0,60 $)
- 2 NRF24L01 +
- 2 condensatori (10 μF)
- Panouri
Link către articolul meu care explică modul de configurare a cipului ATECC608A -> Cum se configurează Atecc608a
Pasul 1: 1. Configurați Atecc608a
Nu voi detalia fiecare pas de urmat pentru a configura un ATECC608A, deoarece am scris un articol complet care explică fiecare etapă pentru a o face. Pentru a-l configura, trebuie să urmați „Pasul 4” din acest articol numit „2. Configurarea cipului (Atecc608a)”
Link-ul este: Cum se configurează un ATECC608A
De asemenea, trebuie să puneți aceeași configurație pentru Atecc608a, partea master și partea slave, altfel nu veți putea decripta datele
Avertizare:
Pentru a configura acest cip, trebuie să urmați toți pașii articolului de mai sus în ordine. Dacă lipsește un pas sau cipul nu este blocat, nu ați putea face acest proiect
Rest:
Pasul de urmat pentru aceasta:
- Creați un șablon de configurare
- Scrieți acest șablon pe cip
- Blocați zona de configurare
- Scrieți cheia AES (128 biți) într-un slot
- Blocați zona de date
Pasul 2: 2. Proiectarea circuitului (Master și Slave)
În acest proiect, veți avea un nod principal și un nod sclav.
Nodul master va imprima datele trimise de nodul slave în clar. Va solicita date de la nodul slave de fiecare dată.
Nodul sclav va asculta „rețeaua” și atunci când va primi un „Solicită date”, îl va genera, cripta și îl va trimite la nodul principal.
Pentru ambele părți, master și slave circuitul este același:
- Un arduino Nano
- Unul ATECC608A
- Unul NRF24L01
Am atașat circuitul la acest pas (cf imaginea de mai sus).
Pentru ATECC608A către Arduino UNO, acesta este un soic 8 pini. Am adăugat „vizualizarea de sus” de mai sus:
- ARDUINO 3.3V -> PIN 8 (Atecc608a)
- ARDUINO GND -> PIN 4 (Atecc608a)
- ARDUINO A4 (SDL) -> PIN 5 (Atecc608a)
- ARDUINO A5 (SCL) -> PIN 6 (Atecc608a)
Pentru NRF24L01 către 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) -> numai pentru nodul Slave, neutilizat în modul Master
De ce să folosiți pinul IRQ al NRF24L01
Pinul IRQ este foarte util, acest pin permite să spună (LOW) când un pachet este primit de către NRF24L01, deci putem atașa o întrerupere la acest pin pentru a trezi nodul sclav.
Pasul 3: 3. Codul (Sclav și Maestru)
Nodul sclav
Folosesc economisirea energiei pentru nodul sclav, deoarece nu are nevoie să asculte tot timpul.
Cum funcționează: nodul sclav ascultă și așteaptă să primească un „pachet Wake UP”. Acest pachet este trimis de nodul Master pentru a cere date de la sclav.
În cazul meu, folosesc o serie de două int:
// Pachet Wake UP
const int wake_packet [2] = {20, 02};
Dacă nodul meu primește un pachet,
- se trezește, citește acest pachet, dacă pachetul este un „Trezire”,
- generează date,
- criptează datele,
- trimite datele către master, așteaptă un pachet ACK,
- dormi.
Pentru criptarea AES, folosesc o cheie în slotul numărul 9.
Acesta este codul meu pentru nodul Slave
#include "Arduino.h" #include "avr / sleep.h" #include "avr / wdt.h"
#includeți „SPI.h”
#include "nRF24L01.h" #include "RF24.h"
#include „Wire.h”
// Biblioteca ATECC608A
#include "ATECCX08A_Arduino / cryptoauthlib.h" #include "AES BASIC / aes_basic.h"
#define ID_NODE 255
#define AES_KEY (uint8_t) 9
ATCAIfaceCfg cfg;
Statutul ATCA_STATUS;
Radio RF24 (9, 10);
const uint64_t masteraddresse = 0x1111111111;
const uint64_t slaveaddresse = 0x1111111100;
/**
* / scurt Funcție executată când este setată întreruperea (IRQ LOW) * * * / void wakeUpIRQ () {while (radio.available ()) {int data [32]; radio.read (& data, 32); if (date [0] == 20 && data [1] == 02) {float temp = 17.6; zumzet plutitor = 16,4;
date uint8_t [16];
uint8_t cypherdata [16];
// Construiește un șir pentru a-mi seta toată valoarea
// Fiecare valoare este separată printr-un „|” iar „$” înseamnă sfârșitul datelor // AVERTISMENT: Trebuie să aibă o lungime mai mică de 11 Șir tmp_str_data = Șir (ID_NODE) + „|” + Șir (temp, 1) + "|" + Șir (zumzet, 1) + "$"; // dimensiunea de 11 Serial.println ("tmp_str_data:" + tmp_str_data);
tmp_str_data.getBytes (date, sizeof (data));
// Criptează datele
ATCA_STATUS status = aes_basic_encrypt (& cfg, data, sizeof (data), cypherdata, AES_KEY); if (status == ATCA_SUCCESS) {long rand = random ((long) 10000, (long) 99999);
// generați un UUID pe baza primului trei număr = nod ID
String uuid = String (ID_NODE) + String (rand); // Dimensiunea 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)); // Nu mai asculta radio.stopListening ();
bool rslt;
// Trimite date rslt = radio.write (& data_to_send, sizeof (data_to_send)); // Începeți să ascultați radio.startListening (); if (rslt) {// Mod sfârșit și repaus Serial.println (F ("Terminat")); }}}}}
configurare nulă ()
{Serial.begin (9600);
// Inițiați constructorul pentru bibliotecă
cfg.iface_type = ATCA_I2C_IFACE; // Tipul comunicării -> Mod I2C cfg.devtype = ATECC608A; // Tipul cipului cfg.atcai2c.slave_address = 0XC0; // adresă I2C (valoare implicită) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Întârziere trezire (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 (masteraddresse);
radio.openReadingPipe (1, slaveaddresse); // Atașați întreruperea la pinul 3 // Modificați 1 cu O dacă doriți întreruperea la pinul 2 // FALLING MODE = Pin la LOW attachInterrupt (1, wakeUpIRQ, FALLING); }
bucla nulă ()
{ // Nu este nevoie }
Nod Maestru
Nodul master se trezește la fiecare 8 secunde pentru a cere date de la Nodul slave
Cum funcționează: nodul master trimite un pachet „WakeUP” către sclav și după ce așteptați un răspuns al sclavului cu date.
În cazul meu, folosesc o serie de două int:
// Pachet Wake UP
const int wake_packet [2] = {20, 02};
Dacă nodul slave trimite un pachet ACK după ce maestrul a trimis un pachet WakeUp:
- Master configurat în modul Ascultare și așteptați o comunicare
- Dacă comunicarea
- Extrageți primul 8 octet, predați primul trei octet al celor 8 octeți, dacă acesta este nodul ID
- Extrageți cei 16 octeți de cifru
- Decriptați datele
- Imprimați datele în serie
- Modul de somn
Pentru criptarea AES, folosesc o cheie în slotul numărul 9.
Acesta este codul meu pentru nodul Master
#include „Arduino.h”
#include "avr / sleep.h" #include "avr / wdt.h" #include "SPI.h" #include "nRF24L01.h" #include "RF24.h" #include "Wire.h" // Biblioteca ATECC608A #include "ATECCX08A_Arduino / cryptoauthlib.h" #include "AES BASIC / aes_basic.h" #define ID_NODE 255 #define AES_KEY (uint8_t) 9 ATCAIfaceCfg cfg; Statutul ATCA_STATUS; Radio RF24 (9, 10); const uint64_t masteraddresse = 0x1111111111; const uint64_t slaveaddresse = 0x1111111100; // Pachet Wake UP const int wake_packet [2] = {20, 02}; // întrerupere ISR (WDT_vect) {wdt_disable () // disable watchdog} void sleepmode () {// disable ADC ADCSRA = 0; // ștergeți diferite steaguri „resetare” MCUSR = 0; // permite modificări, dezactivează resetarea WDTCSR = bit (WDCE) | bit (WDE); // setați modul de întrerupere și un interval WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE și 8 secunde întârziere wdt_reset (); // resetați watchdog set_sleep_mode (SLEEP_MODE_PWR_DOWN); noInterrupts (); // secvența temporizată urmează sleep_enable (); // dezactivați activarea brown-out în software-ul MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); întrerupe (); // garantează următoarea instrucțiune executată sleep_cpu (); // anulați somnul ca măsură de precauție sleep_disable (); } void setup () {Serial.begin (9600); // Inițiați constructorul pentru biblioteca cfg.iface_type = ATCA_I2C_IFACE; // Tipul comunicării -> Mod I2C cfg.devtype = ATECC608A; // Tipul cipului cfg.atcai2c.slave_address = 0XC0; // adresă I2C (valoare implicită) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Întârziere trezire (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 (slaveaddresse); radio.openReadingPipe (1, masteraddresse); } void loop () {bool rslt; // Trimite date rslt = radio.write (& wake_packet, sizeof (wake_packet)); if (rslt) {// Start Listening radio.startListening (); while (radio.available ()) {uint8_t răspuns [32]; radio.read (& answer, sizeof (answer)); uint8_t node_id [3]; uint8_t cypher [16]; memcpy (node_id, answer, 3); memcpy (cifru, răspuns + 3, 16); if ((int) node_id == ID_NODE) {ieșire uint8_t [16]; ATCA_STATUS status = aes_basic_decrypt (& cfg, cypher, 16, output, AES_KEY); if (status == ATCA_SUCCESS) {Serial.println ("Date decriptate:"); for (size_t i = 0; i <16; i ++) {Serial.print ((char) output ); }}}}} else {Serial.println ("Ack nu primește pentru pachetul Wakup"); } // Mod de repaus 8 secunde sleepmode (); }
Dacă aveți întrebări, sunt aici pentru a răspunde
Pasul 4: 4. Mergeți mai departe
Acest exemplu este simplu, astfel încât să puteți îmbunătăți acest proiect
Îmbunătățiri:
- AES 128 este de bază și puteți utiliza un alt algoritm al AES ca AES CBC pentru a fi mai sigur.
- Schimbați modulul wireless (NRF24L01 este limitat de o sarcină utilă de 23 de octeți)
- …
Dacă vedeți o îmbunătățire, explicați-o în zona de discuții
Pasul 5: Concluzie
Sper că acest articol vă va fi de folos. Îmi pare rău dacă am greșit în textul meu, dar engleza nu este limba mea principală și vorbesc mai bine decât scriu.
Mulțumesc că ai citit totul.
Bucură de ea.