Mini algoritmo de cifrado para Arduino

Todo cuanto tiene que ver con la obtención, almacenamiento y proceso de la información digital, sus aplicaciones y el software y hardware utilizado.
Responder
Mensaje
Autor
Avatar de Usuario
heli
Mensajes: 1952
Registrado: Mié Sep 06, 2006 7:28 am
País: España
Ciudad: Alcalá de Henares
Ubicación: Alcala de Henares (Madrid, España)
Contactar:

Mini algoritmo de cifrado para Arduino

#1 Mensaje por heli »

Estoy metido en tres fregados simultáneos de IOT (ahora se llama así, antes solo eran redes de sensores distribuidos) y estaba buscando un algoritmo de encriptación aceptable para dispositivos embebidos (yo no pierdo de vista la seguridad de la IOT, que ya son muchos años programando..)
De momento estoy usando Arduino Uno (Atmega328) y había reciclado un DES https://es.wikipedia.org/wiki/Data_Encryption_Standard que usé en otro proyecto (librería de arduino http://spaniakos.github.io/ArduinoDES) pero como voy justo de memoria y tiempo de ciclo pensé en mejorarlo.

Valoré un AES https://es.wikipedia.org/wiki/Advanced_ ... n_Standard del que también tengo librería para arduino https://github.com/DavyLandman/AESLib pero ocupaba demasiado espacio en flash.

Entonces me encuentro la sorpresa, viendo avr-crypto-lib un listado de algoritmos para micros AVR de atmel, veo que existe uno llamado XTEA y su mejora XXTEA https://en.wikipedia.org/wiki/XXTEA muy sencillos de implementar y pensados para dispositivos embebidos!!

Después de un cortapega de la wikipedia y de machacar el teclado he dejado el algorítmo bastante óptimo para Arduino (he visto un par de librerías ya hechas pero son un calco de la publicación original y no aportan mejoras).

Un arduino Uno a 16Mhz tarda en cifrar y descifra un bloque de 64 bytes:
Con DES en modo CBC tarda 284568us y ocupa 2572 bytes de flash
Con XTEA en modo CBC tarda 11008us y ocupa 916 bytes de flash
Con XXTEA tarda 4168us y ocupa 1086 bytes de flash
O sea que es rapidísimo y pequeñito...

La KEY es de 128 bits (mejor que el DES que solo es de 56) aceptable para mi aplicación. Se conocen ataques pero se basan en usar mas de 2^59 "textos planos escogidos", también aceptable!!

El código es extremadamente sencillo, la única desventaja es que sobreescribe los datos planos con los datos encriptados:

Código: Seleccionar todo

#define DELTA 0x9E3779B9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((Sum^y) + (Key[(WordCount&3)^KeyIdx] ^ z)))
// =================================================================================
// Cifrador  XXTEA (Tiny Encryption Algorithm) Key = 128 bits, 16 bytes
// Blocks = bloques de 32bit, 64 bits min (Blocks = 2)
// https://en.wikipedia.org/wiki/XXTEA
// (c) Heli Tejedor, helitp@gmail.com, Junio 2017
// Licencia Creative Commons 3.0 Reconocimiento, No Comercial, Compartir Igual (CC BY-NC-SA 3.0)
// =================================================================================
void XxteaEncrypt (uint32_t *Data, uint8_t Blocks, uint32_t const Key[4]) 
{
  uint32_t y, z, Sum;
  uint8_t WordCount, Rounds, KeyIdx;       
  Rounds = 6 + 52/Blocks;
  Sum = 0;
  z = Data[Blocks-1];
  do 
  {
    Sum += DELTA;
    KeyIdx = ((uint8_t)Sum >> 2) & 3;
    for (WordCount = 0; WordCount < Blocks-1; WordCount++) 
    {
      y = Data[WordCount+1]; 
      z = Data[WordCount] += MX;
    }
    y = Data[0];
    z = Data[Blocks-1] += MX;
  } while (--Rounds);   
}
  
// =================================================================================
// Descrifrador  XXTEA (Tiny Encryption Algorithm) Key = 128 bits, 16 bytes
// =================================================================================
void XxteaDecrypt (uint32_t *Data, uint8_t Blocks, uint32_t const Key[4]) 
{       
  uint32_t y, z, Sum;       
  uint8_t WordCount, Rounds, KeyIdx;
  Rounds = 6 + 52/Blocks;
  Sum = Rounds*DELTA;
  y = Data[0];
  do 
  {
    KeyIdx = (Sum >> 2) & 3;
    for (WordCount = Blocks-1; WordCount > 0; WordCount--) 
    {
      z = Data[WordCount-1];
      y = Data[WordCount] -= MX;   
    }
    z = Data[Blocks-1];
    y = Data[0] -= MX;
    Sum -= DELTA;
  } while (--Rounds);
}
Para usarlo:

Código: Seleccionar todo

  
#define MYDATA 64
uint8_t Plain[MYDATA] = {"0123456789012345abcdefghijklmnopABCDEFGHIJKLMNOP-.,_:;?=)(/&%$!"};
uint8_t XteaKey[16] = {0xF3, 0xD5, 0x36, 0x32, 0x13, 0x12, 0x34, 0x56, 0xF4, 0xD5, 0xB6, 0x3F, 0x53, 0x15, 0x64, 0x56 };

XxteaEncrypt ((uint32_t*)Plain, MYDATA/4, (uint32_t*)XteaKey);
XxteaDecrypt ((uint32_t*)Plain,  MYDATA/4, (uint32_t*)XteaKey);
¡No es imposible, lo que pasa es que no sabes como hacerlo!
Aka: no es difícil si sabes como.
http://heli.xbot.es

Avatar de Usuario
heli
Mensajes: 1952
Registrado: Mié Sep 06, 2006 7:28 am
País: España
Ciudad: Alcalá de Henares
Ubicación: Alcala de Henares (Madrid, España)
Contactar:

Re: Mini algoritmo de cifrado para Arduino

#2 Mensaje por heli »

Pues ya lo tengo corriendo en todos los nodos de prueba y es una maravilla!
Lo he portado a Teensy 3.2 (compatible con arduino) https://www.pjrc.com/teensy/teensy31.html pero con un micro Freescale MK20DX256VLH7 ARM Cortex-M4 hasta 96Mhz y también funciona perectamente.
Debido a que es un micro de 32 bits he cambiado algunas definiciones de datos para optimizar y he conseguido que, ocupando 448 bytes de programa, encripte y desencripte bloques de 64 bytes en solo 296 microsegundos a 24Mhz

Cambiando también algunas definiciones de datos en Arduino el programa ocupa 10 bytes mas (1096) pero encripta y desencripta los mismos bloques de 64 bytes 128 microsegundos mas rápido (en 4040us).

Es curioso ver como el ARM Cortex M4 ejecuta el programa 13 veces mas rápido que el AVR con solo un 50% mas de velocidad de reloj.

El código para arduino queda así:

Código: Seleccionar todo

#define DELTA 0x9E3779B9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((Sum^y) + (Key[(WordCount&3)^KeyIdx] ^ z)))
// =================================================================================
// Cifrador  XXTEA (Tiny Encryption Algorithm) Key = 128 bits, 16 bytes
// Blocks = bloques de 32bit, 64 bits min (Blocks = 2)
// https://en.wikipedia.org/wiki/XXTEA
// (c) Heli Tejedor, helitp@gmail.com, Junio 2017 V0.2
// Licencia Creative Commons 3.0 Reconocimiento, No Comercial, Compartir Igual (CC BY-NC-SA 3.0)
// =================================================================================
void XxteaEncrypt (uint32_t *Data, int Blocks, uint32_t const Key[4]) 
{
  uint32_t y, z, Sum;
  int WordCount, Rounds, KeyIdx;       
  Rounds = 6 + 52/Blocks;
  Sum = 0;
  z = Data[Blocks-1];
  do 
  {
    Sum += DELTA;
    KeyIdx = ((uint8_t)Sum >> 2) & 3; // Optimizacion para ATMEGA328
    for (WordCount = 0; WordCount < Blocks-1; WordCount++) 
    {
      y = Data[WordCount+1]; 
      z = Data[WordCount] += MX;
    }
    y = Data[0];
    z = Data[Blocks-1] += MX;
  } while (--Rounds);    
}
  
/ =================================================================================
// Descrifrador  XXTEA (Tiny Encryption Algorithm) Key = 128 bits, 16 bytes
// =================================================================================
void XxteaDecrypt (uint32_t *Data, int Blocks, uint32_t const Key[4]) 
{       
  uint32_t y, z, Sum;       
  uint8_t WordCount, Rounds, KeyIdx;  // Optimizaciones para ATMEGA328
  Rounds = 6 + 52/Blocks;
  Sum = Rounds*DELTA;
  y = Data[0];
  do 
  {
    KeyIdx = (Sum >> 2) & 3;
    for (WordCount = Blocks-1; WordCount > 0; WordCount--) 
    {
      z = Data[WordCount-1];
      y = Data[WordCount] -= MX;   
    }
    z = Data[Blocks-1];
    y = Data[0] -= MX;
    Sum -= DELTA;
  } while (--Rounds);
}
¡No es imposible, lo que pasa es que no sabes como hacerlo!
Aka: no es difícil si sabes como.
http://heli.xbot.es

alberttoy
Mensajes: 1090
Registrado: Mar Sep 16, 2014 12:55 am
País: españa
Ciudad: barcelona

Re: Mini algoritmo de cifrado para Arduino

#3 Mensaje por alberttoy »

Muy interesante.
He empezado a seguirlo pero no es nada evidente. :D

Avatar de Usuario
heli
Mensajes: 1952
Registrado: Mié Sep 06, 2006 7:28 am
País: España
Ciudad: Alcalá de Henares
Ubicación: Alcala de Henares (Madrid, España)
Contactar:

Re: Mini algoritmo de cifrado para Arduino

#4 Mensaje por heli »

Pero si es muy facil!
Imagen

Cuando vi el flujograma pensé que no podría implementarlo, pero el ejemplo de la wikipedia es suficiente para hacerlo funcionar en un compilador moderno.
Casi todo el truco esta en el macro:

Código: Seleccionar todo

#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((Sum^y) + (Key[(WordCount&3)^KeyIdx] ^ z)))
¡No es imposible, lo que pasa es que no sabes como hacerlo!
Aka: no es difícil si sabes como.
http://heli.xbot.es

Avatar de Usuario
heli
Mensajes: 1952
Registrado: Mié Sep 06, 2006 7:28 am
País: España
Ciudad: Alcalá de Henares
Ubicación: Alcala de Henares (Madrid, España)
Contactar:

Re: Mini algoritmo de cifrado para Arduino

#5 Mensaje por heli »

Por si alguien necesita el sketch puede descargarlo aqui, junto con algunas pruebas: http://heli.xbot.es/?p=427
¡No es imposible, lo que pasa es que no sabes como hacerlo!
Aka: no es difícil si sabes como.
http://heli.xbot.es

Avatar de Usuario
Anilandro
Mensajes: 4905
Registrado: Dom Feb 11, 2007 10:16 pm
Ubicación: Islas Baleares, España
Contactar:

Re: Mini algoritmo de cifrado para Arduino

#6 Mensaje por Anilandro »

Interesante tema Heli, me bajaré el código, aunque mi conocimiento de los sistemas de encriptación se reduce a los llamados métodos "clásicos", de los cuales he implementado unos cuantos en Visual Basic y uno en Arduino. No obstante, todos ellos están enfocados únicamente al cifrado de textos, y no de datos a nivel general. Respecto a eso, tengo uno de estos programas instalado en un Arduino Leonardo "beetle" (el que parece un pequeño pendrive) y va de maravilla, permite claves de 64 dígitos alfanuméricos y realiza hasta 16 multicifrados sucesivos utilizando subclaves distintas, con lo cual pienso que puede ser un sistema difícil de romper (aunque nunca se sabe...).

Saludos
La VIDA sólo es energía que ha aprendido a defenderse... (Anilandro)

*** La Web de Anilandro *** http://sites.google.com/site/anilandro

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados