Language: EN

como-usar-aes128-en-esp32

What is AES-128 and how to use it on ESP32

In this tutorial, we will learn what AES-128 is, and how to use it on an ESP32 to securely encrypt and decrypt data.

AES-128 encryption is a very secure symmetric encryption method widely used to protect data in embedded systems like the ESP32.

It uses a 128-bit secret key to encrypt and decrypt data, providing a very high level of security (basically unbreakable).

But before we see how to use it with an ESP32, let’s briefly look at what CBC AES-128 is.

What is CBC AES-128?

AES (Advanced Encryption Standard) is a symmetric encryption algorithm that uses a 128, 192, or 256-bit key to encrypt and decrypt data.

The algorithm was selected by the National Institute of Standards and Technology (NIST) as the encryption standard for the United States government in 2001 due to its efficiency and high security.

Key Features of CBC AES-128

  • 128-bit key: AES-128 uses a 128-bit key, which offers a balance between security and efficiency in embedded systems.
  • Block chaining: CBC chains data blocks, meaning each encrypted block depends on the previous block.
  • Initialization vector (IV): CBC requires a unique IV for each encryption operation, ensuring that two identical messages produce different encrypted results.

128-bit encryption is the smallest of them and, logically, the one that requires the least resources. Nevertheless, the level of security it offers is very high.

AES-128 encryption requires that the data be multiples of 16 bytes. If the data does not meet this requirement, padding must be applied.

Meanwhile, CBC (Cipher Block Chaining) is a mode of operation that adds security to AES encryption by chaining data blocks, making each encrypted block depend on the previous one.

Implementing CBC AES-128 on ESP32

The ESP32 uses the integrated AES-128 module in its hardware to perform encryption and decryption operations.

To access this module, we will use the mbedtls library, which provides implementations of various cryptographic algorithms, including AES.

#include <mbedtls/aes.h>

To encrypt data using CBC AES-128, we will follow these steps:

  1. Initialize the AES context: Set up the AES context with the key and IV.
  2. Encrypt the data: Apply CBC AES-128 encryption to the data.
#include <mbedtls/aes.h>
#include <string.h>

void encrypt_cbc_aes128(const uint8_t *key, const uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length) {
    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes);

    // Set the key
    mbedtls_aes_setkey_enc(&aes, key, 128);

    // Encrypt the data in CBC mode
    mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iv, input, output);

    mbedtls_aes_free(&aes);
}

The decryption process is similar to encryption, but using the MBEDTLS_AES_DECRYPT function.

void decrypt_cbc_aes128(const uint8_t *key, const uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length) {
    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes);

    // Set the key
    mbedtls_aes_setkey_dec(&aes, key, 128);

    // Decrypt the data in CBC mode
    mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iv, input, output);

    mbedtls_aes_free(&aes);
}

Complete Example

Here is the complete example of encryption and decryption using CBC AES-128 on the ESP32, neatly separated into files for your convenience 😉

#include "mbedtls/aes.h"
#include "mbedtls/cipher.h"

#define INPUT_LENGTH 16


void encrypt(char* input, char* key, unsigned char* output)
{
	unsigned char iv[] = { 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

	mbedtls_aes_context aes;
	mbedtls_aes_init(&aes);
	mbedtls_aes_setkey_enc(&aes, (const unsigned char*)key, strlen(key) * 8);
	mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, INPUT_LENGTH, iv, (const unsigned char*)input, output);
	mbedtls_aes_free(&aes);

}

void decrypt(unsigned char* input, char* key, unsigned char* output)
{
	unsigned char iv[] = { 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

	mbedtls_aes_context aes;
	mbedtls_aes_init(&aes);
	mbedtls_aes_setkey_enc(&aes, (const unsigned char*)key, strlen(key) * 8);
	mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, INPUT_LENGTH, iv, (const unsigned char*)input, output);
	mbedtls_aes_free(&aes);
}

void setup()
{
	Serial.begin(115200);
	delay(2000);

	char plainText[] = "www.luisllamas.es";
	const uint8_t plainTextSize = sizeof(plainText) / sizeof(char);
	char key[] = "abcdefghijklmnop";

	unsigned char cipherTextOutput[plainTextSize];
	unsigned char decipheredTextOutput[plainTextSize];

	encrypt(plainText, key, cipherTextOutput);
	decrypt(cipherTextOutput, key, decipheredTextOutput);

	Serial.println("\nOriginal plain text:");
	Serial.println(plainText);

	Serial.println("\nCiphered text:");
	for(int i = 0; i < plainTextSize; i++)
	{
		char str[3];

		sprintf(str, "%02x", (int)cipherTextOutput[i]);
		Serial.print(str);
	}

	Serial.println("\n\nDeciphered text:");
	for(int i = 0; i < plainTextSize; i++)
	{
		Serial.print((char)decipheredTextOutput[i]);
	}
}

void loop() {}

And if you run it, you will see something like this

cbc

Extra bonus: ECB Encryption

As a bonus, here’s AES-128 encryption with ECB (instead of CBC). Unlike CBC, ECB does not require an initialization vector, which simplifies its implementation.

However, this makes it vulnerable to repeated patterns. That is, if two blocks of plaintext are identical, they will produce identical ciphertext blocks (which can reveal information about the structure of the message).

The ECB mode is not recommended for encrypting sensitive data due to its lack of randomization.