Recuerda la situación: quieres enviar ese fresco meme picante a tu amigo (digamos) Greg. Abres tu mensajero favorito, encuentras el chat con Greg, adjuntas el meme y le das a enviar.
Entre bastidores, tu mensajero va a alguna nube, lee tu historial de chat de una base de datos, sube tu meme y notifica a tu amigo con una notificación push de que contenido de primera categoría acaba de llegar.
Así es como cada aplicación de chat ha funcionado desde siempre. Incluso un junior que acaba de terminar un curso de "Aprende Python en 21 segundos desde YouTube Shorts", hoy en día puede construirla en una noche con un par de cervezas.
¡Fue una gran época! Vivíamos felices en este mundo simple y pacífico hasta que algunos gobiernos (1, 2, 3) decidieron que ahora también quieren leer nuestros memes picantes en nuestra correspondencia privada y decidir (spoilers para ustedes, occidentales) por cuáles deberíamos ir directamente a la cárcel.
¡Bienvenidos al valiente nuevo internet!
La buena noticia es que el cifrado de extremo a extremo se inventó exactamente para esto: enviar memes picantes a través de canales "no confiables" para que solo el destinatario pueda leerlos.
Tú cifras los datos en tu extremo y aún puedes almacenarlos en algún servidor aleatorio en el que no confías realmente. Sí, todavía no hemos ascendido a la iluminación peer-to-peer – eso viene en la siguiente parte, donde veremos cómo los parlamentos alemán y francés intercambian le memes a través de Matrix. Así que suscríbete para el próximo post, o lo que sea que digan los creadores de contenido.
Todos los chicos cool hoy prefieren el cifrado de extremo a extremo (E2EE) e intentan distanciarse de las "nubes". No solo porque el sufrimiento los hace valientes y sexys. [¿aunque lo hace?] Sino porque son jóvenes y prácticos, entienden que las nubes siguen siendo baratas y convenientes para la mayoría de las personas no frikis.
Mientras el software peer-to-peer "real" siga siendo tan amigable como un reproductor de casetes de 1988, estamos atascados con las nubes. Solo necesitamos ser creativos en cómo las usamos.
Por ahora, volvamos a la situación en la que estábamos enviando nuestro meme picante a Greg. Greg vive a mil millas de distancia de nosotros, así que todavía necesitamos usar esa cosa sospechosa llamada Internet. No hay manera de evitarlo.
Es hora de sumergirnos en cómo funciona realmente el cifrado.
Cubrimos el cifrado asimétrico con sus claves "públicas" y "privadas" en mi antiguo post sobre Blockchain, pero nadie se acuerda de eso, así que empecemos de nuevo.
Todo el cifrado moderno se puede dividir en dos categorías: simétrico (AES) y asimétrico (RSA).
El cifrado simétrico es bastante sencillo – Greg y yo acordamos de antemano una "clave secreta" especial que tanto cifra como descifra todos nuestros mensajes. Es como si ambos tuviéramos llaves del mismo apartamento y pudiéramos pasar en cualquier momento a tomar algo.
¿El problema? De alguna manera necesitamos darnos esa clave en primer lugar.
Con las llaves del apartamento, Greg y yo podríamos encontrarnos en algún callejón tranquilo para el intercambio. Pero en Internet, no hay lugar seguro – estamos constantemente en riesgo de que nuestros datos sean robados o copiados sin siquiera saberlo.
Así que las claves simétricas no son geniales para iniciar nuevas conexiones.
Pero no las tires a la basura todavía. Las claves simétricas tienen grandes ventajas: son mucho más cortas que las asimétricas y mucho más rápidas.
Mira un ejemplo: una clave AES de 128 bits es solo 22 caracteres en base64. Eso es literalmente algo que podrías escribir en la palma de tu mano.
Sin embargo, proporciona una protección sólida según los estándares actuales.
Pero por favor, no te la tatúes.
🔥 Dato curioso: si tomas tu teclado y golpeas tu cabeza con él unas diez veces, el resultado podría funcionar como una clave simétrica terrible. ¡Pruébalo ahora!
La simplicidad y velocidad de las claves simétricas nos vendrán bien cuando cifremos archivos enormes más adelante.
Para evitar enviar claves secretas a través de internet, las personas inteligentes inventaron el cifrado asimétrico.
Con el cifrado asimétrico, todos obtienen dos claves – una clave pública y una clave privada. Estas son básicamente dos números primos muy largos conectados por una fórmula matemática simple que no te diré todavía...
Tu clave privada es súper secreta porque puede descifrar cualquier cosa cifrada con tu clave pública. Pero, ¿tu clave pública? Compártela libremente.
Puedes enviar tu clave pública a Greg, publicarla en tu sitio web, o incluso tuitearla. Cualquiera puede usarla para cifrar un mensaje que solo tú puedes leer.
Para leerlo, por supuesto, necesitas la clave privada. Así que mantén esa a salvo :)
El par de claves pública-privada también tiene un truco inverso genial: si cifras algo con tu clave privada, cualquiera que conozca tu clave pública puede verificar que TÚ lo enviaste, sin siquiera conocer tu clave privada.
¿Para qué sirve eso? ¡Firmas digitales! Como las que usas en banca online o servicios gubernamentales.
Si te asombra toda esta magia matemática, echa un vistazo a "El Libro de los Códigos" de Simon Singh. Salió a principios de los 2000, pero nadie ha escrito nada más claro sobre cifrado desde los tiempos antiguos hasta el (casi) moderno TLS para gente normal.
Ahora podrías estar saltando y gritando: Tío, si estas claves asincrónicas son tan geniales, ¿por qué perdiste mi tiempo con esa cosa de AES?
Primero, es asimétrico, no asincrónico – ¡lee con más cuidado!
Segundo, así es como se ve un par de claves típico:
¿Ves el problema? Estos grandulones pueden, en el mejor de los casos, comerse todo tu cubo de KFC, pero pídeles que cifren un archivo de 10TB y dirán UFFF como tu abuelo en una cinta de correr.
Por eso el internet moderno usa ambos tipos de claves, generalmente juntas, para cancelar las debilidades de cada una.
Y tengo incluso mejores noticias – ¡puedes derivar matemáticamente una de la otra!
Conoce el famoso algoritmo Diffie-Hellman, que hace que los crypto-nerds se emocionen porque te permite crear elegantemente una clave simétrica usando solo dos piezas asimétricas: tu clave privada y la clave pública de otra persona.
Es hermoso y simple: si las claves son solo números, entonces con operaciones matemáticas simples (elevar a potencias, división módulo), ambas partes pueden terminar con resultados idénticos, usando solo las claves públicas del otro lado y sus propias privadas. Sin exponerlas. ¡Brillante!
Sin broma. Cada vez que visitas un sitio web https (incluido este post), tu navegador realiza una versión moderna de Diffie-Hellman para establecer una conexión segura con mi servidor en Alemania y mostrarte el pequeño icono de candado verde en la parte superior de tu navegador.
Así que esto no es solo cosa de nerds – lo has estado usando todo el tiempo. ¡Acéptalo!
¡Genial, conceptos básicos de cifrado cubiertos! Ahora puedes añadir "experto en seguridad" a tu currículum y empezar a ganar dinero.
Entonces, ¿solo intercambiamos claves públicas, ciframos nuestras cosas y las enviamos? ¿Eso es todo? ¿Por qué necesitamos un post entero entonces? ¡Tenemos TikToks que ver!
Los TikToks pueden esperar – tenemos un problema aquí.
Todo lo que he descrito solo funciona para chats individuales entre yo y Greg. Pero en estos días, todos vivimos en chats grupales, y ahí, este enfoque se desmorona por completo.
Abordemos eso a continuación.
Houston, tenemos un problema. Hemos aprendido a cifrar mensajes individuales, pero ahora tenemos un chat con más de 100 personas, y queremos que todo esté bellamente cifrado de extremo a extremo para que las nubes malvadas no puedan ver nuestros memes grupales.
Pensemos en algunas posibles soluciones:
Podríamos pensar en un chat grupal de 100 personas simplemente como 100 chats individuales diferentes. ¿Por qué no, verdad?
Conocemos las claves públicas de todos los demás, así que podemos cifrar cada mensaje por separado para cada persona y enviarlo para que solo ellos puedan descifrarlo, mientras que todos los demás pueden simplemente ignorarlo.
Esto significa que cuando escribimos un mensaje en el chat, lo ciframos 100 veces. O 1000 veces. O un millón de veces si hay un millón de participantes.
¿Ves el problema?
Con este enfoque, incluso si quieres enviar a tus amigos un meme, tu pequeño iPhone luchará tratando de cifrarlo mil veces y no solo se congelará durante varios minutos - agotará tu batería lo suficiente como para que no puedas llamar a un Uber y tengas que caminar a casa.
Pero olvídate de tu iPhone - habrá uno nuevo el próximo año de todos modos. Hay otro problema: en lugar de una imagen de 1MB, necesitas almacenar 1,000 archivos cifrados idénticos, alrededor de 1 GIGABYTE de datos por cada meme. A ningún servidor le gustará eso.
Después de solo un par de memes, tu chat de amigos ocupará más espacio en el servidor que átomos en el universo, y tu asignación mensual de datos durará unos quince segundos.
¿Es este el futuro que quieres? No parece ser así. Así que olvida esta opción - es basura. Veamos la siguiente.
Todos acuerdan una clave de cifrado común para todo el chat, que pueden usar para cifrar y descifrar cualquier mensaje dentro. Esta clave es simétrica para todos, como aprendimos anteriormente.
En la práctica, generalmente la persona que inició el chat la genera y luego la comparte a través de "alguna" conexión segura con todos los demás participantes (usando sus claves asimétricas, por ejemplo).
No sonrías - esta es en realidad una opción decente. Muchos chats cifrados "antiguos" funcionaban exactamente de esta manera durante años, ¿por qué no?
La clave compartida se transmite por la red en forma cifrada, es fácil añadir nuevas personas al chat dándoles nuestra clave, y la nube malvada nunca la conoce. ¡Nuestros mensajes están a salvo!
Pero todavía hay algunos problemas.
Primero: ¿cómo eliminamos usuarios del chat?
Está bien, si mis amigos y yo tenemos más de 130 puntos de ICQ (en total), podríamos inventar un sistema donde cuando un usuario es eliminado, todos los demás generan una nueva clave compartida para proteger los mensajes futuros.
Pero esto crea nuevos problemas técnicos con la comunicación de esta nueva clave a los participantes que están desconectados en este momento - pierden temporalmente el acceso al chat hasta que vuelvan a conectarse y reciban la nueva clave.
Bien, eventualmente todos la obtendrán - podemos descartar esto como un "problema de UX". Tal vez les enviemos una notificación push especial, pidiéndoles que se conecten y actualicen sus claves. Solucionable.
Pero hay un problema más serio: filtración de claves.
En un chat con mil personas, esto sucederá tarde o temprano - alguien subirá una copia de seguridad sin cifrar a iCloud, dejará su teléfono en un bar, o los hackers futuros podrían simplemente forzar nuestra clave. La probabilidad de esto último es extremadamente pequeña, pero nunca cero. Un chat podría usar la misma clave durante años, dando a los hackers mucho tiempo para comprar todas las GPUs y hackearte.
Los memes serios necesitan garantías más serias.
Aunque no desecharemos completamente este método. El protocolo MTProto de Telegram en chats secretos funciona exactamente de esta manera, a pesar de todas las desventajas. Intentan suavizarlo con trucos de UX, ofreciendo, por ejemplo, auto-eliminación de mensajes después de 20 segundos.
🧠 Puedes confirmar esto fácilmente ahora mismo creando un chat secreto en Telegram - te dirá algo como "esperando a que la otra persona se conecte e intercambie claves contigo" y no te permitirá enviar ningún mensaje hasta entonces. Ahora sabes por qué :)
Más adelante aprenderemos que incluso el tan amado Matrix usa una "clave de sesión" (que es lo mismo) para mejorar el rendimiento en chats grandes. Simplemente rota con más frecuencia. Así que no todo es blanco y negro.
Esto es similar a la opción anterior, pero ahora acordamos una nueva clave compartida para cada mensaje enviado. Ahora una filtración de clave no es aterradora - solo podría descifrar un mensaje específico [¿que probablemente también se filtró?], no todo el chat.
Pero ya descubrimos que enviar una nueva clave entre todos los participantes cada vez es una locura. Necesitamos algún truco ingenioso aquí.
Entonces, imagina que nuestro chat está comenzando. Los participantes intercambian claves y obtienen una clave compartida. [¿esto es fácil de hacer al principio porque cada usuario hace clic en el botón Unirse al Chat por sí mismo?] Pero en esta tercera opción, además de la clave, también acuerdan una cosa más - un algoritmo especial que permite a cada participante derivar matemáticamente la siguiente clave sin pedir ayuda a otros.
Puedes visualizar esto como una caja mágica donde ponemos nuestra vieja clave en un lado, giramos una manivela, y escupe una nueva.
Dada la misma clave de entrada, la caja siempre producirá el mismo resultado. Para todos los usuarios. Incluso desconectados. Y será física y matemáticamente imposible girar la manivela hacia atrás y obtener la clave original de la nueva.
¿Cómo? Es simple, incluso un escolar podría entenderlo: podemos multiplicar nuestra clave por algún número primo.
Aquí hay un experimento mental: te doy un papel con dos números - 107 y 283, y te pido que los multipliques. Sacas una calculadora de tu bolsillo y al instante me dices la respuesta - 30281.
Tomó unos cuatro segundos, ¿verdad?
Ahora imagina lo contrario: te doy un papel con 30281 escrito y te pido que me digas qué dos números acabo de multiplicar para obtener este resultado.
¿Difícil? ¿La calculadora no ayuda? Exactamente.
Este ejemplo está muy simplificado pero ayuda a entender cómo podría funcionar nuestra caja mágica - derivando fácilmente una nueva clave de una vieja, pero no viceversa. [¿Esto suena a Diffie-Hellman? ¡Debería!] Los expertos en criptografía llaman a este proceso derivación, y la nueva clave es una "clave derivada". Ese es solo un término elegante que puedes soltar para impresionar a tus amigos.
Un algoritmo que funciona en una dirección pero no en la otra se llama mecanismo de trinquete. Probablemente has visto un destornillador de trinquete o llave que gira fácilmente en una dirección pero no en la otra. De ahí viene el nombre.
A partir de ahora, llamaré a este generador de claves matemágicas simplemente un "trinquete".
OK, así que nuestro trinquete nos da una nueva clave para cada nuevo mensaje.
Si una clave se filtra, los hackers no podrán girar el trinquete hacia atrás para obtener claves antiguas y leer mensajes anteriores - eso es bueno. [¿los expertos en criptografía llaman a esta propiedad "Forward Secrecy", aunque es más como Backward Secrecy, pero quiénes somos para juzgar a las personas inteligentes aquí?] Pero, ¿qué pasa con los nuevos mensajes? El trinquete todavía puede girarse hacia adelante fácilmente.
El problema es que solo hay un número finito de algoritmos para nuestro trinquete. Tal vez una docena de algoritmos estándar. O hasta un centenar si cuentas los no estándar.
No inventamos un nuevo algoritmo de trinquete cada vez para cada nueva aplicación. ¡En criptografía, inventar algoritmos propios es una muy mala práctica!
Pero esto significa que un hacker que robe una clave puede simplemente probar todos los algoritmos conocidos de Wikipedia y encontrar el correcto para descifrar todos nuestros mensajes futuros. Necesitamos arreglar esto. ¡Nuestros memes todavía están en peligro!
¿Y si nuestro trinquete tuviera algún tipo de código, como un candado de combinación? ¿Y dos trinquetes idénticos solo producirían el mismo resultado si el código en ellos coincide?
Básicamente, como dirían los programadores, el trinquete ahora tiene un estado que afecta cómo funciona.
Cualquiera que recuerde cómo funcionaba la famosa máquina de cifrado Enigma debería estar teniendo flashbacks de guerra ahora mismo. Estamos literalmente reinventando la misma cosa una y otra vez...
Pero espera, ¿esto no nos devuelve a la Opción 2 con todos sus problemas? ¿Cómo nos pondremos de acuerdo todos en este código? ¿Cómo se lo diremos a las personas que están desconectadas?
¿Y si otro participante del chat está bebiendo cerveza en un bar del vecindario y no puede parar ahora mismo para generarte una nueva clave pública?
No te preocupes. Déjalos terminar su bebida. Mira atentamente: no necesitamos acordar un nuevo código para cada mensaje - solo cuando la otra persona quiere respondernos. Así:
Así que el código solo cambia cuando el segundo participante se conecta y decide escribirnos de vuelta. Hasta entonces, seguimos generando nuestras claves con el mismo código.
Esto significa que podemos usar nuestro familiar algoritmo Diffie-Hellman para intercambiar el nuevo código.
El segundo participante adjunta su nueva clave pública a sus mensajes, y nosotros calculamos un nuevo código compartido y configuramos nuestro trinquete para descifrar lo que escribieron.
Esto crea un intercambio completamente asincrónico - no necesitamos estar en el chat y responder. Leeremos y calcularemos todos los códigos y trinquetes cuando volvamos a conectarnos.
La próxima vez que queramos responder, adjuntaremos de manera similar nuestra nueva clave pública, y el otro participante puede tomarla (a menudo directamente del mensaje) y calcular el siguiente código en su lado. ¡El problema de estar desconectado está resuelto!
Incluso si un hacker irrumpe en nuestro chat en algún momento en medio de mi monólogo, podrían descifrar unos pocos mensajes, pero después de un nuevo intercambio de códigos, perderán la capacidad de descifrar nuestro acogedor y pequeño chat nuevamente.
Este algoritmo se llama Double Ratchet y su capacidad para "auto-curarse" después de una brecha es una de sus principales características.
Te recomiendo que veas este gran video:
Todos los chats individuales cifrados en mensajeros modernos como WhatsApp, Signal, Matrix usan alguna variación del mecanismo Double Ratchet. Excepto Telegram, que no cifra los chats regulares en absoluto, usa el antiguo método de clave compartida para chats secretos y no puede cifrar chats grupales en absoluto.
¿Sabes quién más no puede cifrar chats grupales? Double Ratchet 🤡🤡🤡
Espera, ¿qué? ¿Qué pasa con los chats grupales? ¿Pasamos por todo esto solo para llegar a un algoritmo que solo funciona para chats individuales OTRA VEZ? ¿Estás drogado o algo así?
Sí. Así que este post no ha terminado todavía. Tendrás que aguantarme un poco más.
Los mensajeros modernos casi siempre usan diferentes tipos de algoritmos para chats grupales versus chats individuales. Double Ratchet funciona muy bien para chats 1-1. La lógica de chat grupal es mucho más compleja y generalmente está llena de trucos que los desarrolladores usan para equilibrar entre seguridad y buena UX.
Hasta ahora, no les está yendo muy bien :) Cualquiera que haya usado seriamente Matrix, especialmente en grupos con más de 500 personas, sabe exactamente de lo que estoy hablando.
"No se puede descifrar el mensaje" todavía me viene mientras duermo.
De todos modos, para darte una perspectiva de lo vanguardista que es este tema - el primer estándar de cifrado real para mensajes de chat grupal, MLS (Messaging Layer Security), solo se lanzó en 2023. ¡Eso es más nuevo que ChatGPT, amigos! Literalmente estamos hablando de tecnología de punta aquí. [¿aunque por supuesto lo habían estado desarrollando desde la década anterior?]
Antes de MLS, cada aplicación de chat inventaba sus propios alucinantes algoritmos de cifrado para grupos, pero ahora todos finalmente se están poniendo de acuerdo y gradualmente moviéndose a este estándar.
Así que guarda tu Double Ratchet en el cajón y conoce - ¡Árbol de Trinquetes!
El principal problema que resuelve este árbol es cómo acordar rápidamente una sola "clave" para nuestros trinquetes de cifrado como grupo sin transmitirla N×N veces entre cada participante.
Está construido bastante simplemente: primero, cada participante del chat comienza en la parte inferior de un árbol binario básico.
No todas las ramas del árbol tienen que estar ocupadas. El chat podría tener un número impar de participantes, y la gente va y viene.
Luego hay nodos más arriba - desde los usuarios hasta la raíz. Estos nodos intermedios no hacen nada; son solo una abstracción conveniente para obtener una clave raíz común.
Cada nodo del árbol tiene su propio par de claves pública-privada. Algo así:
Las claves públicas no son secretas, así que todos los participantes del chat pueden conocerlas. Pero las claves privadas son más interesantes.
En el estándar MLS, las claves privadas de los nodos del árbol solo son conocidas por los usuarios que tienen un camino directo desde ellos mismos hasta la raíz del árbol. Así que Greg, por ejemplo, solo conoce estas claves privadas:
Cada participante del chat almacena el árbol completo localmente.
Para "sus" nodos (los que van desde ellos hasta la raíz), conocen las claves privadas; para "otros" - solo las claves públicas. Pero lo más importante, la razón de todo este circo - cada participante del chat conoce la clave privada del nodo más alto del árbol. Su raíz. Esta clave es el "código" que todos introducen en sus cajas de trinquete para leer y firmar nuevos mensajes.
Todos los usuarios en un chat así viven en armonía y paz, generando nuevas claves usando la raíz común, y cifrando mensajes con ellas. Todo es agradable y pacífico.
Y entonces un día, Greg dice: "Oye, ¿invitamos a Bob al chat?" Después de todo, los chats grupales se inventaron para invitar gente a ellos, ¿verdad?
Bob irrumpe en el chat. Lo primero que hace es tomar cualquier lugar libre en el árbol. [¿Si no hay lugares libres, todo el árbol crece y recalcula claves para nuevos nodos intermedios?]
Greg toma la clave pública de Bob, cifra la instantánea actual del árbol con todas las claves (excepto las privadas) y la envía a Bob. Esto se llama un Mensaje de Bienvenida.
Hay un problema inmediato - Bob todavía no tiene ninguna clave privada. Así que aún no puede cifrar mensajes con nosotros. Para eso, necesita la clave raíz.
Y no podemos simplemente decirle las viejas claves privadas del árbol hacia arriba, porque entonces podría leer nuestros mensajes anteriores, ¿y qué pasa si había memes poco halagadores sobre él?
¡Es hora de crear una nueva clave raíz!
La belleza de nuestro árbol es que cualquier participante del chat (excepto Bob) puede crear una nueva clave raíz.
Así que dejemos que Greg haga el trabajo por todos.
Paso 1: Greg desecha sus claves y crea nuevas. Puede crearlas desde cero o usar un trinquete por estilo - no importa.
Paso 2: Greg gira la manivela de su trinquete para generar nuevas claves para todos los nodos desde él mismo hasta la mismísima raíz. Esta regeneración ascendente es por lo que se llama Árbol de Trinquetes.
Ahora Greg conoce la nueva clave raíz, pero los demás aún no.
Paso 3: Ahora Greg necesita comunicar de manera segura la nueva clave a otros participantes del chat.
Comencemos con el vecino más cercano de Greg. Viven cerca, así que ambos conocen la clave directamente encima de ellos en el árbol.
Greg puede cifrar la nueva clave con la antigua clave pública de este nodo compartido y enviar este mensaje a su vecino - "Bob, toma, usa esto ahora."
Bob puede descifrarlo y leerlo ya que también conoce la clave del nodo compartido, luego enciende su trinquete y, al igual que Greg hizo antes, calcula todas las claves desde él mismo hasta la raíz del árbol. Y como el trinquete de todos funciona de la misma manera, la magia de las matemáticas sucede y ¡Bob obtiene exactamente las mismas claves que Greg obtuvo antes! ¡Incluyendo la nueva clave raíz!
Paso 4: Con los vecinos de otro distrito, es más o menos la misma historia. Greg toma la conocida clave del subárbol vecino, cifra la nueva clave privada con ella y la pasa a los trabajadores en el chat.
Y los trabajadores no necesitan regenerar sus claves - pueden quedarse como están; solo necesitan aprender la nueva clave raíz.
Lo mismo sucede con el resto del árbol. Puedes entender esto por analogía - no eres tonto.
En total, Greg solo necesita enviar 3 mensajes para que los 8 participantes del chat aprendan la nueva clave raíz. Con números pequeños esto puede parecer trivial, pero si hay, digamos, 15,000 personas en el chat, una rotación completa de claves tomará solo 14 transmisiones, no 15,000. Por ese tipo de eficiencia, los desarrolladores merecen al menos una caja de cerveza.
Aquellos que se atiborraron de LeetCode toda la noche para las entrevistas deberían ahora explicar a todos que pasamos de una complejidad O(n) a O(log), por lo que todo se volvió tan hermosa, costosa y ricamente mejor.
La misma situación ocurre cuando se elimina a un usuario del chat. La clave raíz rota para que la persona eliminada no pueda leer nuevos mensajes. La persona responsable de la rotación de claves en este caso es o bien quien hizo la eliminación o simplemente alguna persona desafortunada al azar del chat.
¡Voilà!
Este árbol de claves ni siquiera necesita almacenarse directamente en el servidor - puede ser virtual y almacenarse directamente en el ordenador de cada participante del chat. Esa es la segunda fortaleza de MLS - funciona muy bien en chats peer-to-peer.
Pero hablaremos de esos la próxima vez.