สารบัญ:

การสื่อสารเข้ารหัสไร้สาย Arduino: 5 ขั้นตอน
การสื่อสารเข้ารหัสไร้สาย Arduino: 5 ขั้นตอน

วีดีโอ: การสื่อสารเข้ารหัสไร้สาย Arduino: 5 ขั้นตอน

วีดีโอ: การสื่อสารเข้ารหัสไร้สาย Arduino: 5 ขั้นตอน
วีดีโอ: สอน วิธี ใช้งาน สื่อสารไร้สาย Arduino NRF24L01 วิธีใช้ NRF24L01 Module ร่วมกับ Arduino 2024, พฤศจิกายน
Anonim
การสื่อสารเข้ารหัสไร้สาย Arduino
การสื่อสารเข้ารหัสไร้สาย Arduino

สวัสดีทุกคน, ในบทความที่สองนี้ ฉันจะอธิบายวิธีใช้ชิป Atecc608a เพื่อรักษาความปลอดภัยให้กับการสื่อสารไร้สายของคุณ สำหรับสิ่งนี้ ฉันจะใช้ NRF24L01+ สำหรับส่วนไร้สายและ Arduino UNO

ไมโครชิป ATECC608A ได้รับการออกแบบโดย MicroChip และมีเครื่องมือรักษาความปลอดภัยมากมาย ตัวอย่างเช่น ชิปนี้สามารถเก็บ ECC Keys, AES Keys (สำหรับ AES 128) และ SHA2 Hash

บทความ: NRF24L01 + Arduino UNO + ATECC608A

ระหว่างการสื่อสารระหว่างสอง IoT Object การโจมตีหลายครั้งสามารถเกิดขึ้นได้: Man Of the Mild, Copy of information และอื่นๆ.. ดังนั้นความคิดของฉันจึงง่ายมาก:

  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 Atec608a (ราคาแต่ละอันน้อยกว่า 0.60$)
  • 2 NRF24L01+
  • 2 ตัวเก็บประจุ (10 μF)
  • เขียงหั่นขนม

ลิงก์ไปยังบทความของฉันที่อธิบายวิธีตั้งค่าชิป ATECC608A -> วิธีการตั้งค่า Atecc608a

ขั้นตอนที่ 1: 1. ตั้งค่า Atec608a

1. ตั้งค่า Atec608a
1. ตั้งค่า Atec608a
1. ตั้งค่า Atec608a
1. ตั้งค่า Atec608a

ฉันจะไม่ให้รายละเอียดทุกขั้นตอนในการติดตามเพื่อตั้งค่า ATECC608A เพราะฉันเขียนบทความฉบับเต็มซึ่งอธิบายทุกขั้นตอนที่ต้องทำ ในการตั้งค่า คุณต้องทำตาม "ขั้นตอนที่ 4" ของบทความนี้ชื่อ " 2. การกำหนดค่าชิป (Atecc608a)"

ลิงค์คือ: วิธีการตั้งค่า ATECC608A

นอกจากนี้ คุณต้องใส่การกำหนดค่าเดียวกันสำหรับ Atecc608a ฝั่งมาสเตอร์และฝั่งทาส มิฉะนั้น คุณจะไม่สามารถถอดรหัสข้อมูลของคุณได้

คำเตือน:

ในการตั้งค่าชิปนี้ คุณต้องปฏิบัติตามทุกขั้นตอนของบทความด้านบนตามลำดับ หากไม่มีขั้นตอนใดขั้นตอนหนึ่งหรือชิปไม่ล็อค คุณจะไม่สามารถทำโปรเจ็กต์นี้ได้

ส่วนที่เหลือ:

ขั้นตอนที่ต้องปฏิบัติตามนี้:

  • สร้างเทมเพลตการกำหนดค่า
  • เขียนเทมเพลตนี้ไปที่ชิป
  • ล็อค Config Zone
  • เขียนคีย์ AES ของคุณ (128 บิต) ลงในช่อง
  • ล็อคโซนข้อมูล

ขั้นตอนที่ 2: 2. การออกแบบวงจร (Master และ Slave)

2. การออกแบบวงจร (Master และ Slave)
2. การออกแบบวงจร (Master และ Slave)
2. การออกแบบวงจร (Master และ Slave)
2. การออกแบบวงจร (Master และ Slave)

ในโครงการนี้ คุณจะมี Master Node และ Slave Node

โหนดหลักจะพิมพ์ข้อมูลที่ส่งโดยโหนดรองอย่างชัดเจน มันจะขอข้อมูลจากโหนดสเลฟทุก ๆ X ครั้ง

โหนดสเลฟจะฟัง "เครือข่าย" และเมื่อได้รับ "คำขอข้อมูล" โหนดจะสร้าง เข้ารหัส และส่งไปยังโหนดหลัก

สำหรับทั้งสองฝ่าย วงจรหลักและรองจะเหมือนกัน:

  • หนึ่ง Arduino Nano
  • ATECC608A. หนึ่งเครื่อง
  • หนึ่ง NRF24L01

ฉันแนบวงจรกับขั้นตอนนี้ (cf ภาพด้านบน)

สำหรับ 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 -> มิโซะ (nrf24l01)
  • ARDUINO 13 -> SCK (nrf24l01)
  • ARDUINO 3 -> IRQ (nrf24l01) -> เฉพาะโหนด Slave เท่านั้น ไม่ได้ใช้ในโหมดมาสเตอร์

เหตุใดจึงต้องใช้พิน IRQ ของ NRF24L01

พิน IRQ มีประโยชน์มาก พินนี้อนุญาตให้พูด (ต่ำ) เมื่อ NRF24L01 ได้รับแพ็กเก็ต ดังนั้นเราสามารถแนบ Interrupt กับพินนี้เพื่อปลุกโหนดสลาฟ

ขั้นตอนที่ 3: 3. รหัส (Slave และ Master)

3. รหัส (ทาสและอาจารย์)
3. รหัส (ทาสและอาจารย์)

โหนดทาส

ฉันใช้การประหยัดพลังงานสำหรับโหนดรองเพราะไม่จำเป็นต้องฟังตลอดเวลา

มันทำงานอย่างไร: โหนดทาสฟังและรอเพื่อรับ "แพ็คเก็ตปลุก" แพ็กเก็ตนี้ถูกส่งโดยโหนดมาสเตอร์เพื่อขอข้อมูลจากสเลฟ

ในกรณีของฉันฉันใช้อาร์เรย์สอง int:

// แพ็กเก็ตปลุก

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

หากโหนดของฉันได้รับแพ็กเก็ต

  1. มันตื่นขึ้น อ่านแพ็กเก็ตนี้ ถ้าแพ็กเก็ตเป็น "Wake UP"
  2. มันสร้างข้อมูล
  3. เข้ารหัสข้อมูล
  4. ส่งข้อมูลไปยังมาสเตอร์รอแพ็กเก็ต ACK
  5. นอน.

สำหรับการเข้ารหัส AES ฉันใช้คีย์ในช่องหมายเลข 9

นี่คือรหัสของฉันสำหรับโหนดทาส

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

#รวม "SPI.h"

#รวม "nRF24L01.h" #รวม "RF24.h"

#รวม "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;

/**

* \brief ทำงานเมื่อมีการตั้งค่าอินเตอร์รัปต์ (IRQ LOW) * * */ void wakeUpIRQ() { while (radio.available()) { int data[32]; radio.read(&data, 32); ถ้า (data[0] == 20 && data[1] == 02) { float temp = 17.6; ลอย hum = 16.4;

ข้อมูล uint8_t[16];

uint8_t cypherdata[16];

// สร้างสตริงเพื่อตั้งค่าทั้งหมดของฉัน

// แต่ละค่าถูกคั่นด้วย "|" และ "$" หมายถึงจุดสิ้นสุดของข้อมูล // WARNING: ต้องมีความยาวน้อยกว่า 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 = aes_basic_encrypt(&cfg, data, sizeof(data), cypherdata, AES_KEY); ถ้า (สถานะ == ATCA_SUCCESS) { แรนด์ยาว = สุ่ม ((ยาว) 10000, (ยาว) 99999);

// สร้าง UUID ตามตัวเลขสามตัวแรก = ID node

สตริง 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)); // หยุดฟัง radio.stopListening();

บูล rslt;

// ส่งข้อมูล rslt = radio.write(&data_to_send, sizeof(data_to_send)); // เริ่มฟัง radio.startListening(); if (rslt) {// สิ้นสุดและโหมดสลีป Serial.println (F ("เสร็จสิ้น")); } } } } }

การตั้งค่าเป็นโมฆะ ()

{ 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 ms) 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, ที่อยู่ทาส); // แนบอินเทอร์รัปต์กับพิน 3 // แก้ไข 1 โดย O หากคุณต้องการอินเตอร์รัปต์กับพิน 2 // FALLING MODE = พินที่ LOW AttachInterrupt (1, wakeUpIRQ, FALLING); }

วงเป็นโมฆะ ()

{ // ไม่จำเป็น }

มาสเตอร์โหนด

โหนดหลักจะปลุกทุก 8 วินาทีเพื่อขอข้อมูลจากโหนดรอง

มันทำงานอย่างไร: โหนดหลักส่งแพ็กเก็ต "WakeUP" ไปยังสเลฟและหลังจากรอคำตอบของสเลฟพร้อมข้อมูล

ในกรณีของฉันฉันใช้อาร์เรย์สอง int:

// แพ็กเก็ตปลุก

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

หากโหนดรองส่งแพ็กเก็ต ACK หลังจากที่มาสเตอร์ส่งแพ็กเก็ต WakeUp:

  1. มาสเตอร์ตั้งค่าในโหมดฟังและรอการสื่อสาร
  2. ถ้าการสื่อสาร
  3. แยกไบต์แรก 8 ไบต์ ปล้น 3 ไบต์แรกของ 8 ไบต์ หากเป็นโหนด ID
  4. แยก 16 ไบต์ของ cypher
  5. ถอดรหัสข้อมูล
  6. พิมพ์ข้อมูลใน Serial
  7. โหมดสลีป

สำหรับการเข้ารหัส AES ฉันใช้คีย์ในช่องหมายเลข 9

นี่คือรหัสของฉันสำหรับโหนดหลัก

#รวม "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 แพ็กเก็ต const int wake_packet[2] = {20, 02}; // สุนัขเฝ้าบ้านขัดจังหวะ ISR (WDT_vect) { wdt_disable (); // ปิดการใช้งาน watchdog } โมฆะ sleepmode () { // ปิดการใช้งาน ADC ADCSRA = 0; // ล้างการตั้งค่าสถานะ "รีเซ็ต" ต่างๆ MCUSR = 0; // อนุญาตการเปลี่ยนแปลง ปิดใช้งานการรีเซ็ต WDTCSR = bit(WDCE) | บิต (WDE); // ตั้งค่าโหมดอินเตอร์รัปต์และช่วงเวลา WDTCSR = bit(WDIE) | บิต(WDP3) | บิต(WDP0); // ตั้งค่า WDIE และหน่วงเวลา 8 วินาที wdt_reset(); // รีเซ็ตสุนัขเฝ้าบ้าน set_sleep_mode (SLEEP_MODE_PWR_DOWN); ไม่มีอินเตอร์รัปต์ (); // ลำดับเวลาตาม sleep_enable(); // ปิดการเปิดใช้ Brown-out ในซอฟต์แวร์ MCUCR = bit(BODS) | บิต (BODSE); MCUCR = บิต (BODS); ขัดจังหวะ (); // รับประกันคำสั่งถัดไปที่ดำเนินการ sleep_cpu(); // ยกเลิกโหมดสลีปเพื่อเป็นการป้องกันไว้ก่อน sleep_disable(); } การตั้งค่าเป็นโมฆะ () { 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 ms) 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, ที่อยู่หลัก); } วงเป็นโมฆะ () { bool rslt; // ส่งข้อมูล rslt = radio.write(&wake_packet, sizeof(wake_packet)); if (rslt) { // เริ่มฟัง radio.startListening (); ในขณะที่ (radio.available ()) { uint8_t answer[32]; radio.read(&answer, sizeof(answer)); 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, เอาต์พุต, AES_KEY); ถ้า (สถานะ == ATCA_SUCCESS) { Serial.println ("ข้อมูลที่ถอดรหัส: "); สำหรับ (size_t i = 0; i < 16; i++) { Serial.print((char)output); } } } } } อื่น { Serial.println ("ไม่ได้รับ Ack สำหรับ Wakup Packet"); } // โหมดสลีป 8 วินาที sleepmode(); }

หากคุณมีคำถาม ฉันพร้อมที่จะตอบมัน

ขั้นตอนที่ 4: 4. ก้าวต่อไป

ตัวอย่างนี้เรียบง่ายเพื่อให้คุณสามารถปรับปรุงโครงการนี้ได้

การปรับปรุง:

  • AES 128 เป็นพื้นฐานและคุณสามารถใช้อัลกอริทึมอื่นของ AES เป็น AES CBC ได้เพื่อความปลอดภัยยิ่งขึ้น
  • เปลี่ยนโมดูลไร้สาย (NRF24L01 ถูกจำกัดโดยเพย์โหลด 23 ไบต์)

หากคุณเห็นว่าต้องปรับปรุง ให้อธิบายในส่วนอภิปราย

ขั้นตอนที่ 5: บทสรุป

ฉันหวังว่าบทความนี้จะเป็นประโยชน์สำหรับคุณ ขออภัยถ้าฉันเขียนผิดในข้อความ แต่ภาษาอังกฤษไม่ใช่ภาษาหลักของฉัน และฉันพูดได้ดีกว่าที่ฉันเขียน

ขอบคุณสำหรับการอ่านทุกอย่าง

สนุกกับมัน.

แนะนำ: