ESP NOW encryption not working

freemang
Posts: 4
Joined: Tue Mar 19, 2024 5:29 pm

ESP NOW encryption not working

Postby freemang » Tue Mar 19, 2024 5:38 pm

Hello , I need your assistance with this code:

I have 2 ESP32-S3 dev kits, and I need to communicate between them for short range, small packets and encrypted.

I decided to use ESP NOW protocol.

In my following code:

I create a wifi AP with defined name.

Search this name .

when I find it (and filter own machine), I captured his MAC address. (This currently work only for 2 devices setup)

Initiate ESP NOW protocol with captured MAC address(including encryption)

Packets will send using serial monitor.

I run the same code on both devices.

I use Arduino IDE

The issue:

When I disable encryption (peerInfo.encrypt = false) the communication works.

When I enable encryption (peerInfo.encrypt = true) I get the message "Send success" but other device dont receive the message.

What do you think can be the issue ?

This is the code:

Code: Select all


#include <esp_now.h>
#include <WiFi.h>

esp_now_peer_info_t peerInfo; // Global copy of slave
static const char* PMK_KEY_STR = "wQsx=?a_n;#r49&A"; // PMK key, 16 bytes long
static const char* LMK_KEY_STR = "A4n8=?wQsx;#_49r"; // LMK key, 16 bytes long 
 
  // Generate random string
String RandString(int MaxSTR){
  const char possible[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{}],<>.?/";
  String RTN;
  for(int i = 0; i < MaxSTR; i++){
    RTN += possible[ esp_random() % strlen(possible) + 1  ];
  }
  return RTN;
}

String WiFissid = "DBY";
String MyFi = WiFissid + esp_random() % 256;
int CHN = 9;

typedef struct struct_message {
    char data[250]; // Adjust size as needed
}

struct_message;
struct_message myData;

  // Callback when data is sent
void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Send Success" : "Send Fail");
}

  // Callback when data is received
void on_data_recv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Received: %s\n", myData.data);
}

  // initize ESP NOW
void setup_esp_now(uint8_t broadcastAddress[6]) {
  Serial.println("Initizing ESP-NOW");
    // init ESP NOW
  if (esp_now_init() != ESP_OK) {
      Serial.println("Error initializing ESP-NOW");
      return;
  }
  
  // register collbackes
  esp_now_register_send_cb(on_data_sent);
  esp_now_register_recv_cb(on_data_recv);

  memset(&peerInfo, 0, sizeof(peerInfo));
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = CHN;
  peerInfo.encrypt = true;

  for (uint8_t i = 0; i < 16; i++) {
    peerInfo.lmk[i] = LMK_KEY_STR[i];
  }
  
  if (esp_now_set_pmk((uint8_t *)PMK_KEY_STR) != ESP_OK) {
    Serial.println("Failed to set PMK");
    return;  }
  // TODO security is not working !

  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
  Serial.println("Failed to add peer");
  return;  }
}

  // Initize wifi
void initWiFi(){
  WiFi.mode(WIFI_STA); //station and AP
  WiFi.disconnect();
  if (!WiFi.softAP(MyFi, RandString(16), CHN, false, 2)) { // Creating wifi
    Serial.print("Soft AP creation failed.");
  while(1);
  } else{
    Serial.print("Wifi created secsesfuly: ");
    Serial.println(MyFi);
  }
}

  //Scan for networks
bool ScanNetwork(){
  Serial.println("Scanning for Wi-Fi networks...");
  int n = WiFi.scanNetworks();
  bool NetFound = false;
  if (n == 0) {
    Serial.println("No networks found.");
  } else {
    Serial.print(n);
    Serial.println(" networks found:");
    for (int i = 0; i < n; ++i) {
      if (WiFi.SSID(i).indexOf(WiFissid) >= 0 & WiFi.SSID(i) != MyFi ){
        Serial.print(WiFi.SSID(i)); // print found wifi
        Serial.print(" (");  Serial.print(WiFi.RSSI(i));  Serial.print(" dBm) - "); 
        const uint8_t* bssid = WiFi.BSSID(i);// Retrieve and print the BSSID (MAC address)
        Serial.print("MAC: ");
        uint8_t broadcastAddress[6];
        for (int j = 0; j < 6; ++j) {
          Serial.print(bssid[j], HEX);
          if (j < 5) Serial.print(":");
          broadcastAddress[j] = (uint8_t) bssid[j];
          }
        Serial.println();
        NetFound = true;
        setup_esp_now(broadcastAddress); // Start ESP NOW
      } 
    }
    if (!NetFound){
      NetFound = false;
      Serial.print(WiFissid);
      Serial.println(" not found");
    }
  }
  WiFi.scanDelete();// clean up ram
  return NetFound;
}

void setup() {
  Serial.begin(115200);
  initWiFi();
  delay(100);
  while (!ScanNetwork()){
    delay(1000); //Scan networks until found 
  }
}

void loop() {
  if (Serial.available()) {
    String input = Serial.readStringUntil('\n');
    memset(&myData, 0, sizeof(myData));
    input.toCharArray(myData.data, sizeof(myData.data));
    esp_err_t result = esp_now_send(peerInfo.peer_addr, (uint8_t *) &myData, sizeof(myData));
    if (result == ESP_OK) {
      Serial.println("Sending message ...");
    } else {
      Serial.println("Error sending message");
    }
  }

}
thanks

liaifat85
Posts: 200
Joined: Wed Dec 06, 2023 2:46 pm

Re: ESP NOW encryption not working

Postby liaifat85 » Fri Mar 22, 2024 9:56 am

When you enable encryption in ESP NOW by setting peerInfo.encrypt to true, you need to ensure that both devices share the same encryption keys. In your code, you are setting the encryption keys for the peer device (peerInfo.lmk), but you also need to set the encryption keys for your own device.

To set the encryption keys for your own device, you can use the esp_now_set_pmk function. However, in your code, you are currently setting the PMK (Pairwise Master Key) using a hardcoded string:

Code: Select all

if (esp_now_set_pmk((uint8_t *)PMK_KEY_STR) != ESP_OK) {
    Serial.println("Failed to set PMK");
    return;
}
Here is also a tutorial on ESP-NOW. This is based on one ESP32 and one ESP8266. This may also give you some clues: https://www.theengineeringprojects.com/ ... p8266.html

freemang
Posts: 4
Joined: Tue Mar 19, 2024 5:29 pm

Re: ESP NOW encryption not working

Postby freemang » Fri Mar 22, 2024 2:41 pm

Hi liaifat85

Thank you for the answer.
1. In your example I cannot find any reference for encryption method, as I mansion in my post, the code works well when setting encryption to false.
2. Please be clarify this sentence:
To set the encryption keys for your own device, you can use the esp_now_set_pmk function. However, in your code, you are currently setting the PMK (Pairwise Master Key) using a hardcoded string:

As I understand the PMK need to be equal on both devices.

In my farther investigation running the following code both devices IS WORKING AND I AM ABLE TO SEND ENCRYPTION MESSAGES (only manually change the device MAC address.
This code is working:

Code: Select all

/* ESP NOW with security
Working script
*/

 #include <esp_now.h>
 #include <WiFi.h>

 typedef struct struct_message {
     char data[250]; // Adjust size as needed
 } struct_message;

 struct_message myData;

 // Replace with the MAC address of the other ESP32-S3 unit
 uint8_t broadcastAddress[] = {0x84, 0xfc, 0xe6, 0x6d, 0x66, 0x10}; //ESP32-S3 (2)
//  uint8_t broadcastAddress[] = {0x84, 0xfc, 0xe6, 0x69, 0xe2, 0xA8}; //ESP32-S3 (3)

 // Callback when data is sent
 void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Send Success" : "Send Fail");
 }

 // Callback when data is received
 void on_data_recv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Received: %s\n", myData.data);
 }

 void setup_esp_now() {
  Serial.println("Initizing ESP-NOW");
  if (esp_now_init() != ESP_OK) {
      Serial.println("Error initializing ESP-NOW");
      return;
  }

  esp_now_register_send_cb(on_data_sent);
  esp_now_register_recv_cb(on_data_recv);

  esp_now_peer_info_t peerInfo;
  memset(&peerInfo, 0, sizeof(peerInfo));
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;
  peerInfo.encrypt = true; // Enable encryption

  // Assuming you have already configured the LMK before this setup
  // esp_now_set_pmk((uint8_t *)"00XXmkwei/lpPÇf"); //where `lmk` is the Local Master Key
  esp_now_set_pmk((uint8_t *)"wQÇx=?a_n;#r49&A"); //where `lmk` is the Local Master Key

  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
  Serial.println("Failed to add peer");
  return;  }
 }

 void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA); // Set device as a Wi-Fi Station
  Serial.println("ESP-NOW with encryption, send message using terminal.");
  setup_esp_now();
 }

 void loop() {
  if (Serial.available()) {
    String input = Serial.readStringUntil('\n');
    memset(&myData, 0, sizeof(myData));
    input.toCharArray(myData.data, sizeof(myData.data));
    esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
    if (result == ESP_OK) {
      Serial.println("Message sent successfully");
    } else {
      Serial.println("Error sending message");  }
  }
 }
So I dont understand why this code is working and the original post code is not working.

Who is online

Users browsing this forum: No registered users and 53 guests