El Padding PKCS#7 (Public Key Cryptography Standards #7) es un esquema de relleno que agrega bytes adicionales al final de los datos para que tengan una longitud múltiplo de un tamaño específico.
Este esquema es muy utilizado en criptografía, ya que muchos algoritmos criptográficos, requieren que los datos tengan una longitud que sea múltiplo del tamaño de bloque.
Así que vamos a ver qué es el Padding PKCS#7, cómo funciona y cómo implementarlo en un ESP3.
Qué es el Padding PKCS#7
El Padding PKCS#7 es un método de relleno que se utiliza para ajustar la longitud de los datos a un tamaño determinado, requerido por otro algoritmo.
Básicamente, los algoritmos criptográficos de bloque (como AES), requieren que los datos tengan una longitud que sea múltiplo del tamaño de bloque (por ejemplo, 16 bytes).
Si los datos no cumplen con este requisito, necesitamos agregar relleno para ajustar su longitud (hasta aquí parecería fácil, ¿no?).
Pero claro, para después poder quitar este relleno y quedarnos con los datos originales hay que poder distinguir los bytes que añadimos de relleno.
Hay varios algoritmos para resolver esto. El Padding PKCS#7 es una solución eficiente y sencilla para este problema.
El esquema Padding PKCS#7 agrega bytes adicionales al final de los datos, donde cada byte agregado tiene el valor del número de bytes añadidos. Esto permite que el receptor pueda identificar y eliminar el relleno de manera.
Ejemplo de Padding PKCS#7
Supongamos que tenemos un algoritmo criptográfico que opera con bloques de 16 bytes y queremos cifrar un mensaje de 25 bytes.
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19
En este caso, necesitamos agregar 7 bytes de relleno para que la longitud total sea 32 bytes (múltiplo de 16).
El Padding PKCS#7 agregará 7 bytes, cada uno con el valor 0x07 (7 en hexadecimal).
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 07 07 07 07 07 07 07
Al recibir el mensaje cifrado, el receptor puede verificar el valor del último byte (0x07) para determinar cuántos bytes de relleno deben eliminarse.
Cómo usar el Padding PKCS#7 en un ESP32
Para utilizar el Padding PKCS#7 en un ESP32 podemos implementar nuestras propias funciones de relleno y eliminación de relleno.
Por aquí os dejo un ejemplo de cómo hacerlo, que incluye las funciones pkcs7_padding
y pkcs7_unpadding
, y una demostración de su uso.
#include <vector>
#include <cstdint>
// Función para imprimir un bloque de datos en formato hexadecimal
void printBlockAsHex(std::vector<uint8_t> data) {
for (int i = 0; i < data.size(); i++) {
Serial.printf("%02X ", data[i]);
}
Serial.println();
}
// Función para aplicar el Padding PKCS#7
std::vector<uint8_t> pkcs7_padding(std::vector<uint8_t>& input) {
std::vector<uint8_t> output(input);
// Calcula la longitud necesaria para que sea múltiplo de 16
size_t padded_length = (input.size() / 16 + 1) * 16;
size_t padToAdd = padded_length - input.size();
// Agrega los bytes de relleno
for (auto i = 0; i < padToAdd; i++) {
output.push_back(padToAdd);
}
return output;
}
// Función para eliminar el Padding PKCS#7
std::vector<uint8_t> pkcs7_unpadding(std::vector<uint8_t>& input) {
std::vector<uint8_t> output(input);
// Obtiene el número de bytes de relleno
size_t padToRemove = input[input.size() - 1];
// Elimina los bytes de relleno
for (auto i = 0; i < padToRemove; i++) {
output.pop_back();
}
return output;
}
void setup() {
Serial.begin(115200);
delay(2000);
// Datos de ejemplo
std::vector<uint8_t> data;
for (size_t i = 0; i < 14; i++) {
data.push_back(i);
}
Serial.println("Datos originales:");
printBlockAsHex(data);
// Aplicar Padding PKCS#7
auto padded = pkcs7_padding(data);
Serial.println("Datos con Padding PKCS#7:");
printBlockAsHex(padded);
// Eliminar Padding PKCS#7
auto unpadded = pkcs7_unpadding(padded);
Serial.println("Datos sin Padding PKCS#7:");
printBlockAsHex(unpadded);
}
void loop() {
delay(1000);
}
- Creamos un vector de datos con 14 bytes.
- Se aplica el Padding PKCS#7 y se muestra el resultado.
- Se elimina el relleno y se verifica que los datos originales se han recuperado correctamente.