Ocultar comunicaciones de miradas indiscretas

Ocultar las comunicaciones con codificación en Base64
Ocultar las comunicaciones con codificación en Base64

Para ocultar nuestras comunicaciones de nuestros dispositivos IOT, no es necesario utilizar complejos métodos de encriptación. En la actualidad se dispone de diversos métodos de codificación para que las comunicaciones entre nuestros dispositivos IOT, ya sean creados con arduino o con el ESP32, y los sistemas centrales, no tengan que hacerse en texto plano.

Una de las premisas que suelen usar los ciberdelincuentes es la de, esfuerzo/recompensa.

Si están intentando vulnerar un sistema bancario, el esfuerzo que les puede llevar sera muy grande, pero la recompensa también lo es.

Pero si lo que están vulnerando es el sistema de riego de mi jardín, la recompensa es muy baja. Con lo que aumentando el grado de esfuerzo necesario para la vulneración, podemos eliminar una gran mayoría de amenazas.

Recordatorio: Esto no es un sistema para asegurar las comunicaciones de la Nasa o del FBI. Solo es un sistema para darle una capa más de seguridad a nuestros pequeños proyectos.

Teniendo en cuenta esta premisa, para ocultar nuestras comunicaciones no hace falta desplegar un gran sistema criptográfico para hacer que los crackers desistan con el ataque a nuestro sistema.

Para ello solo tenemos que utilizar los métodos de codificación que tenemos a nuestro alcance, como puede ser la codificación en Base64.

Un poco de teoría

La codificación base64 se define como:

Base64 es un grupo de esquemas de codificación de binario a texto que representa los datos binarios mediante una cadena ASCII, traduciéndolos en una representación radix-64. El término Base64 se origina de un sistema de codificación de transmisión de contenido MIME específico.

https://developer.mozilla.org/es/docs/Web/API/WindowBase64/Base64_codificando_y_decodificando

Este tipo de codificación la tenemos disponible en cualquier lenguaje de programación. Lo que la hace muy fácil de usar.

Una de las formas más fáciles de identificar que una cadena esta codificada en base64, es, si la cadena termina en uno o dos símbolos de igual. Esto se debe a que base64 usa 6 bits de los 8 de los normales. Para cubrir ese hueco el algoritmo de base64 lo rellena con 1 o con dos símbolos de igual.

Otra forma que se puede usar para identificar la codificación, es que la cadena solo está compuesta por letras de la «a» a la «z», tanto en mayúsculas, como en minúsculas, números del 0 al 9 y los símbolos, normalmente, «+» y «/». Ya que la suma de letras y número es 62, y se usan eso dos símbolos para completar los 64.

¿Pero solo con eso puedo ocultar mis comunicaciones?

Pero, ¿si base64, está implementado en todos los lenguajes?, ¿es fácil de identificar?, el esfuerzo de un malo, más bien es poco ¿no?. Pues si, pero ya tenemos la base de nuestro sistema.

Si ya sabemos los puntos débiles del sistema, podemos detectarlos y reforzarlos.

Por ejemplo, sabemos que base64, nos pone en ocasiones, símbolos de igual si la cadena no tiene la longitud deseada. Pues vamos a controlar que la cadena tenga la longitud necesaria para que no incluya los símbolos de igual.

Esto es fácil, solo tenemos que controlar que el tamaño sea múltiplo de 3. Si no es múltiplo añadiremos tantos caracteres como sean necesarios.

Para el tema de los caracteres usados, es más compleja su solución. Pero podemos aplicar un método fácil para dificultar la codificación. Para ello solo tenemos que invertir la cadena en base64, por ejemplo, antes de su envió. Podría ser una forma de ofuscar. Se podrían aplicar otras.

Código, que es lo que mola

Un código de ejemplo que nos permite ocultar nuestras comunicaciones de lo explicado anteriormente en python sería el siguiente.

#!/usr/bin/env python

"""
    Encode base64
"""
import base64

def encode(encode):
    # Calculamos si la cadena es múmtiplo de 3
    rest_message = len(encode.encode('utf-8')) % 3
    if rest_message == 0:
        temp_message = encode
    else:
        # Si no es múltiplo de 3, le añadimos tantos caracteres
        # como necesitemos    
        temp_message = encode + (" " * (3 - rest_message))
    # Lo codificamos en utf-8
    message_byte = temp_message.encode('utf-8')
    # Lo codificamos en base64
    codec_base64 = base64.b64encode(message_byte)
    # Decodificamos el utf-8e invertimos la cadena
    string_codec_base64 = codec_base64.decode('utf-8')[::-1]

    print(f'encode: {string_codec_base64}')

if __name__ == "__main__":
    string_encode = "Esto es una prueba más"
    encode(encode=string_encode)

Para calcular si la cadena es múltiplo de 3 usamos la siguiente linea

rest_message = len(encode.encode('utf-8')) % 3

Si el resto es cero, la longitud de la cadena es múltiplo de 3, por lo que no tenemos que añadir nada. Si fuera distinto de 0, es decir 1 o 2. El valor nos valdría para calcular cuantos caracteres nos hacen faltan.

if rest_message == 0:
    temp_message = encode
else:
    # Si no es múltiplo de 3, le añadimos tantos caracteres
    # como necesitemos    
    temp_message = encode + (" " * (3 - rest_message))

Una vez que ya tenemos ajustado el tamaño solo nos queda codificarla en base64

# Lo codificamos en utf-8
message_byte = temp_message.encode('utf-8')
# Lo codificamos en base64
codec_base64 = base64.b64encode(message_byte)

Para darle la vuelta solo tenemos que añadir [::-1] a la cadena con la codificación en base64

string_codec_base64 = codec_base64.decode('utf-8')[::-1]

Y con esto ya tenemos un sistema fácil de implementar, todos los lenguajes tiene librerías para trabajar con ello. Y que a los malos no le resulte tan fácil.

Vuelta el recordatorio: Esto no es un sistema para proteger información delicada, si no, un método para darle una capa mayor de seguridad a nuestros pequemos proyectos.

Como dormir el ESP32 (deep-sleep)

Dormir nuestro controlador esp32 es la forma más fácil de ahorro de energía que podemos implementar en nuestros sensores de IOT.

En mucho desarrollos con arduino o con similares, como el esp32, por ejemplo. La mayoría de las veces no hace falta que esté constantemente enviando datos o procesándolos. Y si además nuestro dispositivo es autónomo la variable de ahorro de energía cobra mayor importancia.

En los sistemas basados en ESP32 tenemos una forma fácil y sencilla de que nuestro dispositivo IOT pueda ahorrar energía. Para ello solo tenemos que añadir el código para indicarle que pase a modo «durmiente» y conectar la salida D0 al pin de reset. 

El comando que necesitamos para dormir el ESP32 es el siguiente.

ESP.deepSleep(tiempo_milisegundos, modo reinicio)

Modos de uso para dormir el ESP32

Los modos que podemos usar son:

  • modem-sleep: este modo de ahorro permite desactivar la conexión WiFi de tipo Station , establecida con un punto de acceso (router), cuando no sea necesario su uso y volver a activarla cuando se necesite.. El consumo típico en este modo es de 15mA.
  • light-sleep: este modo de ahorro permite mantener la conexión WiFi de tipo Station, pero reduce el consumo de energía en los momentos en los que no hay envío de información.. El consumo típico pasa a ser de unos 0,5 mA.
  • deep-sleep: es el modo que genera mayor ahorro, pero a costa de dejar la placa en suspenso. La única parte de la placa que funciona durante este modo es reloj en tiempo real (Real Time Clock o RTC) para poder reiniciarla cuando haya finalizado el tiempo de reposo. El consumo típico pasa a ser de unos 10 uA.

Además de dispones de los siguientes modos de reinicio.

  • WAKE_RF_DEFAULT: Calibración de señal de radio si es necesario
  • WAKE_RFCAL: Calibración de señal de radio siempre
  • WAKE_NO_RFCAL: Sin calibración de la señal de radio
  • WAKE_RF_DISABLED: Deshabilita la señal de radio después del reencendido

El modo en el que más ahorro de energía conseguiremos es en el modo WAKE_RF_DEFAULT, ya que este modo es el que desactiva todos los sistemas no esenciales del ESP32.

En el siguiente enlace, podemos obtener más información de estos modos de uso y reinicio:

http://arduinoamuete.blogspot.com/2017/01/modo-deep-sleep-en-esp8266.html

La otra condición que tenemos que establecer, es el de conectar el pin D0 con el pin de reset. Ya que una vez que transcurra el tiempo que hemos indicado, este enviara una señal por el pin D0 para activar el reinicio del dispositivo.

ESP32 Deep Sleep
Puente entre D0 y reset para el reinicio

Código de ejemplo

Para la gestión podemos usar el siguiente ejemplo:

// Deep sleep mode

if (millis() >= (time_sleep + start_time)) {

    // Deep sleep mode, the ESP8266 wakes up by itself when GPIO 16 (D0 in NodeMCU board) is connected to the RESET pin

    Serial.print("I'm awake, but I'm going into deep sleep mode for ");

    Serial.print(SLEEP_TIME);

    Serial.println(" seconds");

    ESP.deepSleep(SLEEP_TIME * SECONDS, WAKE_RF_DEFAULT);

}

else

{

    Serial.println("I'm alive");

    delay(500);

}

 

Con esto conseguiremos que nuestro sensores autónomos tenga una mayor autonomía.