Desarrollo de una funcion para enciptar/desencriptar en AES

Hola a todos, estoy intentando desarrollar una función que sea útil para todos para encriptar y desencriptar en AES.

De momento estaba usando esta librería:

El ejemplo que ponen es algo así pelao y mondao.....:

Serial.begin(57600);
uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
char data[] = "0123456789012345"; //16 chars == 16 bytes
aes128_enc_single(key, data);
Serial.print("encrypted:");
Serial.println(data);
aes128_dec_single(key, data);
Serial.print("decrypted:");
Serial.println(data);

Yo he hecho el siguiente código:

//Cargamos las librerias necesarias para AES
#include <AESLib.h>

void setup()
{
  Serial.begin(9600); //Inicializamos el puerto Serie.
    encriptar("top secret",128);  //Lo pongo aquí para que se ejecute una única vez
  //desencriptar(cifrado,128);
}

void loop()
{

}



String encriptar(String var, int bits) 
{ 
  //Variable que se quiere encriptar y bits para encriptación (128, 256, etc)
  //Función que devolverá encriptada el texto que contenga la variable
  //de entrada como parámetro.


  //El IV es un número normalmente aleatorio que se puede compartir
  //y sirve para que un mismo texto encriptado no aparezca siempre
  //de la misma forma, así es mas complicado desenciptarlo buscando
  //patrones repetitivos.


  uint8_t key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  //char data[] = "0123456789012345"; //16 chars == 16 bytes


  // Largo del array (con un caracter extra para el caracter NULL)
  int var_len = var.length() + 1;

  // Prarara array de carateres (el buffer)
  char char_array[var_len];

  // Convertimos la variable a array y lo volcamos en char_array
  var.toCharArray(char_array, var_len);
  
  switch (bits)
  {
    
    case (128):
      aes128_enc_single(key, char_array);
    break;
    
    
    case (256):
      aes256_enc_single(key, char_array);
    break;
    
    
    default:
    
      Serial.println(F("No se dió un parámtro correcto para bits de encriptación"));
    break;
  }
    
    
  
  Serial.print("Encriptado:");
  Serial.println(char_array);
  return (char_array); //Se devuelve el texto encriptado

}

String desencriptar(String var, int bits) 
{ 
  //Variable que se quiere desencriptar y bits que se usaron para encriptarlo (128, 256, etc)
  //Función que devolverá desencriptada el texto que contenga la variable
  //de entrada como parámetro.


  //El IV es un número normalmente aleatorio que se puede compartir
  //y sirve para que un mismo texto encriptado no aparezca siempre
  //de la misma forma, así es mas complicado desenciptarlo buscando
  //patrones repetitivos.


  uint8_t key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  //char data[] = "0123456789012345"; //16 chars == 16 bytes


  // Largo del array (con un caracter extra para el caracter NULL)
  int var_len = var.length() + 1;

  // Prarara array de carateres (el buffer)
  char char_array[var_len];

  // Convertimos la variable a array y lo volcamos en char_array
  var.toCharArray(char_array, var_len);
  
    switch (bits)
  {
    
    case (128):
      aes128_dec_single(key, char_array);
    break;
    
    
    case (256):
      aes256_dec_single(key, char_array);
    break;
    
    
    default:
    
      Serial.println(F("No se dió un parámtro correcto para bits de desencriptación"));
    break;
  }

  Serial.print("Desencriptado:");
  Serial.println(char_array);

  return (char_array); //Se devuelve el texto desencriptado

}

Aunque no está acabado en principio parece que funciona, pero cuando obtengo los valores y los meto en páginas de decodificar AES no me sale nada en claro.

He probado a pasarlo antes por Base64 y nada....

Estoy usando esta web para AES:
https://cifraronline.com/descifrar-aes

Y esta para probar si es que la librería lo combierte antes o despues en base64:

¿Que opinión tenéis ustedes?

Estas funciones las quiero utilizar para darle mas flexibilidad a la hora de encriptar datos con AES y se podrían usar en muchas aplicaciones.
Creo que todos nos podríamos beneficiar de ello.

Y como estas funciones soportan parámetros pues se les puede decir la frase a encriptar, palabra clave, los bits, etc etc....
Pero yo estoy empezando flojito que me está costando.

Un saludo a todos.

Scorpyo82:
Aunque no está acabado en principio parece que funciona, pero cuando obtengo los valores y los meto en páginas de decodificar AES no me sale nada en claro.

Quizá será porque el array key está compuesto por caracteres no imprimibles.

Así como está no te aparecería nada de nada en el monitor serie.

Empieza con el valor 0, el cual es un terminador de strings; key equivaldría a "" si se tratara de un string.
Si el primer valor lo obviáramos, aún así no se vería nada de nada. Quizá después del valor 10 ocurra un cambio de línea (10 == '\n'); pero como no se ve nada, no importa.

El punto es que un string como tal debería ser la clave (key).

Hola @Lucario448,
Primero de nada gracias por responder.

Pues la verdad es que por el monitor serie si salen cosas, pero parecen las palabrotas de un comic :smiley:

Algo así:

Encriptado:4?��2�Yky�

Está claro creo yo que ahí no se está mostrando lo que verdaderamente está haciendo la librería.....
Si lo saco a una SD mediante código obtengo otra cosa pero tampoco me vale.... no parece ser correcta la codificación.

Así, que por un lado creo que tengo el problema de la codificación, y por otro seguramente el código no esté muy bien planteado.

Lo que realmente pasa es que no entiendo muy bien como funcionan los arrays y como trabajar con ellos....

Un saludo.

Scorpyo82:
Pues la verdad es que por el monitor serie si salen cosas, pero parecen las palabrotas de un comic :smiley:

Algo así:

Encriptado:4?��2�Yky�

No me sorprende en lo absoluto; la encriptación puede cambiar los caracteres de una secuencia (cadena o "string") por cualquiera de las 256 posibilidades.

Scorpyo82:
Está claro creo yo que ahí no se está mostrando lo que verdaderamente está haciendo la librería.....

Qué hace? Sería que te estudies el algoritmo de encriptación AES.

Por qué no parece funcionar? Seguro le estás enviando un array cuya longitud (en bytes) no es múltiplo de 16 (para AES128); o no es múltiplo de 32 (para AES256).

Scorpyo82:
Si lo saco a una SD mediante código obtengo otra cosa pero tampoco me vale.... no parece ser correcta la codificación.

Hablas de desencriptar un archivo? Ahí se te puede poner complicado si no sabes:

  • Si el algoritmo de encriptación usado realmente haya sido AES.
  • Si es por bloques de 16 o 32 bytes.
  • La clave (key).
  • El modo de operación.
  • Dependiendo de esto último, también algo llamado "vector de inicialización" (qué básicamente es como una segunda clave).

Scorpyo82:
Lo que realmente pasa es que no entiendo muy bien como funcionan los arrays y como trabajar con ellos....

En qué exactamente? En el tema de las longitudes, punteros de memoria o posicionamiento?

Hola de nuevo @Lucario448.

Pues veamos...

Por qué no parece funcionar? Seguro le estás enviando un array cuya longitud (en bytes) no es múltiplo de 16 (para AES128); o no es múltiplo de 32 (para AES256).

No sabía lo de que según los bits de encriptación así debía de ser el tamaño del char, aunque he hecho pruebas en 128 y 256bits con el mismo resultado y encriptado, no pasando de 16 caracteres encriptados, el resto me lo muestra en texto plano sin encriptar

Hablas de desencriptar un archivo? Ahí se te puede poner complicado si no sabes:

No, hablo de imprimir el texto resultado a un archivo de texto, pero no me convence el resultado y prefiero arreglar el tema del serial para comprenderlo bien y ya mas adelante lo intento de otra forma.

En qué exactamente? En el tema de las longitudes, punteros de memoria o posicionamiento?

Llevo toda la tarde leyendo sobre el tema de arrays, y creo que mas o menos me he quedado.

Un array puede ser de varias longitudes y de distintos tipos.

Por ejemplo, un array de char, son espacios de 8 en 8 bits (1 byte) de la memoria escritos que representan un caracter.

Por ejemplo, un

char var[2];

equivale a reservar espacio en la memoria para dos bytes, (16Bits) con lo que se puede representar 2 caracteres.

Y lo mismo para el resto de tipos.

y para recorrerlo se puede usar el indice.... algo como..

var2=var[0];

Que mostraría el primer carácter del array de "var"

Mas o menos me estoy empapando pero me está costando el tema de saber como funciona la librería AES.

Lo del Vector de inicialización (IV) ya lo he leido en la wiki, está muy bien explicado, supongo que el enlace que me has puesto será lo mismo pero lo miro igualmente ahora.

Por lo demás sigo liado, pero hoy necesito un respiro que me he tirado todo el día con esto y necesito aclarar la mente.

Muchas gracias de nuevo.

En cuanto haga algún avance lo comento.

Un saludo.

Buenas de nuevo, veamos.....

Me he decidido a usar esta otra librería porque con la otra no me aclaro a la hora de crear claves con CBC:

Y este es el código simplificado que he hecho a partir del ejemplo:

#include <AES.h>
#include <Base64.h>
#include "./printf.h"


AES aes ;

byte *key = (unsigned char*)"0123456789123456";

byte plain[] = "Add NodeAdd NodeAdd NodeAdd NodeAdd Node";

//real iv = iv x2 ex: 01234567 = 0123456701234567
unsigned long long int my_iv = 12345678;

void setup ()
{
  Serial.begin (9600) ;
  printf_begin(); //Al inicializar esta función permite a la librería AES mostrar el array por puerto Serial de forma correcta
  
  encriptar(128) ;

  
}

void loop () 
{
}

void encriptar(int bits)
{
  aes.iv_inc(); //Supongo que será para resetear el vector de inicialización
  byte iv [N_BLOCK] ;
  byte plain_p[48];
  byte cipher [48] ;
  byte check [48] ;

  aes.set_IV(my_iv);
  aes.get_IV(iv);
  aes.do_aes_encrypt(plain,41,cipher,key,bits,iv);

  Serial.println(F("Texto plano: "));
  aes.printArray(plain,(bool)true);
  Serial.println(F("Texto cifrado: "));
  
  int cipherLen = sizeof(cipher); //Tamaño del texto ya cifrado
  
  int encodedLen = base64_enc_len(cipherLen); //Tamaño que ocupará una vez pasado a base64
  char encoded[encodedLen]; //Se crea una variable local del tamaño adecuado
  
  // Pasamos a la variable encoded el valor base64 de la variable cipher
  // para poder mostrarlo por Serial.
  base64_encode(encoded, cipher, cipherLen); 
  
  Serial.println(encoded);
  
}

Ahora ya estoy teniendo algún resultado positivo.

Esto me arroja por Serial lo siguiente:

Texto plano: 
Add NodeAdd NodeAdd NodeAdd NodeAdd Node
Texto cifrado: 
El texto cifrado es = gyFxZytVRfDDroYvxjk4/SiRxpGzvR+EkwPeT9VPekdoeEJKsn97ce7MfdmqSSiK

Ahora ya se muestra algo mejor porque lo estoy representando en Base64.

Si vamos a la página siguiente:
https://cifraronline.com/descifrar-aes

Le damos a avanzadas y configuramos así:
Algoritmo: AES
Modo: CBC
Vector de inicialización: 12345678
Hash: ninguno

Le dais a "guardar y volver"

Ponéis el texto que da como resultado en el serial en la ventana de traducción y con la clave siguiente:

0123456789123456

Obtenermos algo como esto:

�w&sP�����V\�Add Node

Ya parece que se muestra algo.....

Pero no se en que más me estaré equivocando.

¿Alguna idea?

Un saludo a todos y buen finde

Bueno, hola de nuevo.

Eh mirado en la página que os comento para descifrar online.

Si dejamos el IV en modo Automático se descifra bien.

Lo que no sé es porqué si meto el IV de forma manual no funciona.

Por lo menos ya estoy muy cerca de solucionarlo.

Este es el núevo código que he añadido, solo he cambiado algunas variables como la KEY y el IV para ir descartando cosas.

Ah! y he añadido una última línea que muestra el IV por Serial pero lo hace creo ¿en base16? no se exactamente, estoy mirando
la documentación de spaniakos pero me cuesta.

http://spaniakos.github.io/AES/classAES.html

#include <AES.h>
#include <Base64.h>
#include "./printf.h"


AES aes ;

byte *key = (unsigned char*)"0123456789123456"; //Puntero de la Key que se usará

byte plain[] = "Add NodeAdd NodeAdd NodeAdd NodeAdd Node";

//real iv = iv x2 ex: 01234567 = 0123456701234567
unsigned long long int my_iv = 87654321;

void setup ()
{
  Serial.begin (9600) ;
  printf_begin(); //Al inicializar esta función permite a la librería AES mostrar el array por puerto Serial de forma correcta
  
  encriptar(128) ;

  
}

void loop () 
{
}

void encriptar(int bits)
{
  
  aes.iv_inc(); //Supongo que será para resetear el vector de inicialización
  byte iv [N_BLOCK] ;
  byte plain_p[48];
  byte cipher [48] ;
  byte check [48] ;
  int plain_len = sizeof(plain) + 1;

  aes.set_IV(my_iv);
  aes.get_IV(iv);
  aes.do_aes_encrypt(plain,plain_len,cipher,key,bits,iv);

  Serial.println(F("Texto plano: "));
  aes.printArray(plain,(bool)true);
  Serial.println(F("Texto cifrado: "));
  
  int cipherLen = sizeof(cipher); //Tamaño del texto ya cifrado
  
  int encodedLen = base64_enc_len(cipherLen); //Tamaño que ocupará una vez pasado a base64
  char encoded[encodedLen]; //Se crea una variable local del tamaño adecuado
  
  // Pasamos a la variable encoded el valor base64 de la variable cipher
  // para poder mostrarlo por Serial.
  base64_encode(encoded, cipher, cipherLen); 
  
  Serial.println(encoded);
  Serial.println("IV:");
  aes.printArray(iv,16);
  
}

Un saludo.

Buen dia, una pregunta, lograste solucionar los errores de la encriptacion y desencriptacion?

Moderador:
No revivas hilos con mas de 120 días. Este supera con creces ese tiempo.
Crea un nuevo tema y explica que deseas hacer con detalle.
Lee las normas del foro por favor.