Language: EN

autentificacion-en-esp32

What is authentication and how to use it on ESP32

The authentication is a fundamental process in any communication system, including those we make with an ESP32.

It consists of verifying the identity of a user, device, or entity before allowing access to a resource or service.

In any project that we intend to expose to the public, authentication is essential to protect our communications, data, and systems against unauthorized access.

So let’s look at the different methods we have available to implement it on a device like the ESP32.

Authentication is often combined with other security mechanisms, such as encryption, to ensure the integrity and confidentiality of the data.

Types of authentication on the ESP32

On the ESP32, we can implement several authentication methods, depending on the system requirements and our project:

  • Password-based authentication: The most common method, where a user or device provides a password to verify their identity.
  • Token-based authentication: Uses temporary tokens (like JWT) to validate identity.
  • Device authentication via certificates: Employs digital certificates to verify the identity of a device.
  • Message authentication: Ensures that messages come from a trusted source through digital signatures.

Next, we’ll see how to implement each of these methods on the ESP32.

Password-based authentication

Password-based authentication is the simplest and most widely used method. It consists of comparing a password provided by the user with one stored in the system.

To implement this method, we can store a password in the memory of the ESP32 (for example, in EEPROM or flash memory) and compare it with the user input.

#include <WiFi.h>

const char* ssid = "YourWiFiNetwork";
const char* password = "YourWiFiPassword";

String storedPassword = "secret123"; // Stored password

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
}

void loop() {
  if (Serial.available()) {
    String enteredPassword = Serial.readString(); // Read the entered password
    enteredPassword.trim(); // Remove whitespace

    if (enteredPassword == storedPassword) {
      Serial.println("Authentication successful");
    } else {
      Serial.println("Authentication failed");
    }
  }
}
  • Secure storage: Never store passwords in plain text. Use hash functions like SHA-256 to store only the hash of the password.
  • Protection against brute force attacks: Limit the number of failed attempts to prevent brute force attacks.

Token-based authentication (JWT)

JWT (JSON Web Tokens) are a secure way to authenticate users or devices. A JWT is an encoded token that contains information about the user’s identity and permissions.

To use JWT on the ESP32, we need a library like ArduinoJson to handle the JSON format and a function to verify the token’s signature.

#include <WiFi.h>
#include <ArduinoJson.h>
#include <base64.h>

const char* ssid = "YourWiFiNetwork";
const char* password = "YourWiFiPassword";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
}

bool verifyJWT(String token) {
  // Decode the JWT token
  int dot1 = token.indexOf('.');
  int dot2 = token.indexOf('.', dot1 + 1);

  String header = token.substring(0, dot1);
  String payload = token.substring(dot1 + 1, dot2);
  String signature = token.substring(dot2 + 1);

  // Verify the signature (simplified)
  // In a real case, you would use a cryptography library to verify the signature.
  return true; // Simulated successful verification
}

void loop() {
  if (Serial.available()) {
    String token = Serial.readString(); // Read the JWT token
    token.trim(); // Remove whitespace

    if (verifyJWT(token)) {
      Serial.println("Authentication successful with JWT");
    } else {
      Serial.println("Authentication failed with JWT");
    }
  }
}

Device authentication via certificates

Certificate-based authentication is a more secure method that uses digital certificates to verify the identity of a device. This method is common in IoT applications where security is critical.

The ESP32 supports TLS/SSL, allowing the use of certificates to authenticate devices in secure connections.

#include <WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid = "YourWiFiNetwork";
const char* password = "YourWiFiPassword";

const char* server = "yourserver.com";
const char* certificate = "-----BEGIN CERTIFICATE-----\n"
                          "YOUR_CERTIFICATE_HERE\n"
                          "-----END CERTIFICATE-----\n";

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  client.setCACert(certificate); // Configure the certificate
}

void loop() {
  if (!client.connected()) {
    if (client.connect(server, 443)) {
      Serial.println("Secure connection established");
      client.println("GET / HTTP/1.1");
      client.println("Host: " + String(server));
      client.println("Connection: close");
      client.println();
    } else {
      Serial.println("Connection error");
    }
  }

  while (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
  }
}

Message authentication

Message authentication ensures that the received messages come from a trusted source and have not been altered. This is achieved through digital signatures or message authentication codes (MAC).

We can use algorithms like HMAC-SHA256 to authenticate messages.

#include <WiFi.h>
#include <mbedtls/md.h>

const char* ssid = "YourWiFiNetwork";
const char* password = "YourWiFiPassword";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
}

String calculateHMAC(String message, String key) {
  byte hmacResult[32];
  mbedtls_md_context_t ctx;
  mbedtls_md_init(&ctx);
  mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
  mbedtls_md_hmac_starts(&ctx, (const unsigned char*)key.c_str(), key.length());
  mbedtls_md_hmac_update(&ctx, (const unsigned char*)message.c_str(), message.length());
  mbedtls_md_hmac_finish(&ctx, hmacResult);
  mbedtls_md_free(&ctx);

  String result;
  for (int i = 0; i < 32; i++) {
    char str[3];
    sprintf(str, "%02x", (int)hmacResult[i]);
    result += str;
  }
  return result;
}

void loop() {
  if (Serial.available()) {
    String message = Serial.readString(); // Read the message
    message.trim(); // Remove whitespace

    String key = "secretKey";
    String hmac = calculateHMAC(message, key);

    Serial.println("Calculated HMAC: " + hmac);
  }
}