Πίνακας περιεχομένων:

Ασύρματη κρυπτογραφημένη επικοινωνία Arduino: 5 βήματα
Ασύρματη κρυπτογραφημένη επικοινωνία Arduino: 5 βήματα

Βίντεο: Ασύρματη κρυπτογραφημένη επικοινωνία Arduino: 5 βήματα

Βίντεο: Ασύρματη κρυπτογραφημένη επικοινωνία Arduino: 5 βήματα
Βίντεο: CS50 2015 - Week 10 2024, Νοέμβριος
Anonim
Ασύρματη κρυπτογραφημένη επικοινωνία Arduino
Ασύρματη κρυπτογραφημένη επικοινωνία Arduino

Γεια σε όλους, Σε αυτό το δεύτερο άρθρο, θα σας εξηγήσω πώς να χρησιμοποιήσετε το τσιπ Atecc608a για να εξασφαλίσετε την ασύρματη επικοινωνία σας. Για αυτό, θα χρησιμοποιήσω το NRF24L01+ για το τμήμα Wireless και το Arduino UNO.

Το μικροτσίπ ATECC608A έχει σχεδιαστεί από την MicroChip και έχει πολλά εργαλεία ασφαλείας. Για παράδειγμα, αυτό το τσιπ μπορεί να αποθηκεύσει κλειδιά ECC, κλειδιά AES (για AES 128) και SHA2 Hash.

Το άρθρο: NRF24L01 + Arduino UNO + ATECC608A

Κατά τη διάρκεια μιας επικοινωνίας μεταξύ δύο αντικειμένων IoT, μπορεί να υπάρξουν πολλαπλές επιθέσεις: Man Of the mild, Αντιγραφή πληροφοριών και πολλά άλλα. Η ιδέα μου λοιπόν είναι πολύ απλή:

  1. Χρήση κρυπτογραφημένων δεδομένων μεταξύ δύο ή περισσότερων αντικειμένων IoT.
  2. Προμήθειες χαμηλού κόστους
  3. Μπορεί να συνεργαστεί με Arduino UNO

Στην περίπτωσή μου, χρησιμοποιώ

  • το Atecc608a για την αποθήκευση του κλειδιού AES και την κρυπτογράφηση/αποκρυπτογράφηση των δεδομένων μου.
  • το Arduino Uno ως μικροελεγκτής
  • Το NRF24L01 για την αποστολή των δεδομένων μου

Πρέπει να ακολουθήσετε αυτά τα βήματα για αυτό το έργο:

  1. Ρυθμίστε το τσιπ ATECC608A
  2. Κάνετε το κύκλωμα (Master Node και Slave Node)
  3. Κωδικό μέρος
  4. Πηγαίνετε Παραπέρα!

Για τα πρώτα βήματα "Ρύθμιση του τσιπ ATECC608A", έγραψα ένα άλλο άρθρο που εξηγεί κάθε βήμα με τη σειρά. Ο σύνδεσμος είναι εδώ:

Τώρα ξεκινήστε!

Προμήθειες

Για αυτό το έργο χρειάζεστε:

  • 2 Arduino UNO ή Arduino NANO ή Arduino Mega
  • Λίγο σύρμα
  • 2 Atecc608a (το καθένα κοστίζει λιγότερο από 0,60 $)
  • 2 NRF24L01+
  • 2 πυκνωτές (10 μF)
  • Breadboards

Σύνδεσμος προς το άρθρο μου που εξηγεί τον τρόπο ρύθμισης του τσιπ ATECC608A -> Πώς να ρυθμίσετε το Atecc608a

Βήμα 1: 1. Ρυθμίστε το Atecc608a

1. Ρυθμίστε το Atecc608a
1. Ρυθμίστε το Atecc608a
1. Ρυθμίστε το Atecc608a
1. Ρυθμίστε το Atecc608a

Δεν θα αναφέρω λεπτομερώς κάθε βήμα που πρέπει να ακολουθήσετε για τη δημιουργία ενός ATECC608A επειδή έγραψα ένα πλήρες άρθρο που εξηγεί κάθε βήμα για να το κάνετε. Για να το ρυθμίσετε, πρέπει να ακολουθήσετε το "Βήμα 4" αυτού του άρθρου που ονομάζεται "2. Διαμόρφωση του τσιπ (Atecc608a)"

Ο σύνδεσμος είναι: Πώς να ρυθμίσετε ένα ATECC608A

Επίσης, πρέπει να βάλετε την ίδια ρύθμιση παραμέτρων για την Atecc608a, την κύρια πλευρά και την πλευρά υποτελών, διαφορετικά δεν θα μπορείτε να αποκρυπτογραφήσετε τα δεδομένα σας

Προειδοποίηση:

Για να ρυθμίσετε αυτό το τσιπ, πρέπει να ακολουθήσετε κάθε βήμα του παραπάνω άρθρου με τη σειρά. Εάν λείπει ένα βήμα ή το τσιπ δεν είναι κλειδωμένο, δεν θα μπορούσατε να κάνετε αυτό το έργο

Υπόλοιπο:

Βήμα που πρέπει να ακολουθήσετε για αυτό:

  • Δημιουργήστε ένα πρότυπο διαμόρφωσης
  • Γράψτε αυτό το πρότυπο στο τσιπ
  • Κλείδωμα της ζώνης διαμόρφωσης
  • Γράψτε το κλειδί AES (128 Bits) σε μια υποδοχή
  • Κλείδωμα της ζώνης δεδομένων

Βήμα 2: 2. Σχεδιασμός του κυκλώματος (Master and Slave)

2. Σχεδιασμός του κυκλώματος (Master and Slave)
2. Σχεδιασμός του κυκλώματος (Master and Slave)
2. Σχεδιασμός του κυκλώματος (Master and Slave)
2. Σχεδιασμός του κυκλώματος (Master and Slave)

Σε αυτό το έργο, θα έχετε έναν κύριο κόμβο και έναν κόμβο σκλάβων.

Ο κύριος κόμβος θα εκτυπώσει με σαφήνεια τα δεδομένα που αποστέλλονται από τον υποτελή κόμβο. Θα ζητάει δεδομένα από τον σκλάβο κόμβο κάθε Χ φορά.

Ο σκλάβος κόμβος θα ακούσει το "δίκτυο" και όταν λάβει ένα "Αίτημα δεδομένων", θα το δημιουργήσει, θα το κρυπτογραφήσει και θα το στείλει στον κύριο κόμβο.

Και για τις δύο πλευρές, κύριος και υποτελής το κύκλωμα είναι το ίδιο:

  • Ένα arduino Nano
  • Ένα ATECC608A
  • Ένα NRF24L01

Επισυνάπτω το κύκλωμα σε αυτό το βήμα (βλ. Εικόνα παραπάνω).

Για το ATECC608A στο Arduino UNO, αυτό είναι ένα soic 8 pin. Πρόσθεσα την "κορυφαία προβολή" παραπάνω:

  • 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) -> μόνο για Slave κόμβο, δεν χρησιμοποιείται σε κύρια λειτουργία

Γιατί να χρησιμοποιήσετε τον πείρο IRQ του NRF24L01

Ο πείρος IRQ είναι πολύ χρήσιμος, αυτός ο πείρος επιτρέπει να λέμε (LOW) όταν ένα πακέτο λαμβάνεται από το NRF24L01, ώστε να μπορούμε να επισυνάψουμε μια διακοπή σε αυτόν τον πείρο για να ξυπνήσει ο σκλάβος κόμβος.

Βήμα 3: 3. ο Κώδικας (Slave and Master)

3. ο Κώδικας (Slave and Master)
3. ο Κώδικας (Slave and Master)

Σκλάβος κόμβος

Χρησιμοποιώ εξοικονόμηση ενέργειας για τον κόμβο σκλάβων επειδή δεν χρειάζεται να ακούγεται όλη την ώρα.

Πώς λειτουργεί: ο σκλάβος κόμβος ακούει και περιμένει να λάβει ένα "Wake UP packet". Αυτό το πακέτο αποστέλλεται από τον κύριο κόμβο για να ζητήσει δεδομένα από τον υποτελή.

Στην περίπτωσή μου, χρησιμοποιώ έναν πίνακα δύο int:

// Wake UP πακέτο

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

Εάν ο κόμβος μου λάβει ένα πακέτο,

  1. ξυπνήστε, διαβάστε αυτό το πακέτο, εάν το πακέτο είναι "Wake UP",
  2. δημιουργεί δεδομένα,
  3. κρυπτογράφηση των δεδομένων,
  4. στείλτε τα δεδομένα στον κύριο, περιμένετε ένα πακέτο ACK,
  5. ύπνος.

Για την κρυπτογράφηση AES, χρησιμοποιώ ένα κλειδί στην υποδοχή 9.

Αυτός είναι ο κωδικός μου για τον κόμβο Slave

#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.

Ραδιόφωνο RF24 (9, 10).

const uint64_t masteraddresse = 0x1111111111;

const uint64_t slaveaddresse = 0x1111111100;

/**

* / σύντομη Λειτουργία που εκτελείται όταν έχει οριστεί η διακοπή (IRQ LOW) * * */ void wakeUpIRQ () {while (radio.available ()) {int data [32]; radio.read (& δεδομένα, 32); if (δεδομένα [0] == 20 && δεδομένα [1] == 02) {float temp = 17,6; πλωτήρα βουητό = 16,4;

uint8_t δεδομένα [16];

uint8_t cypherdata [16];

// Δημιουργήστε μια συμβολοσειρά για να ορίσετε όλη την αξία μου

// Κάθε τιμή χωρίζεται με ένα "|" και το "$" σημαίνει το τέλος των δεδομένων // ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Πρέπει να έχει μήκος μικρότερο από 11 String tmp_str_data = String (ID_NODE) + "|" + Χορδή (θερμοκρασία, 1) + "|" + Χορδή (βουητό, 1) + "$"; // μέγεθος 11 Serial.println ("tmp_str_data:" + tmp_str_data);

tmp_str_data.getBytes (δεδομένα, μέγεθος (δεδομένα));

// Κρυπτογράφηση των δεδομένων

ATCA_STATUS status = aes_basic_encrypt (& cfg, data, sizeof (data), cypherdata, AES_KEY); εάν (κατάσταση == ATCA_SUCCESS) {long rand = random ((long) 10000, (long) 99999);

// δημιουργεί ένα UUID με βάση τον πρώτο πρώτο αριθμό = κόμβος ID

String uuid = String (ID_NODE) + String (rand); // Μέγεθος 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)); // Έναρξη ακρόασης radio.startListening (); if (rslt) {// Τερματισμός και αναστολή λειτουργίας Serial.println (F ("Done")); }}}}}

void setup ()

{Serial.begin (9600);

// Εισαγάγετε τον κατασκευαστικό για τη βιβλιοθήκη

cfg.iface_type = ATCA_I2C_IFACE; // Τύπος επικοινωνίας -> I2C mode cfg.devtype = ATECC608A; // Τύπος τσιπ cfg.atcai2c.slave_address = 0XC0; // I2C adresse (προεπιλεγμένη τιμή) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Καθυστέρηση αφύπνισης (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); // Επισύναψη διακοπής στον πείρο 3 // Τροποποίηση 1 κατά O εάν θέλετε τη διακοπή στον ακροδέκτη 2 // FALLING MODE = Καρφίτσωμα στο LOW attachInterrupt (1, wakeUpIRQ, FALLING); }

κενός βρόχος ()

{ // Δεν χρειάζεται }

Κύριος κόμβος

Ο κύριος κόμβος ξυπνά κάθε 8 δευτερόλεπτα για να ζητήσει δεδομένα από τον υποτελή κόμβο

Πώς λειτουργεί: Ο κύριος κόμβος στέλνει ένα πακέτο "WakeUP" στον σκλάβο και αφού περιμένει μια απάντηση του υποτελούς με δεδομένα.

Στην περίπτωσή μου, χρησιμοποιώ έναν πίνακα δύο int:

// Wake UP πακέτο

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

Εάν ο σκλάβος κόμβος στείλει ένα πακέτο ACK αφού ο κύριος στείλει ένα πακέτο WakeUp:

  1. Το Master έχει ρυθμιστεί σε λειτουργία Ακρόασης και περιμένετε μια επικοινωνία
  2. Αν επικοινωνία
  3. Εξαγάγετε το 8 πρώτο byte, λεηλατήστε τα τρία πρώτα byte από τα 8 byte, εάν αυτός είναι ο κόμβος ID
  4. Εξαγάγετε το 16 byte του cypher
  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. Ραδιόφωνο RF24 (9, 10). const uint64_t masteraddresse = 0x1111111111; const uint64_t slaveaddresse = 0x1111111100; // Wake UP packet const int wake_packet [2] = {20, 02}; // watchdog interrupt ISR (WDT_vect) {wdt_disable (); // απενεργοποίηση watchdog} void sleepmode () {// απενεργοποίηση ADC ADCSRA = 0; // διαγράψτε διάφορες σημαίες "επαναφοράς" MCUSR = 0; // επιτρέψτε αλλαγές, απενεργοποιήστε την επαναφορά WDTCSR = bit (WDCE) | bit (WDE); // ορίστε τη λειτουργία διακοπής και ένα διάστημα WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // ρύθμιση WDIE και καθυστέρηση 8 δευτερολέπτων wdt_reset (); // επαναφέρετε το set_sleep_mode του φύλακα (SLEEP_MODE_PWR_DOWN). noInterrupts (); // η χρονομετρημένη ακολουθία ακολουθεί τη λειτουργία sleep_enable (); // απενεργοποιήστε τη δυνατότητα καφέ ‐ out στο λογισμικό MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); διακόπτει ()? // εγγυάται την επόμενη εντολή που εκτελείται sleep_cpu (); // ακύρωση ύπνου ως προφύλαξη sleep_disable (); } void setup () {Serial.begin (9600); // Εισάγετε τον κατασκευαστικό για τη βιβλιοθήκη cfg.iface_type = ATCA_I2C_IFACE; // Τύπος επικοινωνίας -> I2C mode cfg.devtype = ATECC608A; // Τύπος τσιπ cfg.atcai2c.slave_address = 0XC0; // I2C adresse (προεπιλεγμένη τιμή) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Καθυστέρηση αφύπνισης (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; // Αποστολή δεδομένων rslt = radio.write (& wake_packet, sizeof (wake_packet)); if (rslt) {// Έναρξη ακρόασης radio.startListening (); ενώ (radio.available ()) {uint8_t απάντηση [32]; radio.read (& απάντηση, sizeof (απάντηση)); uint8_t node_id [3]; uint8_t cypher [16]; memcpy (node_id, απάντηση, 3); memcpy (cypher, απάντηση + 3, 16); εάν ((int) node_id == ID_NODE) {uint8_t έξοδος [16]; Κατάσταση ATCA_STATUS = aes_basic_decrypt (& cfg, cypher, 16, output, AES_KEY); if (status == ATCA_SUCCESS) {Serial.println ("Αποκρυπτογραφημένα δεδομένα:"); για (size_t i = 0; i <16; i ++) {Serial.print ((char) έξοδος ); }}}}} else {Serial.println ("Ο Ack δεν λαμβάνει για το πακέτο Wakup"); } // Λειτουργία ύπνου 8 δευτερόλεπτα sleepmode (); }

Αν έχετε απορίες, είμαι εδώ για να σας απαντήσω

Βήμα 4: 4. Προχωρήστε παραπέρα

Αυτό το παράδειγμα είναι απλό, ώστε να μπορείτε να βελτιώσετε αυτό το έργο

Βελτιώσεις:

  • Το AES 128 είναι βασικό και μπορείτε να χρησιμοποιήσετε έναν άλλο αλγόριθμο AES ως AES CBC για να είναι ασφαλέστερο.
  • Αλλάξτε την ασύρματη μονάδα (το NRF24L01 περιορίζεται από ωφέλιμο φορτίο 23 Bytes)

Εάν βλέπετε βελτίωση, εξηγήστε το στην περιοχή συζήτησης

Βήμα 5: Συμπέρασμα

Ελπίζω ότι αυτό το άρθρο θα είναι χρήσιμο για εσάς. Συγγνώμη αν έκανα λάθος στο κείμενό μου, αλλά τα αγγλικά δεν είναι η κύρια γλώσσα μου και μιλάω καλύτερα από ό, τι γράφω.

Ευχαριστώ που διαβάσατε τα πάντα.

Απόλαυσέ το.

Συνιστάται: