جدول المحتويات:

الاتصالات اللاسلكية المشفرة اردوينو: 5 خطوات
الاتصالات اللاسلكية المشفرة اردوينو: 5 خطوات

فيديو: الاتصالات اللاسلكية المشفرة اردوينو: 5 خطوات

فيديو: الاتصالات اللاسلكية المشفرة اردوينو: 5 خطوات
فيديو: شرطي يشرح طريقة فتح نافذة السيارة في حال نسيت المفتاح بالداخل #shorts 2024, شهر نوفمبر
Anonim
الاتصالات اللاسلكية المشفرة اردوينو
الاتصالات اللاسلكية المشفرة اردوينو

مرحبا بالجميع،

في هذا المقال الثاني ، سأشرح لك كيفية استخدام شريحة Atecc608a لتأمين اتصالك اللاسلكي. لهذا ، سأستخدم NRF24L01 + للجزء اللاسلكي و Arduino UNO.

تم تصميم الرقاقة الدقيقة ATECC608A بواسطة MicroChip وحصلت على أدوات أمان متعددة. على سبيل المثال ، يمكن لهذه الشريحة تخزين مفاتيح ECC ومفاتيح AES (لـ AES 128) و SHA2 Hash.

المقال: NRF24L01 + Arduino UNO + ATECC608A

أثناء الاتصال بين جهازي إنترنت الأشياء ، يمكن أن توجد هجمات متعددة: رجل معتدل ، نسخة من المعلومات والمزيد.. لذا فكرتي بسيطة للغاية:

  1. استخدام البيانات المشفرة بين اثنين أو أكثر من عناصر إنترنت الأشياء.
  2. لوازم منخفضة التكلفة
  3. يمكن أن تعمل مع Arduino UNO

في حالتي ، أستخدم

  • Atecc608a لتخزين مفتاح AES الخاص بي ولتشفير / فك تشفير بياناتي.
  • Arduino Uno كمتحكم دقيق
  • NRF24L01 لإرسال بياناتي

تحتاج إلى اتباع هذه الخطوات لهذا المشروع:

  1. قم بإعداد شريحة ATECC608A
  2. قم بعمل الدائرة (العقدة الرئيسية والعقدة التابعة)
  3. جزء التعليمات البرمجية
  4. واصل !

بالنسبة للخطوات الأولى "إعداد الشريحة ATECC608A" ، كتبت مقالًا آخر يشرح كل خطوة بالترتيب. الرابط هنا: https://www.instructables.com/id/Secure-C Communication-Arduino/

إبدأ الآن !

اللوازم

لهذا المشروع تحتاج:

  • 2 Arduino UNO أو Arduino NANO أو Arduino Mega
  • بعض الأسلاك
  • 2 Atecc608a (تكلفة كل منها أقل من 0.60 دولار)
  • 2 NRF24L01 +
  • 2 مكثف (10 μF)
  • الألواح

رابط إلى مقالتي الذي يشرح كيفية إعداد الشريحة ATECC608A -> كيفية إعداد Atecc608a

الخطوة 1: 1. قم بإعداد Atecc608a

1. قم بإعداد Atecc608a
1. قم بإعداد Atecc608a
1. قم بإعداد Atecc608a
1. قم بإعداد Atecc608a

لن أفصل كل خطوة يجب اتباعها لإعداد ATECC608A لأنني كتبت مقالًا كاملاً يشرح كل خطوات للقيام بذلك. لإعداده ، تحتاج إلى اتباع "الخطوة 4" من هذه المقالة المسماة "2. تكوين الشريحة (Atecc608a)"

الرابط هو: كيفية إعداد ATECC608A

تحتاج أيضًا إلى وضع نفس التكوين لـ Atecc608a والجانب الرئيسي والجانب التابع ، وإلا فلن تتمكن من فك تشفير بياناتك

تحذير:

لإعداد هذه الشريحة ، عليك اتباع كل خطوات المقالة أعلاه بالترتيب. إذا كانت إحدى الخطوات مفقودة أو لم يتم قفل الشريحة ، فلن تتمكن من القيام بهذا المشروع

بقية:

خطوة لمتابعة هذا:

  • قم بإنشاء قالب التكوين
  • اكتب هذا القالب على الشريحة
  • قفل منطقة التكوين
  • اكتب مفتاح AES (128 بت) في الفتحة
  • قفل منطقة البيانات

الخطوة 2: 2. تصميم الدائرة (الرئيسي والعبد)

2. تصميم الدائرة (السيد والعبد)
2. تصميم الدائرة (السيد والعبد)
2. تصميم الدائرة (السيد والعبد)
2. تصميم الدائرة (السيد والعبد)

في هذا المشروع ، سيكون لديك عقدة رئيسية وعقدة تابعة.

ستقوم العقدة الرئيسية بطباعة البيانات المرسلة بواسطة العقدة التابعة بشكل واضح. سيطلب بيانات من العقدة التابعة كل مرة.

سوف تستمع العقدة التابعة إلى "الشبكة" وعندما تتلقى "طلب البيانات" ، ستقوم بإنشائها وتشفيرها وإرسالها إلى العقدة الرئيسية.

بالنسبة للجانبين ، فإن الدائرة الرئيسية والعبد هي نفسها:

  • نانو اردوينو واحد
  • واحد ATECC608A
  • واحد NRF24L01

لقد أرفقت الدائرة بهذه الخطوة (صورة cf أعلاه).

بالنسبة لـ ATECC608A إلى Arduino UNO ، هذا هو 8 دبوس soic. أضفت "العرض العلوي" أعلاه:

  • أردوينو 3.3 فولت -> رقم التعريف الشخصي 8 (Atecc608a)
  • أردوينو أرضي -> PIN 4 (Atecc608a)
  • ARDUINO A4 (SDL) -> PIN 5 (Atecc608a)
  • ARDUINO A5 (SCL) -> PIN 6 (Atecc608a)

من أجل NRF24L01 إلى Arduino:

  • أردوينو 3.3 فولت -> VCC (nrf24l01)
  • أردوينو أرضي -> GND (nrf24l01)
  • أردوينو 9-> سي (nrf24l01)
  • أردوينو 10 -> CSN (nrf24l01)
  • أردوينو 11-> MOSI (nrf24L01)
  • أردوينو 12 -> MISO (nrf24l01)
  • أردوينو 13-> SCK (nrf24l01)
  • ARDUINO 3 -> IRQ (nrf24l01) -> فقط للعقدة التابعة ، غير مستخدمة في الوضع الرئيسي

لماذا استخدام دبوس IRQ الخاص بـ NRF24L01

يعتبر دبوس IRQ مفيدًا للغاية ، حيث يسمح هذا الدبوس بقول (LOW) عند تلقي حزمة بواسطة NRF24L01 ، حتى نتمكن من إرفاق مقاطعة بهذا الدبوس لإيقاظ العقدة التابعة.

الخطوة 3: 3. الكود (Slave and Master)

3. القانون (العبد والسيد)
3. القانون (العبد والسيد)

عقدة الرقيق

أستخدم توفير الطاقة للعقدة التابعة لأنها لا تحتاج إلى الاستماع طوال الوقت.

كيف يعمل: العقدة التابعة تستمع وتنتظر لتلقي "حزمة تنبيه". يتم إرسال هذه الحزمة بواسطة العقدة الرئيسية لطلب البيانات من العبد.

في حالتي ، أستخدم مصفوفة من نوعين int:

// حزمة الاستيقاظ

const int wake_packet [2] = {20، 02} ؛

إذا تلقت عقدي حزمة ،

  1. تستيقظ ، اقرأ هذه الحزمة ، إذا كانت الحزمة عبارة عن "تنبيه" ،
  2. تولد البيانات ،
  3. تشفير البيانات ،
  4. أرسل البيانات للسيد ، انتظر حزمة ACK ،
  5. نايم.

بالنسبة لتشفير AES ، أستخدم مفتاحًا في الفتحة رقم 9.

هذا هو الكود الخاص بي للعقدة التابعة

# تضمين "Arduino.h" # تضمين "avr / sleep.h" # تضمين "avr / wdt.h"

# تضمين "SPI.h"

# تضمين "nRF24L01.h" # تضمين "RF24.h"

# تضمين "Wire.h"

// مكتبة ATECC608A

# تضمين "ATECCX08A_Arduino / cryptoauthlib.h" # تضمين "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]؛ قراءة الراديو (والبيانات ، 32) ؛ if (data [0] == 20 && data [1] == 02) {float temp = 17.6؛ همهمة عائمة = 16.4 ؛

uint8_t data [16] ؛

uint8_t cypherdata [16] ؛

// أنشئ سلسلة لتعيين كل قيمي

// كل قيمة مفصولة بعلامة "|" و "$" يعني نهاية البيانات // تحذير: يجب أن يكون أقل من 11 طول سلسلة tmp_str_data = سلسلة (ID_NODE) + "|" + سلسلة (درجة الحرارة ، 1) + "|" + سلسلة (همهمة ، 1) + "$" ؛ // حجم 11 Serial.println ("tmp_str_data:" + tmp_str_data) ؛

tmp_str_data.getBytes (data، sizeof (data)) ؛

// تشفير البيانات

حالة ATCA_STATUS = aes_basic_encrypt (& cfg، data، sizeof (data)، cypherdata، AES_KEY) ؛ إذا (الحالة == ATCA_SUCCESS) {long rand = random ((long) 10000، (long) 99999) ؛

// إنشاء UUID بناءً على الرقم الأول الثلاثة = عقدة المعرف

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)) ؛ // توقف عن الاستماع إلى الراديو.

منطقي 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 addresse (القيمة الافتراضية) cfg.atcai2c.bus = 1 ؛ cfg.atcai2c.baud = 100000 ، cfg.wake_delay = 1500 ؛ // تأخير الاستيقاظ (1500 مللي ثانية) 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 = Pin at LOW attachInterrupt (1، wakeUpIRQ، FALLING) ؛ }

حلقة فارغة()

{ // لا حاجة }

العقدة الرئيسية

تستيقظ العقدة الرئيسية كل 8 ثوانٍ لطلب البيانات من العقدة التابعة

كيف يعمل: ترسل العقدة الرئيسية حزمة "WakeUP" إلى التابع وبعد انتظار إجابة العبد بالبيانات.

في حالتي ، أستخدم مصفوفة من نوعين int:

// حزمة الاستيقاظ

const int wake_packet [2] = {20، 02} ؛

إذا أرسلت العقدة التابعة حزمة ACK بعد أن أرسل السيد حزمة WakeUp:

  1. الإعداد الرئيسي في وضع الاستماع وانتظر الاتصال
  2. إذا كان التواصل
  3. استخرج أول 8 بايت ، ونهب البايتات الثلاثة الأولى من 8 بايت ، إذا كانت هذه هي عقدة المعرف
  4. استخراج 16 بايت من سايفر
  5. فك تشفير البيانات
  6. اطبع البيانات في المسلسل
  7. وضع السكون

بالنسبة لتشفير AES ، أستخدم مفتاحًا في الفتحة رقم 9.

هذا هو الكود الخاص بي للعقدة الرئيسية

# تضمين "Arduino.h"

# تضمين "avr / sleep.h" # تضمين "avr / wdt.h" # تضمين "SPI.h" # تضمين "nRF24L01.h" # تضمين "RF24.h" # تضمين "Wire.h" // مكتبة ATECC608A # تتضمن "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 () ؛ // تعطيل المراقبة} وضع النوم الفارغ () {// تعطيل ADC ADCSRA = 0 ؛ // مسح مختلف "إعادة تعيين" أعلام MCUSR = 0 ؛ // السماح بالتغييرات ، وتعطيل إعادة تعيين WDTCSR = بت (WDCE) | بت (WDE) ؛ // ضبط وضع المقاطعة والفاصل الزمني WDTCSR = بت (WDIE) | بت (WDP3) | بت (WDP0) ؛ // تعيين WDIE ، وتأخير 8 ثوانٍ wdt_reset () ؛ // إعادة تعيين مجموعة المراقبة (SLEEP_MODE_PWR_DOWN) ؛ noInterrupts () ، // التسلسل الزمني يتبع sleep_enable () ؛ // إيقاف تشغيل تمكين اللون البني في البرنامج MCUCR = بت (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 addresse (القيمة الافتراضية) cfg.atcai2c.bus = 1 ؛ cfg.atcai2c.baud = 100000 ، cfg.wake_delay = 1500 ؛ // تأخير الاستيقاظ (1500 مللي ثانية) 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) ؛ } حلقة فارغة () {bool rslt؛ // إرسال البيانات rslt = radio.write (& wake_packet، sizeof (wake_packet)) ؛ if (rslt) {// Start Listening 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، answer، 3) ؛ memcpy (سايفر ، إجابة + 3 ، 16) ؛ إذا ((int) node_id == ID_NODE) {uint8_t output [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 ) ؛ }}}}} else {Serial.println ("Ack not get for Wakup Packet")؛ } // وضع السكون 8 ثوانٍ وضع السكون () ؛ }

إذا كان لديك سؤال ، فأنا هنا للإجابة عليه

الخطوة 4: 4. اذهب أبعد

هذا المثال بسيط حتى تتمكن من تحسين هذا المشروع

تحسينات:

  • يعد AES 128 أساسيًا ويمكنك استخدام خوارزمية أخرى لـ AES مثل AES CBC لتكون أكثر أمانًا.
  • تغيير الوحدة اللاسلكية (NRF24L01 محدود بحمولة 23 بايت)

إذا رأيت تحسينًا يجب القيام به ، فشرح ذلك في منطقة المناقشة

الخطوة 5: الخاتمة

آمل أن تكون هذه المقالة مفيدة لك. آسف إذا أخطأت في نصي ولكن اللغة الإنجليزية ليست لغتي الرئيسية وأنا أتحدث أفضل مما أكتب.

شكرا لقراءة كل شيء.

استمتع بها.

موصى به: