Índice:

Arduino de comunicação criptografada sem fio: 5 etapas
Arduino de comunicação criptografada sem fio: 5 etapas

Vídeo: Arduino de comunicação criptografada sem fio: 5 etapas

Vídeo: Arduino de comunicação criptografada sem fio: 5 etapas
Vídeo: Módulo NRF24L01 com Arduino Controle Remoto RC Dicas para Resolver problemas na comunicação sem fio 2024, Novembro
Anonim
Arduino de comunicação criptografada sem fio
Arduino de comunicação criptografada sem fio

Olá pessoal, Neste segundo artigo, explicarei como usar o chip Atecc608a para proteger sua comunicação sem fio. Para isso utilizarei o NRF24L01 + para a parte Wireless e o Arduino UNO.

O micro chip ATECC608A foi projetado pela MicroChip e tem várias ferramentas de segurança. Por exemplo, este chip pode armazenar chaves ECC, chaves AES (para AES 128) e SHA2 Hash.

O artigo: NRF24L01 + Arduino UNO + ATECC608A

Durante uma comunicação entre dois objetos IoT, vários ataques podem ocorrer: Man Of the light, Cópia de informações e muito mais. Minha ideia é muito simples:

  1. Utilização de dados criptografados entre dois ou mais objetos IoT.
  2. Suprimentos de baixo custo
  3. Pode funcionar com um Arduino UNO

No meu caso, eu uso

  • o Atecc608a para armazenar minha chave AES e para criptografar / descriptografar meus dados.
  • o Arduino Uno como microcontrolador
  • O NRF24L01 para enviar meus dados

Você precisa seguir estas etapas para este projeto:

  1. Configure o chip ATECC608A
  2. Faça o circuito (nó mestre e nó escravo)
  3. Parte do código
  4. Ir além !

Para as primeiras etapas "Configurar o chip ATECC608A", escrevi um outro artigo que explica cada etapa na ordem. O link está aqui:

Agora comece!

Suprimentos

Para este projeto, você precisa de:

  • 2 Arduino UNO ou Arduino NANO ou Arduino Mega
  • Algum fio
  • 2 Atecc608a (cada custo inferior a 0,60 $)
  • 2 NRF24L01 +
  • 2 capacitores (10 μF)
  • Tábuas de pão

Link para o meu artigo que explica como configurar o chip ATECC608A -> Como configurar o Atecc608a

Etapa 1: 1. Configure o Atecc608a

1. Configure o Atecc608a
1. Configure o Atecc608a
1. Configure o Atecc608a
1. Configure o Atecc608a

Não detalharei todas as etapas a seguir para configurar um ATECC608A porque escrevi um artigo completo que explica todas as etapas para fazê-lo. Para configurá-lo, você precisa seguir o "Passo 4" deste artigo denominado "2. Configuração do Chip (Atecc608a)"

O link é: Como configurar um ATECC608A

Além disso, você precisa colocar a mesma configuração para o Atecc608a, lado mestre e lado escravo, caso contrário você não será capaz de descriptografar seus dados

Aviso:

Para configurar este chip, você precisa seguir todas as etapas do artigo acima na ordem. Se uma etapa estiver faltando ou o chip não estiver travado, você não conseguirá realizar este projeto

Restante:

Passo a seguir para isso:

  • Crie um modelo de configuração
  • Escreva este modelo no chip
  • Bloquear a zona de configuração
  • Escreva sua chave AES (128 bits) em um slot
  • Bloqueie a zona de dados

Etapa 2: 2. Projeto do circuito (mestre e escravo)

2. Projeto do circuito (mestre e escravo)
2. Projeto do circuito (mestre e escravo)
2. Projeto do circuito (mestre e escravo)
2. Projeto do circuito (mestre e escravo)

Neste projeto, você terá um nó mestre e um nó escravo.

O nó mestre imprimirá os dados enviados pelo nó escravo em claro. Ele solicitará dados do nó escravo a cada X vez.

O nó escravo ouvirá a "rede" e quando receber um "Pedido de dados", irá gerá-lo, criptografá-lo e enviá-lo ao nó mestre.

Para ambos os lados, mestre e escravo, o circuito é o mesmo:

  • Um Arduino Nano
  • Um ATECC608A
  • Um NRF24L01

Anexei o circuito a esta etapa (veja a imagem acima).

Para o ATECC608A para o Arduino UNO, este é um pino soic de 8. Eu adicionei a "vista de cima" acima:

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

Para o NRF24L01 para o 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) -> apenas para nó Slave, não usado no modo Master

Por que usar o pino IRQ do NRF24L01

O pino IRQ é muito útil, este pino permite dizer (BAIXO) quando um pacote é recebido pelo NRF24L01, então podemos anexar uma interrupção a este pino para despertar o nó escravo.

Etapa 3: 3. o código (escravo e mestre)

3. o código (escravo e mestre)
3. o código (escravo e mestre)

Nó Escravo

Eu uso economia de energia para o nó escravo porque ele não precisa ouvir o tempo todo.

Como funciona: o nó escravo escuta e espera para receber um "pacote Wake UP". Este pacote é enviado pelo nó mestre para solicitar dados do escravo.

No meu caso, uso uma matriz de dois int:

// Pacote Wake UP

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

Se meu nó receber um pacote,

  1. acorde, leia este pacote, se o pacote for um "Wake UP",
  2. ele gera os dados,
  3. criptografar os dados,
  4. envie os dados para o mestre, aguarde um pacote ACK,
  5. dormir.

Para a criptografia AES, uso uma chave no slot número 9.

Este é o meu código para o nó Slave

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

Status ATCA_STATUS;

Rádio RF24 (9, 10);

const uint64_t masteraddresse = 0x1111111111;

const uint64_t slaveaddresse = 0x1111111100;

/**

* / brief Função executada quando a interrupção é definida (IRQ LOW) * * * / void wakeUpIRQ () {while (radio.available ()) {int data [32]; radio.read (& data, 32); if (dados [0] == 20 && dados [1] == 02) {float temp = 17,6; flutuador zumbido = 16,4;

dados uint8_t [16];

uint8_t cypherdata [16];

// Construir uma string para definir todos os meus valores

// Cada valor é separado por um "|" e o "$" significa o fim dos dados // AVISO: Deve ter menos de 11 comprimento String tmp_str_data = String (ID_NODE) + "|" + String (temp, 1) + "|" + Corda (hum, 1) + "$"; // tamanho de 11 Serial.println ("tmp_str_data:" + tmp_str_data);

tmp_str_data.getBytes (dados, sizeof (dados));

// Criptografar os dados

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

// gera um UUID com base nos três primeiros números = nó de ID

String uuid = String (ID_NODE) + String (rand); // Tamanho 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)); // Pare de ouvir radio.stopListening ();

bool rslt;

// Enviar dados rslt = radio.write (& data_to_send, sizeof (data_to_send)); // Comece a ouvir radio.startListening (); if (rslt) {// Fim e modo de espera Serial.println (F ("Concluído")); }}}}}

void setup ()

{Serial.begin (9600);

// Inicie o construtor para a biblioteca

cfg.iface_type = ATCA_I2C_IFACE; // Tipo de comunicação -> modo I2C cfg.devtype = ATECC608A; // Tipo de chip cfg.atcai2c.slave_address = 0XC0; // Endereço I2C (valor padrão) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Atraso de ativação (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); // Anexe a interrupção ao pino 3 // Modifique 1 por O se quiser a interrupção ao pino 2 // FALLING MODE = Pino em LOW attachInterrupt (1, wakeUpIRQ, FALLING); }

void loop ()

{ // Não há necessidade }

Nó Mestre

O nó mestre acorda a cada 8 segundos para solicitar dados do nó escravo

Como funciona: O nó mestre envia um pacote "WakeUP" para o escravo e após espera uma resposta do escravo com os dados.

No meu caso, uso uma matriz de dois int:

// Pacote Wake UP

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

Se o nó escravo enviar um pacote ACK após o mestre enviar um pacote WakeUp:

  1. Master configurado no modo de escuta e aguarde uma comunicação
  2. Se comunicação
  3. Extraia os 8 primeiros bytes, saqueie os três primeiros bytes dos 8 bytes, se este for o nó de ID
  4. Extraia os 16 bytes de cifra
  5. Descriptografar os dados
  6. Imprima os dados em série
  7. Modo dormir

Para a criptografia AES, uso uma chave no slot número 9.

Este é o meu código para o nó mestre

#include "Arduino.h"

#include "avr / sleep.h" #include "avr / wdt.h" #include "SPI.h" #include "nRF24L01.h" #include "RF24.h" #include "Wire.h" // ATECC608A library #include "ATECCX08A_Arduino / cryptoauthlib.h" #include "AES BASIC / aes_basic.h" #define ID_NODE 255 #define AES_KEY (uint8_t) 9 ATCAIfaceCfg cfg; Status ATCA_STATUS; Rádio RF24 (9, 10); const uint64_t masteraddresse = 0x1111111111; const uint64_t slaveaddresse = 0x1111111100; // Pacote Wake UP const int wake_packet [2] = {20, 02}; // interrupção do watchdog ISR (WDT_vect) {wdt_disable (); // desabilita watchdog} void sleepmode () {// desabilita ADC ADCSRA = 0; // limpa vários sinalizadores de "redefinição" MCUSR = 0; // permitir mudanças, desabilitar reset WDTCSR = bit (WDCE) | bit (WDE); // define o modo de interrupção e um intervalo WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // define WDIE e retardo de 8 segundos wdt_reset (); // redefine o watchdog set_sleep_mode (SLEEP_MODE_PWR_DOWN); noInterrupts (); // sequência cronometrada segue sleep_enable (); // desativa a ativação de brown-out no software MCUCR = bit (BODS) | bit (BODSE); MCUCR = bit (BODS); interrupções (); // garante a próxima instrução executada sleep_cpu (); // cancela o sono como precaução sleep_disable (); } void setup () {Serial.begin (9600); // Inicie o construtor para a biblioteca cfg.iface_type = ATCA_I2C_IFACE; // Tipo de comunicação -> modo I2C cfg.devtype = ATECC608A; // Tipo de chip cfg.atcai2c.slave_address = 0XC0; // Endereço I2C (valor padrão) cfg.atcai2c.bus = 1; cfg.atcai2c.baud = 100000; cfg.wake_delay = 1500; // Atraso de ativação (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; // Enviar dados rslt = radio.write (& wake_packet, sizeof (wake_packet)); if (rslt) {// Começar a ouvir radio.startListening (); while (radio.available ()) {uint8_t answer [32]; radio.read (& answer, sizeof (answer)); uint8_t node_id [3]; cifra uint8_t [16]; memcpy (node_id, resposta, 3); memcpy (cifra, resposta + 3, 16); if ((int) node_id == ID_NODE) {uint8_t output [16]; ATCA_STATUS status = aes_basic_decrypt (& cfg, cypher, 16, saída, AES_KEY); if (status == ATCA_SUCCESS) {Serial.println ("Dados descriptografados:"); para (size_t i = 0; i <16; i ++) {Serial.print ((char) output ); }}}}} else {Serial.println ("Ack não recebido para pacote Wakup"); } // Modo de espera 8 segundos sleepmode (); }

Se você tiver alguma dúvida, estou aqui para respondê-la

Etapa 4: 4. Vá mais longe

Este exemplo é simples para que você possa melhorar este projeto

Melhorias:

  • O AES 128 é básico e você pode usar um outro algoritmo do AES como AES CBC para ficar mais seguro.
  • Mude o módulo sem fio (o NRF24L01 é limitado por uma carga útil de 23 bytes)

Se você vir melhorias a serem feitas, explique-as na área de discussão

Etapa 5: Conclusão

Espero que este artigo seja útil para você. Desculpe se me enganei no texto, mas o inglês não é a minha língua principal e falo melhor do que escrevo.

Obrigado por ler tudo.

Aproveite.

Recomendado: