The MD5 (Message Digest Algorithm 5) is a hash algorithm widely used to generate a 128-bit (16 bytes) value from input data of any size.
This hash value is unique for each input, which means that even a small change in the input data will generate a completely different hash.
Like all hash algorithms, MD5 is a one-way algorithm, meaning that the process cannot be reversed to obtain the original data from the MD5 hash (it is not encryption, it is hashing).
Main features of MD5
- Hash size: 128 bits (16 bytes).
- Speed: MD5 is fast and efficient in terms of processing.
- Deterministic: The same input will always produce the same hash.
- Non-reversible: It is not possible to recover the original data from the hash.
Although MD5 was designed to be secure, vulnerabilities have been discovered that allow collisions (two different inputs that produce the same hash).
For this reason, it is not recommended for security applications.
Although it is not recommended for security applications, it remains useful in contexts where quick data integrity verification is needed (such as files or communications).
Implementing MD5 on the ESP32
The ESP32 has a hardware module for cryptographic operations, but we can also use software libraries to implement MD5.
In this case, we will use the MD5.h
library, which is easy to use and available in the Arduino development environment.
Let’s see how to generate an MD5 hash from a text string on the ESP32.
#include "mbedtls/md.h"
#include "stdlib.h"
void printBlockAsHex(std::vector<uint8_t> data)
{
for(int i = 0; i < data.size(); i++)
{
Serial.printf("%02X ", data[i]);
}
}
std::vector<uint8_t> generateMD5(std::string& text)
{
std::vector<uint8_t> hash(16);
mbedtls_md_context_t ctx;
mbedtls_md_type_t md_type = MBEDTLS_MD_MD5;
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, (const unsigned char*)text.c_str(), text.length());
mbedtls_md_finish(&ctx, hash.data());
mbedtls_md_free(&ctx);
return hash;
}
void setup()
{
Serial.begin(115200);
delay(2000);
std::string message = "www.luisllamas.es";
auto hash = generateMD5(message);
Serial.print(message.c_str());
Serial.print("\nHash: ");
printBlockAsHex(hash);
}
void loop() {}
- Include the MD5 library:
#include <MD5.h>
allows you to use the functions from the library. - Input string: We define a text string (
input
) that we want to hash. - Generate the hash: We use the function
MD5(input)
to calculate the hash of the string. - Display the result: We print the original string and its MD5 hash to the serial monitor.
Practical examples
Although MD5 is not secure for critical applications, it can be useful in the following scenarios:
Data integrity verification
We can use MD5 to verify if a file or dataset has been altered. For example, when transmitting data between devices, we can send the MD5 hash along with the data. The receiver can calculate the hash of the received data and compare it with the sent hash to detect changes.
String calcularHash(String datos) {
return MD5(datos);
}
bool verificarIntegridad(String datos, String hashEnviado) {
String hashCalculado = calcularHash(datos);
return hashCalculado == hashEnviado;
}
Generation of unique identifiers
MD5 can be used to generate unique identifiers from data such as usernames, IP addresses, or timestamps. These identifiers are useful in applications where a unique value is needed but cryptographic security is not required.
String generarID(String nombreUsuario) {
return MD5(nombreUsuario + String(millis()));
}