Criptografía práctica de IoT en el Express ESP8266
El chip Espressif ESP8266 hace que las placas de desarrollo de tres dólares del “Internet de las cosas” sean una realidad económica. Según el popular sitio de creación de empresas automatizado nodeMCU-builds, en los últimos 60 días ha habido 13,341 versiones de firmware personalizadas para esa plataforma. De ellos, solo el 19% tiene soporte SSL y el 10% incluye el módulo criptográfico.
A menudo criticamos la falta de seguridad en el sector de IoT y, a menudo, cubrimos botnets y otros ataques, pero ¿mantendremos nuestros proyectos con los mismos estándares que requerimos? ¿Dejaremos de identificar el problema o podemos ser parte de la solución?
Este artículo se centrará en la aplicación de funciones de autorización de hash y cifrado AES al protocolo MQTT utilizando el popular chip ESP8266 con firmware NodeMCU. Nuestro objetivo no es proporcionar una panacea de copiar y pegar, sino pasar por el proceso paso a paso, identificando desafíos y soluciones a lo largo del camino. El resultado es un sistema completamente encriptado y autenticado, que evita las escuchas en el camino y la falsificación de datos válidos, sin depender de SSL.
Somos conscientes de que también hay plataformas más potentes que admiten SSL fácilmente (por ejemplo, Raspberry Pi, Orange Pi, FriendlyARM), pero comencemos con el hardware más barato que tenemos la mayoría de nosotros y un protocolo adecuado para muchos de nuestros proyectos. . AES es algo que podría implementar en AVR si fuera necesario.
Teoría
MQTT es un protocolo de mensajería liviano que funciona además de TCP / IP y se usa comúnmente para proyectos de IoT. Los dispositivos de los clientes se suscriben o publican temas (por ejemplo, sensores / temperatura / cocina), y estos mensajes los emite un agente de MQTT. Más información sobre MQTT está disponible en su sitio web o en nuestra propia serie introductoria.
El protocolo MQTT no tiene funciones de seguridad integradas más allá de la verificación de nombre de usuario / contraseña, por lo que es común encriptar y autenticar a través de una red a través de SSL. Sin embargo, SSL puede ser bastante exigente para el ESP8266 y cuando está habilitado, le queda mucha menos memoria para su aplicación. Como alternativa ligera, puede cifrar solo la carga útil de datos enviada y utilizar un ID de sesión y una función hash para la autenticación.
Una forma directa de hacer esto es usar Lua y el módulo Crypto NodeMCU, que incluye soporte para el algoritmo AES en modo CBC, así como la función de eje HMAC. El uso correcto del cifrado AES requiere tres cosas para producir texto cifrado: mensaje, clave y vector de inicialización (IV). Los mensajes y las claves son conceptos simples, pero vale la pena discutir el vector inicial.
Cuando codifica un mensaje en AES con una clave estática, siempre producirá la misma salida. Por ejemplo, el mensaje "usernamepassword" cifrado con la clave "1234567890ABCDEF" podría producir un resultado como "E40D86C04D723AFF". Si vuelve a iniciar el cifrado con la misma clave y mensaje, obtendrá el mismo resultado. Esto lo abre a varios tipos comunes de ataques, especialmente análisis de patrones y ataques iterativos.
En un ataque al análisis de plantillas, utiliza el conocimiento de que los datos dados siempre producirán el mismo texto cifrado para adivinar cuál es el propósito o el contenido de diferentes mensajes, sin conocer realmente la clave secreta. Por ejemplo, si el mensaje "E40D86C04D723AFF" se envía antes que todas las demás comunicaciones, uno podría adivinar rápidamente que se trata de un inicio de sesión. Básicamente, si el sistema de inicio de sesión es simple, enviar ese paquete (ataque iterativo) podría ser suficiente para identificarlo como un usuario autorizado, y sobreviene el caos.
Los IV dificultan el análisis de patrones. IV son los datos enviados junto con la clave que modifica el resultado final cifrado. Como sugiere el nombre, inicializa el estado del algoritmo de cifrado antes de que ingresen los datos. El IV debe ser diferente para cada mensaje enviado para que los datos repetidos se cifren en un texto cifrado diferente, y algunos cifrados (como AES-CBC) requieren que sea impredecible; una forma práctica de lograr esto es simplemente aleatorizarlo cada vez. Los IV no tienen que ser secretos, pero es común ocultarlos de alguna manera.
Si bien esto protege contra el análisis de patrones, no ayuda con los ataques repetidos. Por ejemplo, retransmitir un conjunto determinado de datos cifrados seguirá copiando el resultado. Para evitar esto, necesitamos autenticar al remitente. Usaremos un ID de sesión pseudogenerado público para cada mensaje. Este ID de sesión se puede generar desde el dispositivo receptor mediante la publicación en un tema MQTT.
La prevención de estos ataques es importante en varios casos de uso habituales. Existen hornos de Internet, y la utilidad dudosa en particular, estaría bien si no usaran comandos inseguros. En segundo lugar, si registro datos de cien sensores, no quiero que nadie llene mi base de datos con basura.
Cifrado práctico
Implementar lo anterior en NodeMCU requiere algo de esfuerzo. Necesitará un firmware compilado para incluir el módulo "cripto" además de cualquier otro que necesite para su aplicación. No se requiere soporte SSL.
Primero, supongamos que está vinculado a un corredor de MQTT con algo como lo siguiente. Puede implementar esto como una función separada de la criptografía para limpiar las cosas. El cliente se suscribe a sessionID
un canal que publica identificadores de sesión pseudoaleatorios apropiadamente largos. Puede cifrarlos, pero no es necesario.
m = mqtt.Client("clientid", 120) m:connect("myserver.com", 1883, 0, function(client) print("connected") client:subscribe("mytopic/sessionID", 0, function(client) print("subscribe success") end ) end, function(client, reason) print("failed reason: " .. reason) end ) m:on("message", function(client, topic, sessionID) end)
Continuando, la ID de nodo es una forma conveniente de ayudar a identificar las fuentes de datos. Sin embargo, puede usar cualquier cadena: nodeid = node.chipid()
.
A continuación, configuramos un vector de inicio estático y una clave. Esto solo se usa para difuminar el vector inicial aleatorio enviado con cada mensaje, NO se usa para ningún dato. También elegimos una clave particular para los datos. Estas claves son hexadecimales de 16 bits, simplemente reemplácelas con las suyas.
Finalmente, necesitaremos una frase de contraseña para una función de pirateo que usaremos más adelante. Una cuerda de longitud razonable es buena.
staticiv = "abcdef2345678901" ivkey = "2345678901abcdef" datakey = "0123456789abcdef" passphrase = "mypassphrase"
También asumiremos que tiene alguna fuente de datos. Para este ejemplo, será un valor leído por el ADC. data = adc.read(0)
Ahora generamos un vector de inicialización pseudoaleatorio. Un número hexadecimal de 16 dígitos es demasiado grande para la función de número pseudoaleatorio, por lo que lo generamos en dos mitades (16 ^ 8 menos 1) y las unimos.
half1 = node.random(4294967295) half2 = node.random(4294967295) I = string.format("%8x", half1) V = string.format("%8x", half2) iv = I .. V
Ahora podemos lanzar el cifrado real. Aquí encriptamos el vector inicial actual, el identificador de nodo y una pieza de datos del sensor.
encrypted_iv = crypto.encrypt("AES-CBC", ivkey, iv, staticiv) encrypted_nodeid = crypto.encrypt("AES-CBC", datakey, nodeid,iv) encrypted_data = crypto.encrypt("AES-CBC", datakey, data,iv)
Ahora aplicamos la función hash para la autenticación. Primero combinamos el nodeid
, iv
, data
y el ID de sesión en un solo mensaje, luego calcule el hash HMAC SHA1 usando la frase de contraseña que definimos anteriormente. Lo convertimos a hexadecimal para hacerlo un poco más legible para cualquier depuración.
fullmessage = nodeid .. iv .. data .. sessionID hmac = crypto.toHex(crypto.hmac("sha1", fullmessage, passphrase))
Ahora que se han realizado las comprobaciones de cifrado y autenticación, podemos poner toda esta información en alguna estructura y enviarla. Aquí usaremos valores separados por comas según corresponda:
payload = table.concat({encrypted_iv, eid, data1, hmac}, ",") m:publish("yourMQTTtopic", payload, 2, 1, function(client) p = "Sent" print(p) end)
Cuando lanzamos el código anterior en NodeMCU real, obtendríamos un resultado como este:
1d54dd1af0f75a91a00d4dcd8f4ad28d, d1a0b14d187c5adfc948dfd77c2b2ee5, 564633a4a053153bcbd6ed25370346d5, c66697df7e7d467112757c841bfb6bce051d6289
En conjunto, el programa de cifrado es el siguiente (se excluyen las secciones MQTT para mayor claridad):
nodeid = node.chipid() staticiv = "abcdef2345678901" ivkey = "2345678901abcdef" datakey = "0123456789abcdef" passphrase = "mypassphrase" data = adc.read(0) half1 = node.random(4294967295) half2 = node.random(4294967295) I = string.format("%8x", half1) V = string.format("%8x", half2) iv = I .. V encrypted_iv = crypto.encrypt("AES-CBC", ivkey, iv, staticiv) encrypted_nodeid = crypto.encrypt("AES-CBC", datakey, nodeid,iv) encrypted_data = crypto.encrypt("AES-CBC", datakey, data,iv) fullmessage = nodeid .. iv .. data .. sessionID hmac = crypto.toHex(crypto.hmac("sha1",fullmessage,passphrase)) payload = table.concat({encrypted_iv, encrypted_nodeid, encrypted_data, hmac}, ",")
Descifrado
Ahora su agente de MQTT no sabe ni le importa que los datos estén encriptados, simplemente los transmite. Por lo tanto, sus otros clientes de MQTT suscritos al tema necesitarán saber cómo descifrar los datos. En NodeMCU esto es bastante fácil. Simplemente divida los datos recibidos en cadenas con comas y haga algo como lo que se muestra a continuación. Tenga en cuenta que este extremo habrá generado el ID de sesión, por lo que ya lo sabe.
staticiv = "abcdef2345678901" ivkey = "2345678901abcdef" datakey = "0123456789abcdef" passphrase = "mypassphrase" iv = crypto.decrypt("AES-CBC", ivkey, encrypted_iv, staticiv) nodeid = crypto.decrypt("AES-CBC", datakey, encrypted_nodeid,iv) data = crypto.decrypt("AES-CBC",datakey, encrypted_data,iv) fullmessage = nodeid .. iv .. data .. sessionID hmac = crypto.toHex(crypto.hmac("sha1",fullmessage,passphrase))
Luego compare el HMAC recibido y calculado, e independientemente del resultado, cancele ese ID de sesión generando uno nuevo.
De nuevo, en Python
Para variar un poco, considere cómo manejaríamos el descifrado en Python si tuviéramos un cliente MQTT en la misma máquina virtual que el corredor que analizó los datos o los almacenó en una base de datos. Suponga que recibió los datos como una "carga útil" de cadena, de algo como el excelente Cliente Paho MQTT para Python.
En este caso, es conveniente cifrar los datos cifrados en el NodeMCU antes de transmitir. Entonces en NodeMCU convertimos todos los datos encriptados a hexadecimales, por ejemplo: encrypted_iv = crypto.toHex(crypto.encrypt("AES-CBC", ivkey, iv, staticiv))
La publicación de una ID de sesión aleatoria no se analiza a continuación, pero es bastante fácil con os.urandom () y Paho MQTT Client. El descifrado se trata de la siguiente manera:
from Crypto.Cipher import AES import binascii from Crypto.Hash import SHA, HMAC # define all keys ivkey = '2345678901abcdef' datakey = '0123456789abcdef' staticiv = 'abcdef2345678901' passphrase="mypassphrase" # Convert the received string to a list data = payload.split(",") # extract list items encrypted_iv = binascii.unhexlify(data[0]) encrypted_nodeid = binascii.unhexlify(data[1]) encrypted_data = binascii.unhexlify(data[2]) received_hash = binascii.unhexlify(data[3]) # decrypt the initialization vector iv_decryption_suite = AES.new(ivkey,AES.MODE_CBC, staticiv) iv = iv_decryption_suite.decrypt(encrypted_iv) # decrypt the data using the initialization vector id_decryption_suite = AES.new(datakey,AES.MODE_CBC, iv) nodeid = id_decryption_suite.decrypt(encrypted_nodeid) data_decryption_suite = AES.new(datakey,AES.MODE_CBC, iv) sensordata = data_decryption_suite.decrypt(encrypted_data) # compute hash function to compare to received_hash fullmessage = s.join([nodeid,iv,sensordata,sessionID]) hmac = HMAC.new(passphrase,fullmessage,SHA) computed_hash = hmac.hexdigest() # see docs.python.org/2/library/hmac.html for how to compare hashes securely
El fin, el principio
Ahora tenemos un sistema que envía mensajes encriptados y autenticados a través de un servidor MQTT a otro cliente ESP8266 o un sistema más grande que ejecuta Python. Los enlaces sueltos siguen siendo importantes si está enlazando eso, si lo está implementando usted mismo. Todas las claves están almacenadas en la memoria flash de los ESP8266, por lo que querrá controlar el acceso a estos dispositivos para evitar la ingeniería inversa. Las claves también se almacenan en el código en la computadora que recibe los datos, aquí ejecutando Python. Además, probablemente desee que cada cliente tenga una clave y una frase de contraseña diferentes. Eso es mucho material secreto para mantener a salvo y posiblemente actualizar cuando sea necesario. Resolver el problema de la distribución de claves sigue siendo un ejercicio para el lector motivado.
Y finalmente, una de las cosas terribles de escribir un artículo sobre criptografía es la posibilidad errar en internet. Esta es una aplicación bastante simple del modo AES-CBC comprobado con HMAC, por lo que debería ser bastante sólido. Sin embargo, si encuentra alguna deficiencia interesante en lo anterior, háganoslo saber en los comentarios.
tomás zerolo dice:
NodeMCU?
¿Esperar lo? ¿Hablas de criptografía y construyes tu "firmware" con algún servicio aleatorio, sin forma de verificar lo que realmente está pasando en la salchicha?
¿En serio?
Elliot Williams dice:
https://github.com/nodemcu/nodemcu-firmware
MS-JEFE dice:
Bueno, te quedas con un desmontaje (por supuesto escrito por ti mismo) ... así como con CUALQUIER plataforma de construcción adecuada.
¿Puede confiar en el compilador C de Microsoft (recuerde la propaganda sobre [and unwanted] inclusión de telemetría en DLL durante la compilación en Visual C hace aproximadamente un año?)?
¿Puedes confiar en GCC, que de vez en cuando genera algún tipo de error (anteriormente sucedía debido a una optimización agresiva, que en algunas versiones optimizaba incluso las instrucciones necesarias para el código)?
¿Puede confiar en MPLAB X, que inyecta código lento en los programas cuando se usa una versión para estudiantes / gratuita? Afirman que la versión paga genera un código al menos un 20% más rápido. Bueno, eso se debe a esas instrucciones que ralentizan (como almacenar W en algún lugar de la RAM y luego volver a leerlo y descartarlo inmediatamente), no un poco de brujería.
¿Alguna vez puedes confiar en algo que no has desenterrado por completo? No. Siempre puede haber algún código malicioso dejado intencionalmente por el creador de la barra de herramientas. Y si ese no es el caso, ¿puede estar seguro de que el código generado por la cadena de herramientas no incluye ningún error? No, hasta que aparezca de alguna manera. Y cuando se trata de eso, ¿puedes confiar en el chip tú mismo? ¿Sabes exactamente qué hay en la ROM interna de ESP8266 (bueno, quizás no estoy seguro aquí)? ¿Sabes qué hay en la ROM interna de STM32 (probablemente no)? ¿Siempre lo sabes todo? No.
No se trata de usar algún servicio automatizado o su propio sistema de implementación, sino de dónde termina su paranoia. O donde te detienes para cuidarte. Casi siempre puede haber algo oculto que puede pasar por alto y que puede repelerlo.
imayoda dice:
Realmente para la clasificación de blobs, pero gcc es de código abierto ... no importa cuántos bytes desordenados escupe, está abierto y los bytes desordenados no se pueden comparar con bytes de malware intencional.
fonz dice:
http://wiki.c2.com/?TheKenThompsonHack
xMob dice:
Me ganaste. 😉
imayoda dice:
incluso un ataque de virus de la gripe es un malware que puede afectarlo horas antes de que se dé cuenta: D
un mundo cruel e imperfectotomás zerolo dice:
https://www.dwheeler.com/trusting-trust/ 🙂
Por cierto, la mayoría de Debian se construye reproducible ahora. Nosotros llegamos ...
Por supuesto, todavía existe el "hardware". Es por eso que los humanos están aquí, ¿verdad?
Moryc dice:
No es MPLAB X, son los propios compiladores XCn, que son AFAIK basados en GCC que deshabilitan el código en una versión gratuita. Solución: edite los archivos ASM generados por XCn y luego compílelos desde ASM o utilice una versión pirateada de XCn, que es ilegal y puede considerarse deshonesta. Por otro lado, estropear deliberadamente el código válido para vender una versión "mejor" del compilador es deshonesto e inmoral, así que ¿por qué no estropearlo? Si está dispuesto a violar la ley, eso es ...
Jonathan Wilson dice:
Lo que no entiendo es por qué nadie llevó el código fuente al compilador XC (que Microchip tiene que publicar ya que está basado en GCC, que es GPL) y lo recompilló para obtener la versión “profesional” de pago completa con todas las optimizaciones para libre. Perfectamente legal bajo los términos de la GPL
En cuanto a las bibliotecas, alguien solo necesita crear un clon de código abierto de esas bibliotecas y decirle a Atmel que se llene.
luma dice:
¡Buen artículo! ¿Alguien puede señalarme una guía similar para realizar la misma tarea bajo el IDE de Arduino?
Elliot Williams dice:
Para el AVR Arduini (UNO y así sucesivamente): https://github.com/DavyLandman/AESLib manejará la parte AES.
¿Qué Arduino?
Hace unos años, intenté que algunas funciones hash de https://github.com/cantora/avr-crypto-lib funcionaran (no recuerdo cuál) y me quedé sin RAM en ATmega168. No sé si ese es todavía el caso o para todas las algas hachís. ¿Alguien? ¿Hash en AVR?
El ESP8266 tiene mucha RAM. El funcionamiento de hash / HMAC en el entorno ESP Arduino debería ser una simple cuestión de llevar algún código (muy portátil).
Si controla la red, el cifrado debería ser suficiente. Si está en Internet, querrá autenticación y las funciones hash.
Dongwaffle dice:
Lo siento, necesito ser más claro, estoy hablando del ESP8266 programado con el IDE de Arduino. Sé que hay varias bibliotecas, pero para alguien que no comprende de forma nativa las complejidades de cómo construir una implementación segura de todas las piezas necesarias (IV, etc.), este tipo de guía sería muy útil.
Sean Boyce dice:
Estoy trabajando en esto. AES en ESP8266 usando el IDE de Arduino tiene algunas rarezas y no es tan simple como en Lua.
Todavía 'funciona' en el sentido de que puedo cifrar cosas (después de cambiar un poco la biblioteca), pero necesitaré algo de tiempo para implementarlo de una manera sensata, y luego un poco más para entenderlo lo suficientemente bien como para explícalo.
En general, no tuve una buena experiencia con el IDE de Arduino en el ESP8266. Implica mucha depuración de bibliotecas. A veces me ahorraba tiempo, pero generalmente no. De todos modos, si tengo éxito, probablemente lo escribiré para las personas que prefieren más la plataforma.
timgray1 dice:
¿Por qué? su esp8266 usa wifi encriptado y su comunicación es a MQTT en su red local. Puedo ver esto por cosas estúpidas como un corredor de MQTT en la nube, pero dentro de su red protegida, ¿quién ya tiene un nivel de cifrado? no hay razón para ello.
Dongwaffle dice:
Utilizo ESP8266 + MQTT en toda mi red doméstica y es completamente inseguro y no he tenido ningún problema hasta ahora, pero eso no significa que sea una buena idea. Además, si quiero llevar mis proyectos de afición a una audiencia más amplia, creo que es irresponsable no intentar al menos asegurar el proyecto de alguna manera básica. Creo que este tipo de guía realmente ayuda a un hacker aficionado como yo.
Urs Eppenberger dice:
Lo mismo aquí: ESP8266 Broker node red
Utilizo SSL para asegurar la conexión.
Tenía un código ejecutándose mientras hacía el cifrado AES de la carga útil, tanto en el ESP8266 como en el lado rojo del nodo. Pero era difícil de mantener y tuve muchos problemas (IV Vektor no funciona, número aleatorio en ESP8266), así que lo dejé caer después de que SLL funcionó.
Este artículo y el ESP32 dan este otro empujón. Tengo que esperar a que los desarrolladores más experimentados hagan el trabajo y algo de documentación. Mi conocimiento se detiene muy pronto, por lo que generalmente publico piezas y piezas juntas hasta que funciona más o menos.Sean Boyce dice:
Sí, esa es exactamente la razón por la que utilizo tales técnicas: mis proyectos de hobby a menudo se vuelven inesperadamente comercialmente viables. Después de que sucedió varias veces, me acostumbré a agregar cifrado desde el principio. Una vez que es un hábito, no agrega mucho trabajo, pero al desarrollarlo, a menudo deseaba que hubiera más ejemplos de código, así que pensé en compartirlo.
Encuentro que el artículo trata tanto del cifrado como de la autenticación, que es más seguro de lo que necesitan muchos proyectos, pero razoné que es mejor pasar el tiempo discutiendo ambos. Si solo desea usar WPA, está bien, pero diferentes herramientas son adecuadas para una variedad de trabajos y todo lo demás.
Ciertamente me he encontrado con situaciones en las que WPA no era suficiente y asumí que no estaba solo en eso. Hay muchos países en los que no puede confiar en sus competidores, personal, ISP y proveedor de alojamiento si está generando datos de algún valor.
frezik dice:
WPA no protege contra un atacante que tenga su clave común. Si lo opera en una red donde se proporciona la clave (como un café o un espacio de piratería), cualquiera puede descifrar esos paquetes.
Jononor dice:
La infraestructura para espacios públicos debe tener su propia red WiFi, separada de la que usan todos. Aunque solo sea por las razones disponibles.
kogepático dice:
> debe tener su propia red WiFi
> Aunque solo sea por razones disponibles.¿Por qué? El cofre de 2.4GHz eliminaría fácilmente cualquier disponibilidad 😉
Separar las redes es una buena idea, pero lo más importante es que los proveedores están enviando dispositivos inseguros y los ciclos de actualización se miden en años (o nunca). Esto es especialmente problemático para los proyectos públicos donde pueden pasar años entre el suministro y la entrega.
Twaroga dice:
En NodeMCU, puede conectarse a un corredor a través del puerto seguro 8883 a través de TLS 1.2 (https://nodemcu.readthedocs.io/en/dev/en/modules/mqtt/#mqttclientconnect) y verificar el certificado del corredor a través del módulo TLS (https: / / nodemcu.readthedocs.io/en/dev/en/modules/tls/#tlscertverify) pero la última vez verifiqué que esta función no funcionaba, cuando usé tls.cert.verify (true) y compilación personalizada con mi certificado en el firmware no se conectará (¡el protocolo de enlace del cliente falló! Motivo:[-0x2700] )
Sean Boyce dice:
Sí, tuve el mismo problema. Mi mejor suposición es que el corredor y el cliente no tenían un algoritmo común. No pude encontrar suficientes documentos para ejecutarlo.
Más en serio, aunque todavía me faltaba memoria. Esto es lo que me llevó a esta solución, que resultó ser más práctica, y asumí que sería mejor documentarla 🙂
Sean Boyce dice:
Actualización: años después, todavía tengo problemas con la implementación de NodeMCU TLS 1.2 sin una memoria que se conecte de forma segura a un corredor de MQTT.
Eventualmente funcionó de manera confiable, pero involucró tanta optimización de código que el método anterior fue más fácil, e implementar cifrados de curva elíptica en el ESP32 es aún más fácil ... y probablemente mucho más seguro.
Puede generar claves públicas del lado del servidor que alguna vez fueron desechables como ID de sesión, cifrar en el ESP32 y luego descifrar el lado del servidor con la clave privada.
Sjaak dice:
es mejor que ninguno, pero impone muchos otros problemas porque el ID de usuario / paso no es "seguro", lo que permite cualquier DOS o sobrecargar el servidor mqtt.
mhwlng dice:
¿Por qué no SSL?
Las bibliotecas de arduino ESP8266 'WiFiClientSecure' tienen SSL / TLS incorporado:
Cliente WiFiClientSecure;
client.connect (host, 443)https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp
Jan Ciger (@ janoc200) dice:
Creo que es que este tipo de tutorial es útil más allá de los protocolos y plataformas que tienen SSL disponible.
Le resultaría difícil implementar SSL en AVR o 8bit-PIC, por ejemplo.
hackadave dice:
Utilizo ESP como "puntos finales" de IoT que se comunican a través de redes wifi locales exclusivas de IoT dedicadas a servidores / concentradores basados en Pi que manejan el cifrado para la comunicación externa. Estas redes en línea dedicadas están protegidas por WPA2 con contraseñas aleatorias (significativamente) largas. Las contraseñas no deben ser fáciles de recordar, solo deben almacenarse de forma segura, por ejemplo, en papel en un dispositivo de memoria seguro o seguro. Esto deja un MQTT auténtico / encriptado para los servidores Pi, lo cual es simple. Estoy buscando cifrado basado en hardware en el futuro, tal vez con ESP32 combinado con hardware de cifrado para Pi. Había un proyecto de Kickstarter para cifrado Pi adicional, pero era demasiado caro. ¿Alguien sabe acerca de una placa criptográfica a un precio razonable para Pi?
dcfusor2015 dice:
Este me parece un plan inteligente. Hace años, cuando comencé mis proyectos de "LAN of Things" aquí y obviamente era IoT simplemente estúpido, al menos para mí, por muchas razones, simplemente puse cosas en mi wifi o LAN por cable sin pensarlo mucho: rasguños, ESP ahora, tu lo llamas.
Comencé a construir un WAP basado en pi-3, pero es especial porque no revisará las cosas de LoT en absoluto, solo júntelas y sirva un montón de páginas web usted mismo, y esa es toda mi LAN, y si hay será un crack - Internet - siempre lo que veas. En mi diseño actual, recién crecido ", todo tiene una página web, y hacer cgi en C para esp no es mi idea divertida, ni navegar a una para obtener datos sensoriales y luego a otra para controlar algo. A veces QUIERO una contribución humana, pero muchas En ocasiones, podría automatizarse si las cosas pudieran comunicarse entre sí, o arquitectónicamente mejor, algo central donde cambiar las reglas es más fácil.hackadave dice:
Lo bueno de este enfoque es que puedo usar protocolos de mensajería sencillos y rápidos basados en UDP, como CoAP, desde terminales ESP, lo que acelera la respuesta y ahorra energía en comparación con los protocolos basados en TCP / IP. Luego, puedo usar node.js, Node-Red y MQTT seguro en un servidor local Pi para alojar un servidor de programas o servidor web que integre todos los dispositivos ESP locales. Usé Blynk en el Pi, pero voy a pasar a algo más flexible y abierto. Todavía no estoy seguro de qué es exactamente.
SlowBro dice:
No veo ningún mecanismo para caducar las claves comprometidas. Si entregaste tu clave a través del canal seguro, creo que habrías perdido un secreto anterior perfecto. Como dominio, un atacante con una clave de compromiso puede comprometer cualquier clave que siga solo mediante la captura de paquetes. Es por eso que elegiría TLS en su lugar. (Perdóname si me perdí algo, porque soy un poco verde en eso).
La falta de verificación del certificado SSL para el ESP8266 con MicroPython me llevó a abandonarlo para mi producto. ESP32 cuesta un dólar más y puede verificar SSL si lo inicia con el firmware de Pycom.
SlowBro dice:
Yo diría que si tiene una clave de compromiso y luego decide actualizar los clientes entregando una nueva clave a través del mismo canal de compromiso, creo que perdería la seguridad y el seguimiento previos perfectos.
Sean Boyce dice:
Sí, esto es una debilidad. Para los casos de uso que pensé, cada dispositivo podría tener su propia clave, por lo que una clave de compromiso es equivalente a un dispositivo roto. Podría cancelar de forma centralizada el acceso a ese dispositivo y enviar uno nuevo.
En mi parte del mundo (Asia), la diferencia de precio entre el ESP8266 y el ESP32 es significativa, es un mercado muy costoso y la entrega de un nuevo dispositivo por clave comprometida es rentable. Dadas las limitaciones, fue una solución aceptable.
Si el costo del ESP32 baja aún más o una nueva plataforma resolverá mejor estos problemas, pasaré a eso y, con suerte, obtendremos un nuevo artículo.
SlowBro dice:
Es extraño que sea mucho más caro. Aquí puedo pedir (desde Asia) ESP32 por $ 1 más. Sí, eso es aproximadamente un 50% más, pero sigue siendo el precio de una buena taza de café. Como un porcentaje del costo total de mis acciones es de aproximadamente el 3%, para mí vale la pena el cambio.
De todos modos, su proceso de pensamiento parece saludable. Existen otras preocupaciones sobre dejar expuestas algunas partes sin cifrar de su canal de datos, como se menciona en otra parte de los comentarios, pero al menos para este problema, parece que lo está resolviendo.
¿Qué tal proporcionar una interfaz de Internet para cambiar la clave? Luego, se podría enviar una nueva clave a través de un canal alternativo.
De hecho, tengo la intención de hacer ambas cosas; TLS para cifrado de datos AES todos e individuales. Si TLS se ve comprometido, el proveedor de SSL se encarga de ese problema. Y si AES se ve comprometido, es solo un dispositivo y se puede contactar al usuario para cambiar la clave por teléfono a través de la interfaz de Internet.
No quiero ser responsable de la próxima botnet de IoT, así que estoy un poco paranoico.
Ian dice:
Mientras lo hacía en C, agregué AES a todos mis 8266 proyectos hace bastante tiempo. Y el generador de números aleatorios de hardware incorporado obtiene un comunicado de prensa bastante bueno de personas serias que están investigando qué tan aleatorio es realmente (¡y es rápido!).
Por lo tanto, es bastante fácil (y funciona bastante rápido) obtener mensajes seguros hacia / desde su programa receptor y colocar una semilla aleatoria en cada sesión para que los diferentes ataques, etc. no funcionen.
Intentar lo mismo en arduio es problemático: solo cifrar paquetes demasiado lento (¡lo intenté!).
En el problema de la clave de compromiso anterior, lo que hice fue permitir que la clave principal se cambiara solo a través de USB. es decir, para que si estuviera comprometida (lo que no sería fácil porque es una clave aleatoria larga generada por hardware) el atacante no podría cambiarla a menos que tuviera acceso físico a los dispositivos. Para ESTE cambio a través de USB se necesita otra llave que nunca se usa a través de wifi ...
Por supuesto, si tienen acceso físico durante un período de tiempo razonable, alguien podría evitarlo, pero casi nada lo detendrá.neon22 dice:
muy interesante. ¿Qué pasa si usó la criptografía en un micrófono en la placa en lugar de nodeMCU?
Axtls se actualizó a 2.1.3 hace una semana en el puerto esp8266lento dice:
Esto puede salir mal de muchas formas. Para los principiantes, el modo CBC se puede romper, que conoce los problemas completos de Oracle. Este problema depende de si se verifica primero o no el HMAC y si el código proporciona un oráculo de relleno obvio. En segundo lugar, si el HMAC no se compara de manera constante en el tiempo, entonces un atacante puede alimentarse de un valor hash que coincidiría parcialmente con el hash comparado y filtrar información en una comparación precisa. Con esto, un atacante podría eventualmente obtener un valor HMAC exacto y enviar su mensaje modificado. Además, CBC puede ser vulnerable a los ataques bitflip, donde un atacante puede cambiar el valor del mensaje descifrado. La implementación adecuada de esto depende del orden del descifrado y la confirmación de la integridad del mensaje. Sugeriría a cualquiera que haga esto que siga usando SSL, pero si realmente insiste en lanzarlo, use algo mejor como el modo GCM AES. Por cierto, no soy un criptógrafo, solo un tipo que hizo la mitad de estos (http://cryptopals.com/).
Sean Boyce dice:
Los mejores planes de ratones y hombres ... están sujetos a objetivos de gestión de precios y límites de dispositivos. Si tengo una Raspberry Pi para cada sensor (y a veces la tengo), ¡estoy totalmente de acuerdo! SSL es la mejor solución y no vale la pena jugar con las técnicas cubiertas aquí, excepto como un ejercicio académico.
Me gusta la idea de seguir analizando el orden en el que el servidor procesa los datos, por ejemplo, el descifrado y la autenticación. He estado pensando mucho en eso últimamente. Si el hash se crea usando algunos datos originales (como una forma de verificar la integridad), entonces lógicamente al menos debe ocurrir algo de descifrado antes de la autenticación. No estoy convencido de que esta sea la mejor manera, y todavía estoy preocupado por los ataques DDoS, pero creo que eso será historia por otro día.
bhass1 dice:
¡Hola, Sean, siempre, siempre, siempre usa Cifrar y luego autenticar! Existen ataques denominados "ataques selectivos de cifrado" (CCA) que se pueden utilizar para romper la seguridad de Autenticar y luego cifrar o Cifrar y autenticar. Encriptar-luego-autenticar deshabilita toda la clase CCA porque los bits encriptados están autenticados. Para hacer esto, cree el texto cifrado a partir del texto sin formato, luego firme (o HMAC) el texto cifrado. En el extremo receptor, verifique el HMAC antes de intentar descifrar los datos. Piense en ello como un sello abusivo en un sobre. Si el sello del dedo está roto, no abra el sobre. Sería peligroso abrir el sobre y luego revisar el sello de un dedo en el interior, ya que el contenido podría manipularse incorrectamente. No ayuda mucho si ya tiene ántrax para descubrir que el sello del dedo se ha roto.
algún chico dice:
Solo quería agradecerle por publicar este enlace, ¡se ve realmente interesante! Me recuerda un poco al Proyecto Euler https://projecteuler.net/ ("una serie de problemas difíciles de programación matemática / informática" pero no centrados en la criptografía)
José Macaulay dice:
Actualmente estoy usando el SDK 2.1.0 NONOS con MBEDTLS para realizar la autenticación del cliente TLS1.2-PKI con Amazon AWS IOT. Estoy trabajando para descubrir AWS IOT Greengrass (lo resolví, solo necesito "terminarlo"). La conexión es un certificado de servidor / cliente y yo uso una clave privada RSA de 2k. Mucho más fácil de lo descrito anteriormente. Investigué el código fuente de NodeMCU e hice modificaciones para admitir la autenticación PKI del servidor / cliente en Amazon AWS. Sin embargo, NodeMCU es grande en comparación con el tamaño de NONOS SDK. NodeMCU quiere 600kb, mientras que mi configuración NONOS usa 350k. Quería apuntar a menos de 512k debido a ESP8285s solo con un tamaño de 1 MB. Quería dividir la ROM por la mitad para poder hacer actualizaciones de OTA (lo que me funciona con los ejemplos de rBoot y los controles de CRC también funcionan bien con OTA).
mxb dice:
Hay hardware para realizar encriptación / validación por menos de un dólar. Específicamente ATECC108A o ATSHA204.
Prefiero usar estos que guardan los certificados en lugares ilegibles. A continuación, puede integrar mejores protocolos de cifrado y HMAC (AES en un chip). Estás en el escudo críptico de Ada si tienes el dinero para eso.SlowBro dice:
mxb Tengo algunos ATECC508 y no sé cómo usarlos en absoluto. Los compré para Mongoose OS, que los admite desde el primer momento del ESP8266 y luego cambié de marcha a un idioma que conozco mejor (Python), que a priori no los admite.
En el contexto de este artículo que protege a Lua, ¿podría compartir cómo ejecutar estos lenguajes y / o Python? Veo que Atmel ha lanzado algunas bibliotecas de C que son adecuadas para los usuarios de ese lenguaje, pero ...
teerencia dice:
¡Hola!
Gran artículo gracias ..
Solo una pregunta estúpida ... No veo cómo funciona la parte de ID de sesión ...
Piense en decir un sensor de temperatura que mostraría la temperatura de un sujeto cada minuto ... ¡a priori no es solo un dispositivo receptor! Puede suscribirse a varios dispositivos para el tema ... ¿qué genera el ID de sesión?Gracias