diff --git a/es/xchat/cryptography-primer.mdx b/es/xchat/cryptography-primer.mdx index cc2c53ef3..9a2bcd562 100644 --- a/es/xchat/cryptography-primer.mdx +++ b/es/xchat/cryptography-primer.mdx @@ -1,297 +1,261 @@ --- -title: Introducción a la criptografía -sidebarTitle: Introducción a la criptografía -description: Aprende los conceptos de ECDH, cifrado de clave pública y firmas digitales detrás del cifrado de extremo a extremo de X Chat sin detalles de implementación. -keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "digital signatures", "conversation keys"] +title: Manual básico de criptografía +sidebarTitle: Manual básico de criptografía +description: "Los conceptos detrás del cifrado de extremo a extremo de X Chat: cómo se protegen tus mensajes." +keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "ECIES", "digital signatures", "conversation keys"] --- -import { Button } from '/snippets/button.mdx'; +X Chat está cifrado de extremo a extremo: los mensajes de un usuario, en texto plano, solo existen en sus dispositivos. Esta página explica cómo funciona. -Esta introducción explica las ideas criptográficas detrás de X Chat a nivel conceptual. No necesitas esta profundidad para construir—el [Chat XDK](/es/xchat/xchat-xdk) realiza el cifrado, descifrado, firma y almacenamiento de claves por ti—pero el modelo mental ayuda cuando diseñas tu app o depuras su comportamiento. - -Cuando estés listo para implementarlo, usa [Primeros pasos](/es/xchat/getting-started) para un recorrido completo y la [referencia de la API](/x-api/chat/get-chat-conversations) en la barra lateral para las rutas individuales. -**Tú no implementas esta criptografía por tu cuenta.** El Chat XDK se encarga. Esta página es para entender, no una lista de verificación de la API. +**Esta página es informativa. No necesitas este conocimiento para construir (el [Chat XDK](/xchat/xchat-xdk) realiza cada operación aquí por ti).** --- ## El panorama general -X Chat usa un sistema de cifrado por capas donde: +Veamos el flujo completo desde la creación de la cuenta hasta el envío y recepción de mensajes. -1. Los **mensajes** se cifran con una **clave de conversación** (cifrado simétrico rápido) -2. Las **claves de conversación** se cifran para cada participante usando su **clave pública de identidad** (intercambio de claves asimétrico) -3. Los **mensajes se firman** con la **clave de firma** para que los destinatarios puedan verificar quién los envió y que nada fue alterado + + + Aquí el Chat XDK genera dos pares de claves en tu dispositivo: -El cifrado simétrico es eficiente para grandes volúmenes de tráfico de mensajes; el cifrado asimétrico se usa principalmente para **distribuir** claves de conversación de manera segura. + - un **par de claves de identidad**, para recibir secretos + - un **par de claves de firma**, para demostrar la autoría -```mermaid -flowchart TB - subgraph "Message Encryption" - A[Your Message] --> B[Encrypt with
Conversation Key] - B --> C[Encrypted Message] - end - - subgraph "Key Distribution" - D[Conversation Key] --> E[Encrypt with
Recipient's Public Key] - E --> F[Encrypted Key
for Recipient] - end - - subgraph "Authentication" - C --> G[Sign with
Your Private Key] - G --> H[Signature] - end -``` + Las mitades privadas van a la [copia de seguridad segura de claves](#secure-key-backup-distributed-key-storage), que detallaremos más adelante. Lo importante aquí es que solo son recuperables con tu código de acceso; X no puede recuperarlas. -En el flujo del producto, X transporta **texto cifrado y sobres de clave**—no contenido legible del mensaje ni la clave de conversación en bruto. Tu app usa el Chat XDK para la criptografía y la [Chat API](/es/xchat/introduction) (a través del XDK en Python/TypeScript, o HTTPS) para registrar claves y enviar o recibir esos payloads cifrados. Consulta [Primeros pasos](/es/xchat/getting-started) para ver cómo encajan estas piezas. + Las mitades públicas se publican al backend de X a través de la API de **public key**, con una firma que vincula las claves de identidad y de firma entre sí. +
+ + Para enviarte un mensaje, el remitente genera una nueva **clave de conversación**, una clave simétrica que cifrará los mensajes. ---- + Descarga tu clave pública desde el backend de X, verifica la firma que la acompaña y cifra la clave de conversación con tu clave de identidad. -## Tipos de claves explicados + Esta es una propiedad crucial de la criptografía de clave pública: cualquiera puede cifrar hacia tu clave pública; **solo tu clave privada puede descifrar, y solo tú la tienes**. Así que X puede almacenar y entregar la copia cifrada, pero nunca abrirla. (Para los esquemas exactos utilizados, consulta el [glosario](#glossary).) -X Chat usa tres tipos de material de clave, cada uno con un propósito específico. + ¿Por qué no ciframos los mensajes directamente con tu clave pública? Por velocidad: el cifrado de clave pública es mucho más costoso que el cifrado de clave simétrica, por lo que intercambiar una clave permite una mejor eficiencia para los mensajes posteriores. + + + Cuando alguien te envía un mensaje, recibirás la clave de conversación, cifrada con tu clave pública de identidad, y los mensajes cifrados con la clave de conversación. -### 1. Par de claves de identidad + Usas tu clave privada de identidad para descifrar la clave de conversación (de nuevo, solo tú tienes esta clave) y luego usas la clave de conversación resultante para descifrar los mensajes. -**Propósito:** Intercambiar de manera segura claves de conversación entre usuarios + De vez en cuando, las claves en una conversación rotan (se comparte una nueva clave simétrica), por diferentes motivos. Por eso, cada clave de conversación tiene una versión para que los participantes siempre sepan que están usando la clave correcta. + + + El cifrado permite que cualquiera te envíe un mensaje que solo tú puedes descifrar. La firma es, en cierto sentido, lo contrario: te permite (y solo a ti) firmar un mensaje, y a cualquiera verificar la firma. En la práctica, la clave privada es necesaria para firmar, y la clave pública puede usarse para verificar. -| Componente | Descripción | -|:----------|:------------| -| **Clave pública de identidad** | Se comparte con otros; se usa para cifrar claves de conversación *dirigidas a* ti | -| **Clave privada de identidad** | Se mantiene en secreto; se usa para descifrar claves de conversación enviadas *a* ti | + En X Chat, cada remitente firma su mensaje. Las firmas prueban tanto quién firmó el mensaje como los bytes exactos firmados, así todos los destinatarios pueden verificar que este mensaje exacto es lo que el remitente escribió. Nuevamente, el XDK se encarga de esto por ti; cubrimos los detalles en [Firmas explicadas](#signatures-explained). + +
-Cuando alguien te añade a una conversación, cifra la clave de conversación usando tu clave pública de identidad. Solo tu clave privada de identidad puede descifrarla. +--- -Las mitades públicas se registran y se descubren a través de las APIs de **public-key** de la plataforma (consulta Claves de cifrado en la referencia de la API). Las mitades privadas permanecen en el Chat XDK (por ejemplo, mediante [copia de seguridad segura de claves](#secure-key-backup-distributed-key-storage) o un blob de claves cuidadosamente protegido). +## Poniéndolo todo junto -### 2. Par de claves de firma +X Chat combina tres herramientas criptográficas estándar, cada una haciendo el trabajo en el que es buena: -**Propósito:** Demostrar que fuiste el autor de un mensaje +1. Una **clave de conversación** cifra los mensajes: simétrica, lo bastante rápida para todo el tráfico de mensajes y multimedia. +2. Un **par de claves de identidad** entrega las claves de conversación a cada participante sin que nadie más (incluido X) las vea. +3. Un **par de claves de firma** demuestra la autoría: cada mensaje lleva una firma que los destinatarios verifican. -| Componente | Descripción | -|:----------|:------------| -| **Clave pública de firma** | Se comparte con otros; se usa para verificar tus firmas | -| **Clave privada de firma** | Se mantiene en secreto; se usa para firmar tus mensajes | +```mermaid +flowchart TB + subgraph "Message Encryption" + A[Your Message] --> B[Encrypt with
Conversation Key] + B --> C[Encrypted Message] + end -Cuando envías un mensaje, se firma con tu clave privada de firma. Los destinatarios lo verifican usando tu clave pública de firma (también publicada a través de las APIs de public-key). El Chat XDK firma como parte del cifrado de un mensaje y puede verificar al descifrar cuando proporcionas el material de clave pública del remitente. + subgraph "Key Delivery" + D[Conversation Key] --> E[Wrap to Recipient's
Identity Public Key] + E --> F[Encrypted Key Copy
for Recipient] + end -### 3. Clave de conversación + subgraph "Authentication" + C --> G[Sign with Your
Signing Private Key] + G --> H[Signature] + end +``` -**Propósito:** Cifrar y descifrar mensajes (y [contenido multimedia](/es/xchat/media)) dentro de una conversación específica +X transporta y almacena únicamente **texto cifrado y claves envueltas**, nada que pueda abrir. El XDK hace la criptografía; la [Chat API](/xchat/introduction) registra las claves y mueve las cargas cifradas ([Primeros pasos](/xchat/getting-started)). -| Propiedad | Descripción | -|:---------|:------------| -| **Simétrica** | La misma clave cifra y descifra | -| **Por conversación** | Cada conversación tiene su propia clave | -| **Compartida entre participantes** | Todos los participantes que deban leer la conversación tienen una copia | -| **Versionada** | Las claves pueden rotarse; las apps deben rastrear las versiones a lo largo del tiempo | +El elenco completo: -Las claves de conversación se generan cuando se configura una conversación o cuando las claves rotan. Cada participante recibe una **copia cifrada** de la clave, generada con su clave pública de identidad. Después de descifrar tu copia una vez, guardas la clave de conversación en **bruto** y la usas para el cifrado rápido de mensajes (y [contenido multimedia](/es/xchat/media)). La configuración de esas copias para una conversación se realiza mediante el Chat XDK junto con los endpoints de **key** de conversación—se recorre en [Primeros pasos](/es/xchat/getting-started#4-set-up-conversation-keys). +| Clave | Quién la tiene | Qué hace | +|:------|:---------------|:---------| +| **Identity keypair** | Mitad privada: solo tú. Mitad pública: publicada | Recibe claves de conversación envueltas | +| **Signing keypair** | Mitad privada: solo tú. Mitad pública: publicada | Firma mensajes y cambios de estado; otros verifican | +| **Conversation key** | Cada participante de una conversación | Cifra mensajes y multimedia; con versión, rota | --- -## Cómo funciona el cifrado (conceptualmente) +## Un ejemplo práctico -### Enviar un mensaje +Veamos qué sucede en realidad cuando creas un grupo con Bob y Carol. - - Escribes: "Hola, ¿cómo estás?" - - - Tu app usa la clave de conversación en bruto para este chat (de la configuración o de un evento anterior de distribución de claves), para la versión de clave correcta. - - - El Chat XDK cifra tu mensaje con la clave de conversación. El resultado es texto cifrado que es inútil sin esa clave. + + El XDK genera una nueva clave de conversación aleatoria. Hasta ahora existe solo en memoria en tu dispositivo. - - El Chat XDK firma el payload cifrado con tu clave privada de firma, demostrando que fuiste el autor de este contenido exacto. + + Tu app descarga las claves públicas de Bob y Carol desde el backend de X y verifica la firma de cada una. Si una firma no cuadra, te detienes; nunca cifres hacia una clave que no pudiste verificar. - - Tu app envía el payload cifrado y la firma a X a través del endpoint **send message** de la Chat API. X almacena y entrega bytes que no puede leer como texto plano. - - - -### Recibir un mensaje - - - - Tu app recibe texto cifrado de X—a través de [webhooks o un activity stream](/es/xchat/real-time-events), o al leer **events** de conversación para el historial. + + El XDK envuelve la clave de conversación tres veces: para la clave pública de identidad de Bob, la de Carol y la tuya (para que tus otros dispositivos también puedan leerla). - - Usa tu clave en bruto en caché, u obténla descifrando tu copia desde un evento de distribución de claves (cambio de clave) si es nueva o rotada. + + El XDK firma una carga que describe exactamente este cambio: el grupo, sus miembros, las claves envueltas. Crear un grupo necesita **dos** [firmas de acción](#signed-state-changes-action-signatures); el XDK produce ambas por ti. - - El Chat XDK comprueba la firma usando la clave pública de firma del remitente (y el enlace de identidad asociado), para que sepas quién lo envió y que no fue modificado. + + Tu app hace POST de las copias envueltas y las firmas a X. El servidor almacena tres blobs cifrados que no puede abrir. ¡En ningún momento la clave de conversación en bruto salió de tu dispositivo! - - El Chat XDK descifra con la clave de conversación. Ahora puedes leer: "Hola, ¿cómo estás?" + + El XDK de Bob desenvuelve su copia con su clave privada de identidad, verifica que el cambio de clave provino de ti y guarda la clave de conversación en bruto. -La implementación de cifrar, enviar, recibir y descifrar está en [Primeros pasos](/es/xchat/getting-started) y en la referencia del [Chat XDK](/es/xchat/xchat-xdk). - ---- - -## Distribución de claves explicada - -Un desafío central en el cifrado de extremo a extremo es la **distribución de claves**: cómo los participantes obtienen la clave de conversación **sin** que X (o un observador) vea esa clave en claro. - -### Configuración inicial de la clave +Esa es la configuración única. A partir de aquí, cada mensaje sigue los mismos dos flujos: -Cuando se prepara una conversación para mensajería: +**Envío.** El XDK cifra tu mensaje con la clave de conversación actual, lo firma, y tu app hace POST de ambos al endpoint **send message**. X almacena y entrega bytes que no puede leer. -1. El Chat XDK genera una clave de conversación aleatoria -2. El Chat XDK cifra esa clave para **la clave pública de identidad de cada participante** -3. Tu app publica esas copias cifradas a través de las Chat APIs de X -4. Cada participante descifra **su** copia con su clave privada de identidad (en el Chat XDK) +**Recepción.** El texto cifrado llega a través de [webhooks o un activity stream](/xchat/real-time-events), o leyendo los **events** de la conversación para el historial. El XDK verifica primero la firma del remitente, luego descifra con tu clave de conversación almacenada (si la clave rotó, un evento **key change** entrega tu nueva copia envuelta). Si la verificación falla, el mensaje se rechaza. -X solo maneja las copias **envueltas**, nunca la clave de conversación en bruto. - -### Eventos de cambio de clave - -Cuando la clave de conversación rota (por ejemplo cuando cambia la membresía), los participantes reciben un evento de **cambio de clave** con nuevas copias cifradas para cada miembro. - -Tu app debe: - -1. Detectar material de cambio de clave en eventos en vivo o en el historial de la conversación -2. Descifrar y almacenar la nueva clave de conversación (y versión) -3. Usar la versión más reciente para los envíos posteriores - -[Primeros pasos](/es/xchat/getting-started#6-receive-and-decrypt) y [Eventos en tiempo real](/es/xchat/real-time-events) describen dónde aparecen esos eventos en la práctica. +La implementación vive en [Primeros pasos](/xchat/getting-started) y en la referencia del [Chat XDK](/xchat/xchat-xdk). --- ## Copia de seguridad segura de claves: almacenamiento distribuido de claves -Tus claves **privadas** de identidad y de firma deben almacenarse con cuidado. X Chat incluye un sistema de **copia de seguridad segura de claves** para que las claves puedan recuperarse con un código de acceso en distintos dispositivos sin darle a un solo servidor el secreto completo. +Antes dijimos que tus claves privadas se guardan en la **copia de seguridad segura de claves**, recuperables solo con tu código de acceso. Veamos cómo funciona, porque es la parte sobre la que la gente es más escéptica: ¿cómo pueden las claves respaldarse sin que X pueda leerlas? -### El problema con el almacenamiento tradicional de claves +### El problema del almacenamiento tradicional de claves | Enfoque | Problema | -|:---------|:--------| -| Almacenar solo en el dispositivo | Perder el dispositivo = perder las claves = perder acceso al historial de mensajes | -| Almacenar en una copia de seguridad en la nube común | El proveedor podría acceder al material de la clave | -| Recordar una clave larga | Las personas no pueden memorizar de forma confiable claves de alta entropía | +|:--------|:---------| +| Guardar solo en el dispositivo | Perder el dispositivo = perder las claves = perder acceso al historial de mensajes | +| Guardar en un backup en la nube común | El proveedor puede acceder al material de la clave | +| Recordar una clave larga | Las personas no pueden memorizar secretos de alta entropía | ### Cómo lo resuelve la copia de seguridad segura de claves -La copia de seguridad segura de claves combina **compartición de secretos** con **protección por código de acceso**: +X Chat usa el protocolo de código abierto [**Juicebox**](https://juicebox.xyz), que combina **compartición de secretos con umbral** con protección por código de acceso. El protocolo completo está especificado allí; la versión corta: + +**Almacenar (una sola vez, al crear la cuenta).** El XDK divide tus claves privadas en fragmentos y los distribuye a tres **realms**, servicios separados aislados entre sí. Los tres son operados por X, así que el aislamiento por sí solo no significaría gran cosa. Ahí es donde entra el hardware: dos de los realms viven dentro de **módulos de seguridad de hardware** (HSM), hardware resistente a manipulación que no entregará su fragmento a nadie, ni siquiera a un administrador de X con acceso completo al servidor. Un fragmento por sí solo no revela nada, y la recuperación requiere fragmentos de **dos de los tres** realms, por lo que cada recuperación posible pasa por al menos un HSM: no hay un camino solo por software hacia tus claves. El software del HSM y la **key ceremony** que lo aprovisionó están documentados públicamente. + +**Recuperar (nuevo dispositivo).** Ingresas tu código de acceso, y el XDK demuestra a cada realm que lo conoces. El protocolo Juicebox hace esto posible sin que el código de acceso salga jamás de tu dispositivo. Cada realm que te verifica libera su fragmento de tus claves, y una vez que dos de los tres responden, el XDK reconstruye tus claves en tu dispositivo. -1. Las claves privadas se **dividen en shares** -2. Los shares los guardan **realms independientes** (servidores separados) -3. **Ningún realm** tiene por sí solo información suficiente para reconstruir las claves -4. La recuperación requiere tu **código de acceso** y la cooperación de **suficientes realms** -5. Los códigos de acceso incorrectos están **limitados por tasa** para ralentizar las conjeturas +**Límites de intentos.** Cada realm permite como máximo **20 intentos incorrectos de código de acceso**. En el vigésimo intento incorrecto, tu fragmento de clave se elimina del realm. Esto se aplica por hardware mediante los HSM y protege contra cualquier ataque de fuerza bruta. ```mermaid flowchart LR - A[Your Private Keys] --> B[Split into Shares] - B --> C[Realm 1
Share A] - B --> D[Realm 2
Share B] - B --> E[Realm 3
Share C] - - subgraph Recovery - F[Your Passcode + Multiple Realms] --> G[Reconstruct Keys] + subgraph Storing + A[Your Private Keys] --> B[Split into Shares] + B --> C[Realm 1
Share A · HSM] + B --> D[Realm 2
Share B · HSM] + B --> E[Realm 3
Share C] end + + subgraph Recovering + F[Your Passcode + 2 of 3 Realms] --> G[Reconstruct Keys] + end + + E ~~~ F ``` -Obtienes capacidad de recuperación (nuevo dispositivo + código de acceso) sin que una sola parte guarde todo el secreto. +El resultado: puedes recuperar tus claves en un dispositivo nuevo solo con tu código de acceso, ningún realm por sí solo contiene el secreto completo, y los realms respaldados por hardware imponen sus límites incluso contra el propio X. -No configuras servidores de copia de seguridad de claves manualmente para el flujo normal. El Chat XDK incluye el cliente de copia de seguridad; la configuración de los realms viene de la X API como el campo **`juicebox_config`** en tu registro de public-key. El almacenamiento inicial del código de acceso y el desbloqueo posterior son llamadas del Chat XDK—consulta [inicializar con claves existentes](/es/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) y [crear y registrar claves](/es/xchat/getting-started#3-create-and-register-keys-first-time-setup) en Primeros pasos. Algunas apps (especialmente servidores y bots) usan un blob de claves exportado en lugar de la copia de seguridad segura de claves; protege ese material como si fuera una contraseña. +No configuras nada de esto a mano. El Chat XDK incluye el cliente de copia de seguridad, y la configuración del realm llega desde el backend de X con tu registro de clave pública. El almacenamiento del código de acceso y el desbloqueo son llamadas del Chat XDK; consulta [initialize with existing keys](/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) y [create and register keys](/xchat/getting-started#3-create-and-register-keys-first-time-setup). Los servidores y bots suelen omitir la copia de seguridad y usan un blob de claves exportado; protégelo como si fuera una contraseña. --- ## Firmas explicadas -Cada mensaje de X Chat incluye una **firma digital** que aporta: - -1. **Autenticidad** — se produjo con la clave privada de firma del remitente -2. **Integridad** — el contenido cifrado no se modificó después de firmarse +La firma de cada mensaje ofrece a los destinatarios dos garantías: -### Cómo funcionan las firmas (conceptualmente) +1. **Autenticidad**: producida por el titular de la clave privada de firma del remitente +2. **Integridad**: el contenido cifrado no se modificó después de firmar -| Acción | Clave utilizada | Resultado | -|:-------|:---------|:-------| -| **Firmar** | Clave privada de firma del remitente | Una firma vinculada a este mensaje cifrado exacto | -| **Verificar** | Clave pública de firma del remitente | Confirma que la firma coincide con el mensaje y la clave | +Si algo en el contenido firmado cambia, la verificación falla. Por supuesto, esta garantía es tan fuerte como el secreto de la clave de firma, por lo que el [almacenamiento de claves](#secure-key-backup-distributed-key-storage) importa tanto. -Si algo en el material firmado cambia, la verificación falla. Solo alguien con la clave privada de firma puede producir una firma válida para esa clave. +**En tu app.** El XDK firma cuando ciframos y verifica cuando desciframos. El rechazo ocurre en ambos extremos: X Chat mismo rechaza eventos que no puede verificar, y el XDK hace lo mismo al recibirlos, **obligatorio por defecto** (deshabilitar esto no se recomienda). Detalles: [Chat XDK](/xchat/xchat-xdk). -### En tu app - -El Chat XDK firma cuando cifras mensajes salientes y verifica cuando descifras los entrantes contra el material de clave pública del remitente (obtenido de las APIs de public-key). La verificación es **obligatoria por defecto**: el SDK rechaza eventos firmados no verificados a menos que desactives explícitamente la comprobación (no recomendado). Los detalles están en la referencia del [Chat XDK](/es/xchat/xchat-xdk). - -Las firmas también cubren el contenido citado. Una respuesta incrusta el mensaje original **firmado** en bruto que cita; cuando el Chat XDK descifra la respuesta, verifica ese original incrustado y compara la cita contra él, reportando el resultado como `reply_preview_validation` (`Valid` / `Invalid`). Un resultado `Invalid` significa que la cita no coincide con el original firmado—trata el material citado como no confiable, aunque la respuesta en sí se verifique por separado—de modo que ningún participante pueda atribuir palabras inventadas a otro. +Las firmas también cubren el contenido citado. Una respuesta incrusta el mensaje original **firmado** en bruto que cita; cuando el Chat XDK descifra la respuesta, verifica ese original incrustado y compara la cita con él, reportando el resultado como `reply_preview_validation` (`Valid` / `Invalid`). Un resultado `Invalid` significa que la cita no coincide con el original firmado—trata el material citado como no confiable, aunque la respuesta en sí se verifique por separado—de modo que ningún participante pueda atribuir palabras inventadas a otro. ### Cambios de estado firmados (firmas de acción) -Los mensajes no son el único material firmado. Cada llamada que cambia el estado de una conversación—añadir o rotar claves de conversación, crear un grupo, añadir miembros—debe llevar una o más **firmas de acción**: el remitente firma un payload que describe exactamente lo que hace el cambio (para un cambio de clave, ese payload incluye la nueva clave de conversación en sí), y la API rechaza la solicitud si las firmas faltan o están mal formadas. +Los mensajes no son lo único que se firma. Todo cambio en una conversación (crear un grupo, agregar miembros, rotar una clave) también debe llevar **firmas de acción**: el remitente firma una carga que describe exactamente qué hace el cambio, y la API rechaza las solicitudes donde estas faltan o están mal formadas. El XDK las produce por ti. -Como el servidor nunca posee la clave de conversación en texto plano, no puede comprobar criptográficamente la firma de un cambio de clave; valida que la descripción firmada y codificada del cambio coincida con la solicitud que recibió. La comprobación **criptográfica** ocurre en los extremos: el Chat XDK de cada destinatario verifica la firma contra la clave pública de firma del remitente cuando descifra el evento de cambio de clave. Los métodos `prepare` del Chat XDK producen estas firmas por ti—las creaciones de grupo y las adiciones de miembros devuelven **dos** (el cambio de clave más la acción del grupo), y ambas deben enviarse. +**Por qué el servidor no puede verificar completamente un cambio de clave.** El servidor nunca tiene la clave de conversación en bruto (esa es la idea), por lo que no puede comprobar una firma sobre material que no puede ver. Verifica lo que puede—que la descripción firmada coincida con la solicitud—y los destinatarios hacen la verificación criptográfica real cuando desenvuelven el cambio de clave. -Las firmas están vinculadas al contenido del evento y son inmutables: un evento cuya firma no se verifica nunca podrá volverse válido más tarde. Consulta [Solución de problemas](/es/xchat/troubleshooting) para saber cómo tratarlos. +Los eventos son inmutables: uno que falle la verificación es permanentemente inválido. Consulta [Solución de problemas](/xchat/troubleshooting). --- ## Propiedades de seguridad -### Contra qué protege X Chat +Esto es contra lo que X Chat protege, y —igual de importante— contra lo que no. + +### Contra lo que X Chat protege -| Amenaza | Protección | -|:-------|:-----------| -| **X lee los cuerpos de los mensajes** | El contenido se cifra antes de enviarse a X | -| **Espías de la red** | Seguridad del transporte más contenido cifrado de extremo a extremo | -| **Manipulación de mensajes** | Las firmas detectan la modificación | -| **Suplantación trivial del remitente** | Las firmas válidas requieren la clave privada de firma del remitente | -| **Robo de claves en un solo servidor (con copia de seguridad segura de claves)** | Los shares se dividen entre realms y están protegidos por código de acceso | +| Amenaza | Protección | Se apoya en | +|:--------|:-----------|:------------| +| **X leyendo los cuerpos de los mensajes** | El contenido se cifra antes de llegar a X | Las claves de conversación nunca salen de los dispositivos de los participantes sin envolver | +| **Espías en la red** | Seguridad de transporte más contenido cifrado de extremo a extremo | TLS estándar, más todo lo anterior | +| **Manipulación de mensajes** | Las firmas detectan cualquier modificación | Verificación de firma en cada evento | +| **Suplantación del remitente** | Una firma válida requiere la clave privada de firma del remitente | Secreto de la clave de firma, más la vinculación de claves que verificaste | +| **Robo de claves desde un servidor de copia de seguridad** | Los fragmentos se dividen entre realms y están protegidos por código de acceso, con un límite estricto de intentos | Ningún realm por sí solo puede reconstruir las claves; los HSM imponen el límite de intentos por hardware | -### Contra qué **no** protege X Chat +### Contra lo que X Chat no protege, y por qué -| Amenaza | Por qué no | -|:-------|:--------| -| **Dispositivo comprometido** | El texto plano y las claves pueden quedar expuestos en un cliente desbloqueado | -| **Metadatos** | X puede saber quién envió mensajes a quién y cuándo—no el texto del mensaje | -| **Confidencialidad hacia adelante** | El compromiso de las claves de identidad puede exponer las claves de conversación que se envolvieron con esas claves | -| **Seguridad post-compromiso** | Rotar las claves no reescribe el historial | +| Limitación | La versión honesta | +|:-----------|:-------------------| +| **Un dispositivo comprometido** | Un cliente desbloqueado contiene texto plano y claves en bruto. Ningún diseño de extremo a extremo sobrevive a un endpoint comprometido. | +| **Metadatos** | X debe saber quién envió un mensaje a quién, y cuándo, para enrutar el texto cifrado. El cifrado oculta el *qué*, no el *quién* ni el *cuándo*. | +| **Sin forward secrecy** | Las claves de conversación se envuelven con claves de identidad de larga duración: un atacante con tu clave privada de identidad puede desenvolver sobres capturados previamente y, con ellos, texto cifrado pasado. | +| **Sin recuperación automática tras compromiso** | La recuperación funciona, pero es deliberada en lugar de automática: expulsar a un atacante rota la clave de conversación, y recuperar un dispositivo comprometido normalmente incluye generar una nueva clave de identidad y nuevas claves de conversación, de modo que incluso las claves robadas no lean nada nuevo. Lo que ninguna rotación puede hacer es reescribir el pasado, o protegerte en la ventana antes de que se atienda el compromiso. | --- ## Glosario | Término | Definición | -|:-----|:-----------| -| **Cifrado simétrico** | La misma clave cifra y descifra (usado para mensajes y streams de multimedia) | -| **Cifrado asimétrico** | Claves diferentes para cifrar y descifrar (usado para intercambiar claves de conversación) | -| **Clave pública** | Se puede compartir con seguridad; se usa para cifrar *a* alguien o verificar sus firmas | -| **Clave privada** | Debe permanecer secreta; se usa para descifrar o firmar | -| **Par de claves** | Una clave pública y una clave privada vinculadas | -| **ECDH / ECIES** | Algoritmos usados al intercambiar claves de conversación mediante claves de identidad | -| **ECDSA** | Algoritmo de firma usado para la autoría de mensajes | -| **P-256** | Curva elíptica usada en X Chat (secp256r1) | -| **Clave de conversación** | Clave simétrica compartida por los participantes de una conversación (versionada en el tiempo) | -| **Compartición de secretos** | Dividir un secreto de forma que se necesiten varias piezas para reconstruirlo | -| **Realm** | Un servidor independiente de copia de seguridad segura de claves que guarda un share de tu material de clave | +|:--------|:-----------| +| **Cifrado simétrico** | La misma clave cifra y descifra (usado para mensajes y multimedia) | +| **Cifrado asimétrico** | Clave pública para cifrar, clave privada para descifrar (usado para entregar claves de conversación) | +| **Clave pública** | Se puede publicar sin riesgo; se usa para cifrar *hacia* alguien o verificar sus firmas | +| **Clave privada** | Debe mantenerse en secreto; se usa para descifrar o firmar | +| **ECDH** | *Acuerdo* de claves: dos partes derivan un secreto compartido a partir de la clave privada de una y la clave pública de la otra | +| **ECIES** | Cifrado híbrido construido sobre ECDH: derivar un secreto compartido, cifrar simétricamente con él. Así se envuelven las claves de conversación | +| **ECDSA** | El algoritmo de firma de curva elíptica usado para mensajes y firmas de acción | +| **P-256** | La curva elíptica (secp256r1) que usan todos los pares de claves de X Chat | +| **Vinculación de claves** | La firma publicada que une la clave de identidad de un usuario con su clave de firma; se verifica antes de envolver cualquier cosa hacia un registro descargado | +| **Clave de conversación** | Clave simétrica compartida por los participantes de una conversación, con versión a lo largo del tiempo | +| **Envoltura** | Cifrar una clave con otra; aquí, una clave de conversación con una clave pública de identidad | +| **Compartición de secretos con umbral** | Dividir un secreto en fragmentos de modo que solo un subconjunto suficiente pueda reconstruirlo; menos del umbral no aprende nada | +| **Juicebox** | El protocolo de código abierto detrás de la copia de seguridad segura de claves: recuperación con umbral protegida por código de acceso con límites estrictos de intentos | +| **HSM** | Hardware security module: hardware resistente a manipulación que contiene el fragmento de un realm y hace cumplir su límite de intentos | +| **Realm** | Un servicio de copia de seguridad segura de claves separado y aislado que contiene un fragmento de tu material de claves | --- ## Próximos pasos - - Implementa claves, envío y recepción paso a paso + + Implementa claves, envía y recibe paso a paso - + Métodos y tipos del SDK de cifrado - + Descripción general del producto y arquitectura - + Cómo se entregan los eventos cifrados diff --git a/ja/xchat/cryptography-primer.mdx b/ja/xchat/cryptography-primer.mdx index f8df4115a..9fbfe5a59 100644 --- a/ja/xchat/cryptography-primer.mdx +++ b/ja/xchat/cryptography-primer.mdx @@ -1,297 +1,261 @@ --- title: 暗号技術入門 sidebarTitle: 暗号技術入門 -description: X Chat のエンドツーエンド暗号化の背後にある ECDH、公開鍵暗号、デジタル署名の概念を実装の詳細抜きで学びます。 -keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "digital signatures", "conversation keys"] +description: "X Chat のエンドツーエンド暗号化の背景にある概念: メッセージがどのように保護されるのか。" +keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "ECIES", "digital signatures", "conversation keys"] --- -import { Button } from '/snippets/button.mdx'; +X Chat はエンドツーエンドで暗号化されています。ユーザーのメッセージは、平文の状態ではそのユーザーのデバイス上にしか存在しません。このページでは、その仕組みを説明します。 -この入門記事では、X Chat の背後にある暗号技術のアイデアを概念レベルで説明します。実装するにあたってこれほどの深さを理解する必要はありません——[Chat XDK](/ja/xchat/xchat-xdk) が暗号化、復号、署名、鍵の保管を代わりに行います——が、この考え方はアプリを設計したり動作をデバッグしたりする際に役立ちます。 - -実装の準備ができたら、フル解説の[はじめに](/ja/xchat/getting-started)と、サイドバーの各ルートに関する [API リファレンス](/x-api/chat/get-chat-conversations)を参照してください。 -**この暗号処理を自分で実装する必要はありません。** Chat XDK が処理します。このページは理解のためのものであり、API のチェックリストではありません。 +**このページは情報提供を目的としたものです。実装にあたってこの知識は必要ありません([Chat XDK](/xchat/xchat-xdk) がここに書かれた全ての処理を代わりに実行します)。** --- ## 全体像 -X Chat は階層的な暗号化システムを採用しており、次のように動作します。 +アカウント作成からメッセージの送受信までのフロー全体を見てみましょう。 -1. **メッセージ**は**会話鍵**で暗号化されます(高速な対称鍵暗号) -2. **会話鍵**は各参加者の**アイデンティティ公開鍵**を使って暗号化されます(非対称鍵交換) -3. **メッセージは署名鍵で署名**されるため、受信者は送信者と改ざんがないことを検証できます + + + ここで Chat XDK は、あなたのデバイス上で 2 組のキーペアを生成します。 -対称鍵暗号は大量のメッセージ通信に効率的です。非対称鍵暗号は主に会話鍵を安全に**配布**するために使われます。 + - **identity キーペア** — シークレットを受け取るためのもの + - **signing キーペア** — 作者であることを証明するためのもの -```mermaid -flowchart TB - subgraph "Message Encryption" - A[Your Message] --> B[Encrypt with
Conversation Key] - B --> C[Encrypted Message] - end - - subgraph "Key Distribution" - D[Conversation Key] --> E[Encrypt with
Recipient's Public Key] - E --> F[Encrypted Key
for Recipient] - end - - subgraph "Authentication" - C --> G[Sign with
Your Private Key] - G --> H[Signature] - end -``` + 秘密鍵側は [secure key backup](#secure-key-backup-distributed-key-storage) に送られます。詳しくは後述しますが、ここで重要なのは、これらはあなたのパスコードによってのみ復元可能であり、X が復元することはできないということです。 -プロダクトのフローでは、X が伝送するのは**暗号文と鍵のエンベロープ**であり、読み取り可能なメッセージ内容や生の会話鍵ではありません。あなたのアプリは暗号処理に Chat XDK を用い、鍵の登録や暗号化ペイロードの送受信に [Chat API](/ja/xchat/introduction)(Python/TypeScript の XDK、または HTTPS 経由)を使います。これらがどのように組み合わさるかは[はじめに](/ja/xchat/getting-started)を参照してください。 + 公開鍵側は、identity 鍵と signing 鍵を結び付ける署名とともに、**public key** API を通じて X バックエンドに公開されます。 +
+ + あなたにメッセージを送るには、送信者は新しい**会話鍵**(メッセージを暗号化する対称鍵)を生成します。 ---- + 送信者は X バックエンドからあなたの公開鍵を取得し、その署名を検証し、あなたの identity 鍵に対して会話鍵を暗号化します。 -## 鍵の種類の解説 + これは公開鍵暗号の重要な特性です。誰でもあなたの公開鍵に対して暗号化できますが、**復号できるのはあなたの秘密鍵だけであり、それを持っているのはあなただけです**。したがって X は暗号化されたコピーを保存・配信することはできますが、それを開くことはできません。(使用されている具体的な方式については [glossary](#glossary) を参照してください。) -X Chat は 3 種類の鍵素材を用い、それぞれに特定の目的があります。 + なぜメッセージを直接あなたの公開鍵で暗号化しないのでしょうか? 速度のためです。公開鍵暗号は対称鍵暗号よりもはるかにコストが高いため、鍵を交換することで、以降のメッセージをより効率的に扱えるようになります。 + + + 誰かがあなたにメッセージを送ると、あなたの identity 公開鍵で暗号化された会話鍵と、その会話鍵で暗号化されたメッセージを受け取ります。 -### 1. アイデンティティ鍵ペア + あなたは identity 秘密鍵を使って会話鍵を復号し(繰り返しますが、この鍵を持っているのはあなただけです)、得られた会話鍵を使ってメッセージを復号します。 -**目的:** ユーザー間で会話鍵を安全にやり取りするため + 会話における鍵は、さまざまな理由で時折ローテーションされます(新しい対称鍵が共有されます)。そのため、参加者が常に正しい鍵を使っていることを確認できるように、各会話鍵にはバージョンが付いています。 + + + 暗号化により、誰でもあなたにメッセージを送ることができ、それを復号できるのはあなただけになります。署名はある意味その反対で、あなた(だけ)がメッセージに署名でき、誰でもその署名を検証できます。実際には、署名には秘密鍵が必要で、検証には公開鍵が使えます。 -| コンポーネント | 説明 | -|:----------|:------------| -| **アイデンティティ公開鍵** | 他者と共有し、会話鍵をあなた宛に暗号化するために使われる | -| **アイデンティティ秘密鍵** | 秘密に保持し、あなた宛に送られた会話鍵を復号するために使われる | + X Chat では、送信者は全員自分のメッセージに署名します。署名は、誰がメッセージに署名したかと、署名された正確なバイト列の両方を証明するため、すべての受信者はこのメッセージが送信者の入力そのものであることを検証できます。ここでも XDK があなたの代わりにこれを処理します。詳細は [Signatures explained](#signatures-explained) で扱います。 + +
-誰かがあなたを会話に追加すると、その相手はあなたのアイデンティティ公開鍵を用いて会話鍵を暗号化します。それを復号できるのはあなたのアイデンティティ秘密鍵だけです。 +--- -公開部分はプラットフォームの **public-key** API を通じて登録・検索されます(API リファレンスの「Encryption keys」を参照)。秘密部分は Chat XDK 内に保持されます(たとえば[セキュアキーバックアップ](#secure-key-backup-distributed-key-storage)や慎重に保護された鍵ブロブとして)。 +## まとめると -### 2. 署名鍵ペア +X Chat は 3 つの標準的な暗号ツールを組み合わせており、それぞれが得意な仕事を 1 つだけ担っています。 -**目的:** メッセージの作者があなたであることを証明するため +1. **会話鍵**はメッセージを暗号化します。対称鍵で、すべてのメッセージやメディア通信に対して十分に高速です。 +2. **identity キーペア**は、他の誰か(X を含む)に見られることなく、各参加者に会話鍵を届けます。 +3. **signing キーペア**は作者であることを証明します。すべてのメッセージには、受信者が検証する署名が付いています。 -| コンポーネント | 説明 | -|:----------|:------------| -| **署名公開鍵** | 他者と共有し、あなたの署名を検証するために使われる | -| **署名秘密鍵** | 秘密に保持し、メッセージへの署名に使われる | +```mermaid +flowchart TB + subgraph "Message Encryption" + A[Your Message] --> B[Encrypt with
Conversation Key] + B --> C[Encrypted Message] + end -メッセージを送信すると、あなたの署名秘密鍵で署名されます。受信者はあなたの署名公開鍵(これも public-key API を通じて公開されます)を用いて検証します。Chat XDK はメッセージを暗号化するのと同時に署名し、送信者の公開鍵素材を渡せば復号時に検証も行えます。 + subgraph "Key Delivery" + D[Conversation Key] --> E[Wrap to Recipient's
Identity Public Key] + E --> F[Encrypted Key Copy
for Recipient] + end -### 3. 会話鍵 + subgraph "Authentication" + C --> G[Sign with Your
Signing Private Key] + G --> H[Signature] + end +``` -**目的:** 特定の会話内でメッセージ(および[メディア](/ja/xchat/media))を暗号化・復号するため +X が転送・保存するのは**暗号文とラップされた鍵**だけで、X 自身がその中身を開くことはできません。XDK が暗号処理を担い、[Chat API](/xchat/introduction) は鍵の登録と暗号化ペイロードの受け渡しを行います([Getting Started](/xchat/getting-started))。 -| プロパティ | 説明 | -|:---------|:------------| -| **対称鍵** | 同じ鍵で暗号化と復号を行う | -| **会話ごと** | 各会話は独自の鍵を持つ | -| **参加者間で共有** | 会話を読めるべきすべての参加者がコピーを持つ | -| **バージョン管理** | 鍵はローテーション可能。アプリは時系列でバージョンを追跡すべき | +登場人物一覧: -会話鍵は会話がセットアップされる時や鍵がローテーションされる時に生成されます。各参加者は自分のアイデンティティ公開鍵で作られた鍵の**暗号化されたコピー**を受け取ります。自分のコピーを一度復号したあと、**生の**会話鍵を保持し、高速なメッセージ(および[メディア](/ja/xchat/media))暗号化に使用します。会話のためにこれらのコピーをセットアップする処理は Chat XDK と会話の **key** エンドポイントの組み合わせで行います——手順は[はじめに](/ja/xchat/getting-started#4-set-up-conversation-keys)で解説しています。 +| 鍵 | 保有者 | 役割 | +|:----|:-------------|:-------------| +| **Identity keypair** | 秘密鍵側: あなただけ。公開鍵側: 公開される | ラップされた会話鍵を受け取る | +| **Signing keypair** | 秘密鍵側: あなただけ。公開鍵側: 公開される | メッセージや状態変更に署名し、他者が検証する | +| **Conversation key** | 1 つの会話のすべての参加者 | メッセージやメディアを暗号化する。バージョン付きでローテーションされる | --- -## 暗号化の仕組み(概念) +## 実例で見てみよう -### メッセージの送信 +Bob と Carol とグループを作成する際に、実際に何が起きるのかを追ってみましょう。 - - あなたは「Hello, how are you?」と入力します。 - - - アプリはこのチャット用の生の会話鍵(セットアップ時、または以前の鍵配布イベントから取得したもの)を、正しい鍵バージョンで使用します。 - - - Chat XDK が会話鍵でメッセージを暗号化します。結果はその鍵なしでは無意味な暗号文となります。 + + XDK は新しいランダムな会話鍵を生成します。この時点では、鍵はあなたのデバイスのメモリ上にしか存在しません。 - - Chat XDK が暗号化されたペイロードにあなたの署名秘密鍵で署名し、まさにこの内容の作者があなたであることを証明します。 + + あなたのアプリは、X バックエンドから Bob と Carol の公開鍵を取得し、それぞれの署名を検証します。署名が正しくない場合は処理を中止します。検証できなかった鍵に対して暗号化してはいけません。 - - アプリは Chat API の **send message** エンドポイントを介して、暗号化ペイロードと署名を X に送信します。X は平文として読めないバイト列を保存・配信します。 + + XDK は会話鍵を 3 回ラップします。Bob の identity 公開鍵、Carol のそれ、そしてあなた自身のもの(あなたの他のデバイスからも読めるように)に対してです。 - - -### メッセージの受信 - - - - アプリは X から暗号文を受信します——[Webhook またはアクティビティストリーム](/ja/xchat/real-time-events)経由、または履歴用に会話の **events** を読み取ることで受信します。 + + XDK は、まさにこの変更を記述するペイロードに署名します。グループ、そのメンバー、ラップされた鍵などです。グループの作成には**2 つ**の [action signature](#signed-state-changes-action-signatures) が必要ですが、XDK があなたの代わりに両方を生成します。 - - キャッシュした生の鍵を使うか、新規または新しくローテーションされた会話の場合は鍵配布(key change)イベントから自分のコピーを復号して取得します。 + + あなたのアプリは、ラップされたコピーと署名を X に POST します。サーバーは自分では開けない 3 つの暗号化された blob を保存します。生の会話鍵があなたのデバイスから出ることは一度もありません! - - Chat XDK が送信者の署名公開鍵(および関連するアイデンティティ束縛)を使って署名を検証するので、誰が送ったか、そして改ざんされていないかがわかります。 - - - Chat XDK が会話鍵で復号します。これで「Hello, how are you?」と読めるようになります。 + + Bob の XDK は、自身の identity 秘密鍵で自分のコピーをアンラップし、鍵の変更があなたから来たものであることを検証し、生の会話鍵を保持します。 -暗号化、送信、受信、復号の実装は[はじめに](/ja/xchat/getting-started)と [Chat XDK](/ja/xchat/xchat-xdk) リファレンスで確認できます。 - ---- - -## 鍵配布の解説 - -エンドツーエンド暗号化の中心的な課題は**鍵配布**です。X(または観察者)に会話鍵を平文で見せることなく、いかにして参加者に配るかという問題です。 - -### 初回の鍵セットアップ - -会話でメッセージのやり取りができるように準備される時: +これが 1 回限りのセットアップです。ここから先、すべてのメッセージは同じ 2 つのフローに従います。 -1. Chat XDK がランダムな会話鍵を生成します -2. Chat XDK が**各参加者のアイデンティティ公開鍵**でその鍵を暗号化します -3. あなたのアプリは X の Chat API を通じてこれらの暗号化コピーを公開します -4. 各参加者は自分のアイデンティティ秘密鍵で**自分の**コピーを復号します(Chat XDK 内で) +**送信。** XDK は現在の会話鍵でメッセージを暗号化し、それに署名します。あなたのアプリは両方を **send message** エンドポイントに POST します。X は自分では読めないバイト列を保存・配信します。 -X が扱うのは**ラップされた**コピーのみで、生の会話鍵ではありません。 +**受信。** 暗号文は [Webhook またはアクティビティストリーム](/xchat/real-time-events)経由、または履歴用に会話**イベント**を読み取ることで届きます。XDK は最初に送信者の署名を検証し、その後、保存されている会話鍵で復号します(鍵がローテーションされていた場合、**key change** イベントが新しいラップされたコピーを届けます)。検証に失敗した場合、メッセージは拒否されます。 -### 鍵変更イベント - -会話鍵がローテーションされると(たとえばメンバーが変更された時)、参加者は各メンバー向けの新しい暗号化コピーを含む **key change** イベントを受け取ります。 - -アプリは次の処理を行うべきです。 - -1. ライブイベントや会話履歴で鍵変更素材に気付く -2. 新しい会話鍵(とバージョン)を復号して保存する -3. 以降の送信で最新のバージョンを使用する - -[はじめに](/ja/xchat/getting-started#6-receive-and-decrypt)と[リアルタイムイベント](/ja/xchat/real-time-events)で、実際にこれらのイベントがどこに現れるかを説明しています。 +実装は [Getting Started](/xchat/getting-started) と [Chat XDK](/xchat/xchat-xdk) リファレンスにあります。 --- -## セキュアキーバックアップ:分散型鍵ストレージ +## Secure key backup: 分散型鍵ストレージ -**秘密の**アイデンティティ鍵と署名鍵は慎重に保管する必要があります。X Chat には**セキュアキーバックアップ**の仕組みが含まれており、単一のサーバーに完全な秘密を渡すことなく、パスコードを使って複数デバイス間で鍵を復元できます。 +先ほど、あなたの秘密鍵は **secure key backup** に保存され、あなたのパスコードによってのみ復元可能だと述べました。これは人々が最も懐疑的に感じる部分なので、その仕組みを見てみましょう。X が読めない状態で、どうやって鍵をバックアップできるのでしょうか? ### 従来の鍵ストレージの問題 -| 手法 | 問題 | +| アプローチ | 問題 | |:---------|:--------| -| デバイスにのみ保存 | デバイスを失う = 鍵を失う = メッセージ履歴へのアクセスを失う | -| 通常のクラウドバックアップに保存 | プロバイダーが鍵素材にアクセスできる可能性がある | -| 長い鍵を暗記 | 高エントロピーな鍵を確実に暗記することは難しい | +| デバイスにのみ保存する | デバイスを失う = 鍵を失う = メッセージ履歴へのアクセスを失う | +| 一般的なクラウドバックアップに保存する | プロバイダが鍵素材にアクセスできる | +| 長い鍵を覚える | 人は高エントロピーなシークレットを暗記できない | -### セキュアキーバックアップによる解決 +### Secure key backup による解決方法 -セキュアキーバックアップは**秘密分散**と**パスコード保護**を組み合わせます。 +X Chat はオープンソースの [**Juicebox**](https://juicebox.xyz) プロトコルを使用しており、これは**しきい値秘密分散**とパスコード保護を組み合わせたものです。プロトコルの完全な仕様はそちらにありますが、簡潔にまとめると次のようになります。 -1. 秘密鍵を**シェアに分割**します -2. シェアは**独立したレルム**(別々のサーバー)に保管されます -3. **単一のレルム**だけでは鍵を再構成するのに十分な情報を持ちません -4. 復元にはあなたの**パスコード**と**十分な数のレルム**の協力が必要です -5. 誤ったパスコード試行は**レート制限**され、総当たり攻撃を遅らせます +**保存(アカウント作成時、1 回のみ)。** XDK はあなたの秘密鍵をシェアに分割し、互いに隔離された 3 つの **realm**(サービス)に分散します。3 つとも X が運用しているため、隔離だけでは大した意味を持ちません。ここでハードウェアが登場します。3 つのうち 2 つの realm は**ハードウェアセキュリティモジュール**(HSM)の内部に置かれています。HSM は耐タンパー性のあるハードウェアで、サーバへのフルアクセスを持つ X の管理者に対してすら、自分のシェアを渡しません。1 つのシェアだけでは何もわからず、復元には 3 つのうち **2 つ**の realm のシェアが必要となるため、あらゆる復元の経路は必ず少なくとも 1 つの HSM を経由します。つまり、鍵に至るソフトウェアだけの経路は存在しません。HSM のソフトウェアと、それをプロビジョニングした**鍵セレモニー**は公に文書化されています。 + +**復元(新しいデバイス)。** あなたはパスコードを入力し、XDK は各 realm に対してあなたがそれを知っていることを証明します。Juicebox プロトコルにより、パスコードがあなたのデバイスから出ることなくこれが可能になります。あなたを検証した各 realm は鍵のシェアを解放し、3 つのうち 2 つが応答した時点で、XDK はあなたのデバイス上で鍵を再構成します。 + +**推測回数の制限。** 各 realm は、パスコードの誤入力を最大 **20 回**まで許容します。20 回目に失敗すると、あなたの鍵のシェアはその realm から削除されます。これは HSM によってハードウェアで強制され、あらゆる総当たり攻撃から保護します。 ```mermaid flowchart LR - A[Your Private Keys] --> B[Split into Shares] - B --> C[Realm 1
Share A] - B --> D[Realm 2
Share B] - B --> E[Realm 3
Share C] - - subgraph Recovery - F[Your Passcode + Multiple Realms] --> G[Reconstruct Keys] + subgraph Storing + A[Your Private Keys] --> B[Split into Shares] + B --> C[Realm 1
Share A · HSM] + B --> D[Realm 2
Share B · HSM] + B --> E[Realm 3
Share C] + end + + subgraph Recovering + F[Your Passcode + 2 of 3 Realms] --> G[Reconstruct Keys] end + + E ~~~ F ``` -これにより、単一の当事者が完全な秘密を保持することなく、復元可能性(新しいデバイス + パスコード)を実現できます。 +その結果、あなたはパスコードだけで新しいデバイスに鍵を復元でき、単一の realm が秘密全体を保持することは決してなく、ハードウェアに支えられた realm は X 自身に対してすらその制限を強制します。 -通常のパスでは、鍵バックアップサーバーを手作業で構成する必要はありません。Chat XDK にはバックアップクライアントが含まれており、レルム構成はあなたの public-key レコードの **`juicebox_config`** フィールドとして X API から取得します。初回のパスコード保存と以降のアンロックは Chat XDK の呼び出しで行います——はじめにの [既存の鍵で初期化する](/ja/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) と [鍵を作成して登録する](/ja/xchat/getting-started#3-create-and-register-keys-first-time-setup) を参照してください。一部のアプリ(特にサーバーやボット)はセキュアキーバックアップではなくエクスポートした鍵ブロブを使用します。その素材はパスワードのように保護してください。 +これらは手動で設定する必要はありません。Chat XDK にはバックアップクライアントが含まれており、realm 設定はあなたの公開鍵レコードとともに X バックエンドから届きます。パスコードの保存とアンロックは Chat XDK の呼び出しです。[initialize with existing keys](/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) および [create and register keys](/xchat/getting-started#3-create-and-register-keys-first-time-setup) を参照してください。サーバやボットではバックアップをスキップして、エクスポートされた鍵 blob を使うことがよくあります。それはパスワードと同じように保護してください。 --- -## 署名の解説 - -すべての X Chat メッセージには**デジタル署名**が含まれ、次の 2 つを支えます。 - -1. **真正性** — 送信者の署名秘密鍵で作成されたこと -2. **完全性** — 暗号化された内容が署名後に改変されていないこと +## 署名の詳細 -### 署名の仕組み(概念) +すべてのメッセージの署名は、受信者に次の 2 つの保証を与えます。 -| 操作 | 使用する鍵 | 結果 | -|:-------|:---------|:-------| -| **署名** | 送信者の署名秘密鍵 | この暗号化メッセージにひもづく署名 | -| **検証** | 送信者の署名公開鍵 | 署名がメッセージおよび鍵と一致することを確認 | +1. **真正性**: 送信者の signing 秘密鍵の保持者によって生成されたものである +2. **完全性**: 暗号化されたコンテンツは署名後に改ざんされていない -署名された素材の一部でも変更されると検証は失敗します。その鍵に対する有効な署名を作成できるのは、署名秘密鍵を持つ者だけです。 +署名対象の内容が少しでも変更されると、検証は失敗します。もちろん、この保証は signing 鍵の秘匿性の強さに依存しており、それが[鍵のストレージ](#secure-key-backup-distributed-key-storage)が非常に重要である理由です。 -### アプリでの動作 +**アプリでは。** XDK は暗号化時に署名し、復号時に検証します。拒否は両端で発生します。X Chat 自体は検証できないイベントを拒否し、XDK も受信時に同様に拒否します。これは**デフォルトで必須**です(無効化は推奨しません)。詳細: [Chat XDK](/xchat/xchat-xdk)。 -Chat XDK は送信メッセージを暗号化する際に署名し、受信メッセージを復号する際に送信者の公開鍵素材(public-key API から取得)に対して検証を行います。検証は**デフォルトで必須**です:SDK は明示的にチェックを無効化しない限り、検証されていない署名付きイベントを拒否します(推奨されません)。詳細は [Chat XDK](/ja/xchat/xchat-xdk) リファレンスにあります。 +署名は引用されたコンテンツもカバーします。返信には、引用対象となる**署名済み**の元メッセージそのものが埋め込まれます。Chat XDK が返信を復号する際、埋め込まれた元メッセージを検証し、引用をそれと比較して、結果を `reply_preview_validation`(`Valid` / `Invalid`)として報告します。`Invalid` という結果は、引用が署名済みの元メッセージと一致していないことを意味します。返信自体は別途検証されているとはいえ、引用された内容は信頼できないものとして扱ってください。これにより、どの参加者も他者に偽の言葉を帰属させることはできなくなります。 -署名は引用された内容もカバーします。返信は引用している生の**署名済み**元メッセージを埋め込みます。Chat XDK が返信を復号する際、埋め込まれた元メッセージを検証し、引用と比較して、結果を `reply_preview_validation`(`Valid` / `Invalid`)として報告します。`Invalid` の結果は、引用が署名済みの元メッセージと一致しないことを意味します——返信自体は別途検証されていますが、引用素材は信頼できないものとして扱ってください——これにより、いかなる参加者も他者に捏造した発言を帰属させることはできません。 +### 署名付き状態変更(action signatures) -### 署名付きの状態変更(アクション署名) +署名されるのはメッセージだけではありません。会話に対するすべての変更(グループ作成、メンバー追加、鍵のローテーション)にも **action signature** を伴わせる必要があります。送信者は、その変更が何を行うのかを正確に記述したペイロードに署名し、API はこれが欠落していたり不正な形式である場合、リクエストを拒否します。XDK があなたの代わりにこれを生成します。 -署名される素材はメッセージだけではありません。会話の状態を変える呼び出し(会話鍵の追加やローテーション、グループの作成、メンバーの追加)はすべて、1 つ以上の**アクション署名**を伴う必要があります。送信者は変更内容を厳密に記述するペイロードに署名し(鍵変更の場合、そのペイロードには新しい会話鍵そのものが含まれます)、署名がない、または不正な形式の場合、API はリクエストを拒否します。 +**サーバが鍵の変更を完全には検証できない理由。** サーバは生の会話鍵を保持しません(それがポイントです)。そのため、サーバは自身に見えない素材に対する署名を検証することはできません。サーバは可能な範囲、つまり署名された記述がリクエストと一致するかどうかを確認し、本当の意味での暗号的な確認は、受信者が鍵の変更をアンラップする際に行います。 -サーバーは平文の会話鍵を保持しないため、鍵変更の署名を暗号学的に検証することはできません。サーバーは変更の署名済みエンコード記述が受信したリクエストと一致することを検証します。**暗号学的**な検証はエッジで行われます:各受信者の Chat XDK が鍵変更イベントを復号する際に、送信者の署名公開鍵に対して署名を検証します。Chat XDK の `prepare` メソッドはこれらの署名を代わりに生成します——グループ作成とメンバー追加は**2 つ**の署名(鍵変更とグループアクション)を返し、両方を送信する必要があります。 - -署名はイベントの内容と結び付いており、不変です:署名が検証されないイベントが後から有効になることはありません。それらの扱いは[トラブルシューティング](/ja/xchat/troubleshooting)を参照してください。 +イベントは不変です。検証に失敗したイベントは永続的に無効です。[Troubleshooting](/xchat/troubleshooting) を参照してください。 --- ## セキュリティ特性 -### X Chat が保護するもの +以下は X Chat が守るもの、そして同じくらい重要な、守らないものです。 + +### X Chat が守るもの -| 脅威 | 保護 | -|:-------|:-----------| -| **X がメッセージ本文を読むこと** | コンテンツは X に送信される前に暗号化される | -| **ネットワーク盗聴者** | トランスポートセキュリティに加えてエンドツーエンド暗号化されたコンテンツ | -| **メッセージの改ざん** | 署名により改変を検出 | -| **単純な送信者なりすまし** | 有効な署名には送信者の署名秘密鍵が必要 | -| **単一サーバーからの鍵の盗難(セキュアキーバックアップ使用時)** | シェアは複数のレルムに分散されパスコードで保護される | +| 脅威 | 保護 | 根拠 | +|:-------|:-----------|:-----------| +| **X がメッセージ本文を読むこと** | コンテンツは X に届く前に暗号化される | 会話鍵はアンラップされた状態で参加者のデバイスから出ることはない | +| **ネットワーク上の盗聴者** | 通信路のセキュリティに加え、エンドツーエンド暗号化されたコンテンツ | 標準の TLS に、上記すべてを加えたもの | +| **メッセージの改ざん** | 署名があらゆる変更を検出する | すべてのイベントに対する署名検証 | +| **送信者のなりすまし** | 有効な署名には送信者の signing 秘密鍵が必要 | signing 鍵の秘匿性と、あなたが検証した鍵バインディング | +| **バックアップサーバからの鍵盗難** | シェアは realm 間で分割され、パスコードで保護され、厳格な推測回数制限がある | 単一の realm では鍵を再構成できない。HSM がハードウェアで推測回数制限を強制する | -### X Chat が保護**しない**もの +### X Chat が守らないもの、およびその理由 -| 脅威 | 理由 | -|:-------|:--------| -| **侵害されたデバイス** | アンロックされたクライアント上では平文や鍵が露出する可能性がある | -| **メタデータ** | X は誰と誰がいつやり取りしたかを知ることができる——ただしメッセージのテキストは知らない | -| **前方秘匿性** | アイデンティティ鍵の侵害により、それらの鍵にラップされた会話鍵が露出する可能性がある | -| **侵害後のセキュリティ** | 鍵をローテーションしても履歴は書き換えられない | +| 制限 | 率直な説明 | +|:-----------|:-------------------| +| **侵害されたデバイス** | ロック解除されたクライアントは平文と生の鍵を保持しています。エンドポイントが侵害された時点で、いかなるエンドツーエンド設計もこれを乗り越えることはできません。 | +| **メタデータ** | X は暗号文をルーティングするために、誰が誰にいつメッセージを送ったかを知らなければなりません。暗号化は「何を」は隠しますが、「誰が」や「いつ」は隠しません。 | +| **前方秘匿性がない** | 会話鍵は長寿命の identity 鍵に対してラップされます。攻撃者があなたの identity 秘密鍵を入手した場合、以前にキャプチャされたエンベロープをアンラップし、それによって過去の暗号文も読めるようになります。 | +| **侵害後の自動的な回復はない** | 回復は可能ですが、自動ではなく意図的なものです。攻撃者を排除するには会話鍵をローテーションし、侵害されたデバイスを回復させる際には通常、新しい identity 鍵と新しい会話鍵を生成するため、盗まれた鍵で新しいものを読むことはできません。ローテーションにできないのは、過去を書き換えることや、侵害が処理される前の期間においてあなたを守ることです。 | --- -## 用語集 +## Glossary | 用語 | 定義 | |:-----|:-----------| -| **対称鍵暗号** | 同じ鍵で暗号化と復号を行う(メッセージやメディアストリームに使用) | -| **非対称鍵暗号** | 暗号化と復号で異なる鍵を使う(会話鍵の交換に使用) | -| **公開鍵** | 共有して安全。誰かに暗号化して送るとき、または署名の検証に使う | -| **秘密鍵** | 秘密に保つ必要がある。復号や署名に使用 | -| **鍵ペア** | 関連付けられた公開鍵と秘密鍵 | -| **ECDH / ECIES** | アイデンティティ鍵を介して会話鍵をやり取りする際に使われるアルゴリズム | -| **ECDSA** | メッセージの作者性に使われる署名アルゴリズム | -| **P-256** | X Chat で使われる楕円曲線(secp256r1) | -| **会話鍵** | 1 つの会話の参加者が共有する対称鍵(時系列でバージョン管理される) | -| **秘密分散** | 秘密を分割し、再構成に複数のピースを必要とすること | -| **レルム** | 鍵素材のシェアを 1 つ保持する独立したセキュアキーバックアップサーバー | +| **Symmetric encryption** | 同じ鍵で暗号化と復号を行う(メッセージやメディアに使用) | +| **Asymmetric encryption** | 公開鍵で暗号化し、秘密鍵で復号する(会話鍵の配布に使用) | +| **Public key** | 公開しても安全。誰かに対して暗号化したり、その署名を検証したりするために使う | +| **Private key** | 秘密に保つ必要がある。復号や署名に使う | +| **ECDH** | 鍵*合意*: 2 者が、一方の秘密鍵と他方の公開鍵から共有シークレットを導出する | +| **ECIES** | ECDH に基づくハイブリッド暗号: 共有シークレットを導出し、その下で対称暗号化する。会話鍵はこの方式でラップされる | +| **ECDSA** | メッセージや action signature に使用される楕円曲線署名アルゴリズム | +| **P-256** | X Chat のすべてのキーペアが使用する楕円曲線(secp256r1) | +| **Key binding** | ユーザーの identity 鍵を signing 鍵に結び付ける公開署名。取得したレコードに対して何かをラップする前に検証される | +| **Conversation key** | 1 つの会話の参加者間で共有される対称鍵。時とともにバージョンが付けられる | +| **Wrapping** | ある鍵を別の鍵で暗号化すること。ここでは、identity 公開鍵で会話鍵を暗号化する | +| **Threshold secret sharing** | シークレットをシェアに分割し、十分な数の部分集合のみが再構成できるようにすること。しきい値未満では何もわからない | +| **Juicebox** | secure key backup の背後にあるオープンソースのプロトコル。厳格な推測回数制限を伴う、パスコード保護されたしきい値回復方式 | +| **HSM** | Hardware security module: realm のシェアを保持し、その推測回数制限を強制する耐タンパー性ハードウェア | +| **Realm** | 鍵素材のシェアを 1 つ保持する、隔離された独立の secure key backup サービス | --- ## 次のステップ - - 鍵、送信、受信をステップバイステップで実装 + + 鍵、送信、受信を段階的に実装する - + 暗号化 SDK のメソッドと型 - - プロダクトの概要とアーキテクチャ - - - 暗号化イベントの配信方法 + + 製品概要とアーキテクチャ + + 暗号化されたイベントがどのように配信されるか + diff --git a/ko/xchat/cryptography-primer.mdx b/ko/xchat/cryptography-primer.mdx index 75686b12b..701b646db 100644 --- a/ko/xchat/cryptography-primer.mdx +++ b/ko/xchat/cryptography-primer.mdx @@ -1,263 +1,223 @@ --- title: 암호화 입문 sidebarTitle: 암호화 입문 -description: 구현 세부 사항 없이 X Chat 종단 간 암호화 이면의 ECDH, 공개 키 암호화, 디지털 서명 개념을 학습합니다. -keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "digital signatures", "conversation keys"] +description: "X Chat 종단 간 암호화의 이면에 있는 개념: 메시지가 어떻게 보호되는지 살펴봅니다." +keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "ECIES", "digital signatures", "conversation keys"] --- -import { Button } from '/snippets/button.mdx'; +X Chat은 종단 간 암호화되어 있습니다. 사용자의 메시지는 평문 형태로는 오직 사용자의 기기에만 존재합니다. 이 페이지는 그 동작 방식을 설명합니다. -이 입문서는 X Chat 이면의 암호화 아이디어를 개념적 수준에서 설명합니다. 앱을 구축하기 위해 이 정도의 깊이가 필요한 것은 아니며—[Chat XDK](/ko/xchat/xchat-xdk)가 암호화, 복호화, 서명, 키 저장을 대신 수행합니다—하지만 이 멘탈 모델은 앱을 설계하거나 동작을 디버깅할 때 도움이 됩니다. - -구현할 준비가 되면 전체 안내를 위해 [시작하기](/ko/xchat/getting-started)를 사용하고, 개별 경로에 대해서는 사이드바의 [API 레퍼런스](/x-api/chat/get-chat-conversations)를 참고하세요. -**이 암호화를 직접 구현하지 않습니다.** Chat XDK가 처리합니다. 이 페이지는 API 체크리스트가 아니라 이해를 위한 것입니다. +**이 페이지는 참고용입니다. 앱을 구축하기 위해 이 지식이 반드시 필요하지는 않습니다([Chat XDK](/xchat/xchat-xdk)가 여기의 모든 작업을 대신 수행합니다).** --- ## 전체 그림 -X Chat은 계층화된 암호화 시스템을 사용합니다: +계정 생성부터 메시지 송수신에 이르는 전체 흐름을 살펴보겠습니다. -1. **메시지**는 **대화 키**로 암호화됩니다(빠른 대칭 암호화). -2. **대화 키**는 각 참여자의 **아이덴티티 공개 키**를 사용해 암호화됩니다(비대칭 키 교환). -3. **메시지는 서명 키**로 **서명**되어, 수신자가 발신자를 확인하고 내용이 변경되지 않았음을 검증할 수 있습니다. + + + 이 단계에서 Chat XDK는 사용자의 기기에서 두 개의 키페어를 생성합니다: -대칭 암호화는 많은 메시지 트래픽에 효율적이며, 비대칭 암호화는 주로 대화 키를 안전하게 **배포**하는 데 사용됩니다. + - 비밀을 수신하기 위한 **아이덴티티 키페어(identity keypair)** + - 작성자임을 증명하기 위한 **서명 키페어(signing keypair)** -```mermaid -flowchart TB - subgraph "Message Encryption" - A[Your Message] --> B[Encrypt with
Conversation Key] - B --> C[Encrypted Message] - end - - subgraph "Key Distribution" - D[Conversation Key] --> E[Encrypt with
Recipient's Public Key] - E --> F[Encrypted Key
for Recipient] - end - - subgraph "Authentication" - C --> G[Sign with
Your Private Key] - G --> H[Signature] - end -``` + 개인 키 부분은 [보안 키 백업](#secure-key-backup-distributed-key-storage)으로 전달되며, 이는 뒤에서 자세히 설명합니다. 여기서 중요한 점은 이 키들이 오직 사용자의 패스코드로만 복구 가능하다는 것입니다. X는 이를 복구할 수 없습니다. -제품 흐름에서 X가 전달하는 것은 **암호문과 키 봉투**이며, 읽을 수 있는 메시지 내용이나 원시 대화 키가 아닙니다. 앱은 암호화를 위해 Chat XDK를 사용하고, 키 등록 및 암호화된 페이로드 송수신을 위해 [Chat API](/ko/xchat/introduction)(Python/TypeScript의 XDK 또는 HTTPS 통해)를 사용합니다. 이 구성 요소들이 어떻게 맞물리는지는 [시작하기](/ko/xchat/getting-started)를 참고하세요. + 공개 키 부분은 아이덴티티 키와 서명 키를 서로 묶는 서명과 함께 **public key** API를 통해 X 백엔드에 게시됩니다. +
+ + 사용자에게 메시지를 보내려면, 발신자는 메시지를 암호화할 대칭 키인 새로운 **대화 키(conversation key)**를 생성합니다. ---- + 발신자는 X 백엔드에서 사용자의 공개 키를 가져와 서명을 검증한 후, 사용자의 아이덴티티 키로 대화 키를 암호화합니다. -## 키 유형 설명 + 이것은 공개 키 암호화의 결정적 특성입니다. 누구나 사용자의 공개 키로 암호화할 수 있지만, **오직 사용자의 개인 키만이 복호화할 수 있으며, 그 키는 사용자만이 보유합니다**. 따라서 X는 암호화된 사본을 저장하고 전달할 수는 있지만 결코 열어볼 수 없습니다. (사용된 정확한 방식은 [용어집](#glossary)을 참고하세요.) -X Chat은 세 가지 종류의 키 자료를 사용하며 각각 특정 목적이 있습니다. + 왜 메시지를 사용자의 공개 키로 직접 암호화하지 않을까요? 속도 때문입니다. 공개 키 암호화는 대칭 키 암호화보다 훨씬 비용이 크므로, 키를 교환하면 이후 메시지들의 효율성이 높아집니다. + + + 누군가 사용자에게 메시지를 보내면, 사용자는 아이덴티티 공개 키로 암호화된 대화 키와, 그 대화 키로 암호화된 메시지들을 받게 됩니다. -### 1. 아이덴티티 키쌍 + 사용자는 아이덴티티 개인 키로 대화 키를 복호화하고(다시 강조하지만, 이 키는 오직 사용자만 보유합니다), 얻어낸 대화 키로 메시지를 복호화합니다. -**목적:** 사용자 간에 대화 키를 안전하게 교환 + 이따금 여러 이유로 대화의 키가 회전됩니다(새로운 대칭 키가 공유됩니다). 따라서 각 대화 키에는 버전이 있어 참여자들이 항상 올바른 키를 사용하고 있음을 확인할 수 있습니다. + + + 암호화는 누구든 사용자에게 메시지를 보낼 수 있고 오직 사용자만 복호화할 수 있게 해줍니다. 서명은 어떤 의미에서 그 반대로, 사용자(그리고 오직 사용자만)가 메시지에 서명할 수 있고, 누구든 그 서명을 검증할 수 있게 해줍니다. 실무적으로 서명에는 개인 키가 필요하며, 검증에는 공개 키를 사용할 수 있습니다. -| 구성 요소 | 설명 | -|:----------|:------------| -| **아이덴티티 공개 키** | 타인과 공유; 대화 키를 *당신에게* 암호화하는 데 사용 | -| **아이덴티티 개인 키** | 비밀로 유지; *당신에게* 보내진 대화 키를 복호화하는 데 사용 | + X Chat에서는 모든 발신자가 자신의 메시지에 서명합니다. 서명은 누가 메시지에 서명했는지와 서명된 정확한 바이트를 모두 증명하므로, 모든 수신자는 이 메시지가 발신자가 입력한 바로 그 메시지임을 검증할 수 있습니다. 다시 말하지만, XDK가 이를 대신 처리합니다. 세부 사항은 [서명 설명](#signatures-explained)에서 다룹니다. + +
-누군가 당신을 대화에 추가할 때, 그들은 당신의 아이덴티티 공개 키로 대화 키를 암호화합니다. 오직 당신의 아이덴티티 개인 키만 이를 복호화할 수 있습니다. +--- -공개 절반은 플랫폼의 **공개 키(public-key)** API를 통해 등록 및 조회됩니다(API 레퍼런스의 Encryption keys 참고). 개인 절반은 Chat XDK 안에 남습니다(예: [보안 키 백업](#secure-key-backup-distributed-key-storage) 또는 신중히 보호된 키 blob을 통해). +## 종합하기 -### 2. 서명 키쌍 +X Chat은 세 가지 표준 암호화 도구를 조합하며, 각 도구는 자신이 잘하는 한 가지 일을 담당합니다: -**목적:** 메시지를 당신이 작성했음을 증명 +1. **대화 키**는 메시지를 암호화합니다. 대칭 방식이며, 모든 메시지 및 미디어 트래픽에 충분히 빠릅니다. +2. **아이덴티티 키페어**는 다른 누구(X 포함)도 볼 수 없도록 각 참가자에게 대화 키를 전달합니다. +3. **서명 키페어**는 작성자를 증명합니다. 모든 메시지는 수신자가 검증하는 서명을 가집니다. -| 구성 요소 | 설명 | -|:----------|:------------| -| **서명 공개 키** | 타인과 공유; 당신의 서명을 검증하는 데 사용 | -| **서명 개인 키** | 비밀로 유지; 메시지에 서명하는 데 사용 | +```mermaid +flowchart TB + subgraph "Message Encryption" + A[Your Message] --> B[Encrypt with
Conversation Key] + B --> C[Encrypted Message] + end -메시지를 보낼 때 서명 개인 키로 서명이 이루어집니다. 수신자는 당신의 서명 공개 키(공개 키 API를 통해 게시된)를 사용하여 검증합니다. Chat XDK는 메시지를 암호화하는 과정의 일부로 서명하고, 발신자의 공개 키 자료를 제공하면 복호화 시 검증도 수행합니다. + subgraph "Key Delivery" + D[Conversation Key] --> E[Wrap to Recipient's
Identity Public Key] + E --> F[Encrypted Key Copy
for Recipient] + end -### 3. 대화 키 + subgraph "Authentication" + C --> G[Sign with Your
Signing Private Key] + G --> H[Signature] + end +``` -**목적:** 특정 대화 내에서 메시지(및 [미디어](/ko/xchat/media))를 암호화하고 복호화 +X는 오직 **암호문과 감싸진 키(wrapped keys)**만 전송하고 저장하며, X 자신이 열 수 있는 것은 없습니다. XDK가 암호화를 수행하고, [Chat API](/xchat/introduction)는 키를 등록하고 암호화된 페이로드를 이동시킵니다([시작하기](/xchat/getting-started)). -| 속성 | 설명 | -|:---------|:------------| -| **대칭** | 동일한 키로 암호화와 복호화 수행 | -| **대화별** | 각 대화는 자체 키를 가짐 | -| **참여자 간 공유** | 대화를 읽어야 하는 모든 참여자가 사본을 보유 | -| **버전 관리** | 키는 순환될 수 있으며, 앱은 시간에 따른 버전을 추적해야 함 | +전체 등장 인물: -대화 키는 대화가 설정되거나 키가 순환될 때 생성됩니다. 각 참여자는 자신의 아이덴티티 공개 키로 만들어진 **암호화된 사본**을 받습니다. 자신의 사본을 한 번 복호화한 후에는 **원시** 대화 키를 보관하고 이를 빠른 메시지(및 [미디어](/ko/xchat/media)) 암호화에 사용합니다. 대화를 위한 이러한 사본 설정은 Chat XDK와 대화 **키** 엔드포인트를 함께 사용하여 수행되며, 자세한 내용은 [시작하기](/ko/xchat/getting-started#4-set-up-conversation-keys)에 있습니다. +| 키 | 누가 보유하는가 | 하는 일 | +|:----|:-------------|:-------------| +| **Identity keypair** | 개인 키 부분: 사용자만. 공개 키 부분: 게시됨 | 감싸진 대화 키를 수신 | +| **Signing keypair** | 개인 키 부분: 사용자만. 공개 키 부분: 게시됨 | 메시지와 상태 변경에 서명. 다른 사람이 검증 | +| **Conversation key** | 한 대화의 모든 참가자 | 메시지와 미디어를 암호화. 버전 관리되며 회전됨 | --- -## 암호화 동작 방식(개념적) +## 실제 사례 -### 메시지 보내기 +Bob과 Carol이 있는 그룹을 생성할 때 실제로 어떤 일이 일어나는지 살펴보겠습니다. - - "안녕, 어떻게 지내?"라고 입력합니다. - - - 앱은 해당 채팅의 원시 대화 키(설정 시 또는 이전 키 배포 이벤트에서 얻은)를 올바른 키 버전으로 사용합니다. - - - Chat XDK가 대화 키로 메시지를 암호화합니다. 결과는 그 키 없이는 쓸모없는 암호문입니다. + + XDK가 새로운 랜덤 대화 키를 생성합니다. 지금까지 이 키는 오직 사용자의 기기 메모리에만 존재합니다. - - Chat XDK가 서명 개인 키로 암호화된 페이로드에 서명하여, 당신이 정확히 이 내용을 작성했음을 증명합니다. + + 앱이 X 백엔드에서 Bob과 Carol의 공개 키를 가져와 각 키의 서명을 검증합니다. 서명이 유효하지 않으면 진행을 중단합니다. 검증할 수 없는 키로는 절대 암호화하지 마세요. - - 앱은 Chat API의 **send message** 엔드포인트를 통해 암호화된 페이로드와 서명을 X로 전송합니다. X는 평문으로는 읽을 수 없는 바이트를 저장하고 전달합니다. - - - -### 메시지 받기 - - - - 앱은 [웹훅 또는 활동 스트림](/ko/xchat/real-time-events)을 통해, 혹은 히스토리를 위해 대화 **events**를 읽어 X로부터 암호문을 받습니다. + + XDK는 대화 키를 세 번 감쌉니다: Bob의 아이덴티티 공개 키로, Carol의 것으로, 그리고 사용자 자신의 것으로(사용자의 다른 기기에서도 읽을 수 있도록). - - 캐시된 원시 키를 사용하거나, 새롭거나 순환된 경우 키 배포(키 변경) 이벤트에서 자신의 사본을 복호화하여 얻습니다. + + XDK는 정확히 이 변경 사항—그룹, 그 멤버, 감싸진 키—을 기술하는 페이로드에 서명합니다. 그룹 생성은 **두 개**의 [액션 서명](#signed-state-changes-action-signatures)이 필요하며, XDK가 둘 다 생성해 줍니다. - - Chat XDK가 발신자의 서명 공개 키(및 관련 아이덴티티 바인딩)를 사용해 서명을 확인하므로, 누가 보냈고 변조되지 않았음을 알 수 있습니다. + + 앱이 감싸진 사본과 서명을 X에 POST합니다. 서버는 자신이 열 수 없는 세 개의 암호화된 blob을 저장합니다. 이 과정 어디에서도 원시 대화 키가 사용자의 기기를 떠난 적이 없습니다! - - Chat XDK가 대화 키로 복호화합니다. 이제 "안녕, 어떻게 지내?"를 읽을 수 있습니다. + + Bob의 XDK가 자신의 아이덴티티 개인 키로 자신의 사본을 풀고, 키 변경이 사용자로부터 온 것임을 검증한 뒤, 원시 대화 키를 보유합니다. -암호화, 전송, 수신, 복호화의 구현은 [시작하기](/ko/xchat/getting-started)와 [Chat XDK](/ko/xchat/xchat-xdk) 레퍼런스에 있습니다. - ---- - -## 키 배포 설명 - -종단 간 암호화의 핵심 과제는 **키 배포**입니다: 참여자들이 X(또는 관찰자)가 평문으로 그 키를 볼 수 **없이** 어떻게 대화 키를 얻는가입니다. - -### 초기 키 설정 +이것은 일회성 설정입니다. 여기서부터 모든 메시지는 동일한 두 흐름을 따릅니다: -메시징을 위해 대화가 준비될 때: +**보내기.** XDK가 현재 대화 키로 메시지를 암호화하고 서명하며, 앱이 **send message** 엔드포인트에 둘 다 POST합니다. X는 자신이 읽을 수 없는 바이트를 저장하고 전달합니다. -1. Chat XDK가 임의의 대화 키를 생성합니다 -2. Chat XDK가 그 키를 **각 참여자의 아이덴티티 공개 키**로 암호화합니다 -3. 앱이 그 암호화된 사본들을 X의 Chat API를 통해 게시합니다 -4. 각 참여자는 자신의 아이덴티티 개인 키로 **자신의** 사본을 (Chat XDK 안에서) 복호화합니다 +**받기.** 암호문은 [웹훅 또는 활동 스트림](/xchat/real-time-events)을 통해, 혹은 이력 조회를 위한 대화 **events**를 통해 도착합니다. XDK는 먼저 발신자의 서명을 검증한 뒤, 저장된 대화 키로 복호화합니다(키가 회전된 경우, **key change** 이벤트가 새로 감싸진 사본을 전달합니다). 검증에 실패하면 메시지는 거부됩니다. -X는 오직 **감싼(wrapped)** 사본만 다루며, 원시 대화 키는 다루지 않습니다. - -### 키 변경 이벤트 - -대화 키가 순환될 때(예: 멤버십이 변경될 때) 참여자들은 각 멤버에 대한 새 암호화된 사본이 포함된 **키 변경** 이벤트를 받습니다. - -앱은 다음을 수행해야 합니다: - -1. 실시간 이벤트 또는 대화 히스토리에서 키 변경 자료를 감지 -2. 새 대화 키(및 버전)를 복호화하고 저장 -3. 이후 전송에는 최신 버전 사용 - -[시작하기](/ko/xchat/getting-started#6-receive-and-decrypt)와 [실시간 이벤트](/ko/xchat/real-time-events)에서 이러한 이벤트가 실제로 어디에 나타나는지를 설명합니다. +구현 내용은 [시작하기](/xchat/getting-started)와 [Chat XDK](/xchat/xchat-xdk) 레퍼런스에 있습니다. --- -## 보안 키 백업: 분산 키 저장소 +## 보안 키 백업: 분산 키 저장 -**개인** 아이덴티티 및 서명 키는 신중하게 저장되어야 합니다. X Chat에는 어떤 단일 서버에도 전체 비밀을 주지 않고, 기기 간 패스코드로 키를 복구할 수 있도록 하는 **보안 키 백업** 시스템이 포함되어 있습니다. +앞서 사용자의 개인 키는 **보안 키 백업**에 저장되며 오직 패스코드로만 복구할 수 있다고 말했습니다. 이제 그 동작 방식을 살펴보겠습니다. 이것이 사람들이 가장 회의적으로 여기는 부분이기 때문입니다. X가 읽을 수 없으면서 어떻게 키를 백업할 수 있을까요? -### 전통적인 키 저장소의 문제점 +### 전통적 키 저장 방식의 문제점 | 접근 방식 | 문제점 | |:---------|:--------| -| 기기에만 저장 | 기기를 잃으면 키를 잃고 = 메시지 기록에 접근 불가 | +| 기기에만 저장 | 기기를 잃으면 = 키를 잃고 = 메시지 이력에 대한 접근을 잃음 | | 일반 클라우드 백업에 저장 | 제공자가 키 자료에 접근할 수 있음 | -| 긴 키를 기억 | 사람은 고엔트로피 키를 안정적으로 기억할 수 없음 | +| 긴 키를 암기 | 사람은 엔트로피가 높은 비밀을 외울 수 없음 | + +### 보안 키 백업이 이를 해결하는 방식 + +X Chat은 오픈소스 [**Juicebox**](https://juicebox.xyz) 프로토콜을 사용하며, 이는 **임계 비밀 공유(threshold secret sharing)**와 패스코드 보호를 결합합니다. 전체 프로토콜은 해당 사이트에 명세가 있으며, 짧게 요약하면 다음과 같습니다: -### 보안 키 백업이 해결하는 방법 +**저장(계정 생성 시 한 번).** XDK가 사용자의 개인 키를 여러 조각(share)으로 나누고, 이를 서로 격리된 별개의 서비스인 세 개의 **realm**에 분산 저장합니다. 세 realm 모두 X가 운영하므로 격리만으로는 큰 의미가 없을 것입니다. 여기서 하드웨어가 역할을 합니다. 세 realm 중 두 개는 **하드웨어 보안 모듈(HSM)** 내부에서 동작하며, 이는 자신의 조각을 그 누구에게도—심지어 서버 접근 권한을 가진 X 관리자에게도—내놓지 않는 변조 방지 하드웨어입니다. 조각 하나만으로는 아무것도 드러나지 않으며, 복구에는 세 realm 중 **두 개**의 조각이 필요하므로, 가능한 모든 복구는 최소한 하나의 HSM을 거치게 됩니다. 즉, 사용자의 키에 도달하는 소프트웨어만의 경로는 존재하지 않습니다. HSM 소프트웨어와 이를 프로비저닝한 **키 세리머니(key ceremony)**는 공개 문서화되어 있습니다. -보안 키 백업은 **비밀 공유(secret sharing)**와 **패스코드 보호**를 결합합니다: +**복구(새 기기).** 사용자가 패스코드를 입력하면, XDK가 각 realm에 그것을 안다는 것을 증명합니다. Juicebox 프로토콜은 패스코드가 기기를 떠나지 않고도 이것이 가능하게 합니다. 사용자를 검증한 각 realm이 자신의 키 조각을 내놓고, 세 realm 중 두 개가 응답하면 XDK가 사용자의 기기에서 키를 다시 조립합니다. -1. 개인 키가 **여러 조각(share)로 분할**됩니다 -2. 조각들은 **독립된 realm**(별개 서버)이 보관합니다 -3. **어떤 단일 realm**도 단독으로 키를 재구성하기에 충분한 정보를 갖지 않습니다 -4. 복구는 **패스코드**와 **충분한 수의 realm** 협조가 필요합니다 -5. 잘못된 패스코드는 추측을 지연시키기 위해 **속도 제한**됩니다 +**추측 제한.** 각 realm은 최대 **20회의 잘못된 패스코드 시도**를 허용합니다. 20번째 잘못된 시도 시, 사용자의 키 조각이 해당 realm에서 삭제됩니다. 이는 HSM에 의해 하드웨어로 강제되며, 모든 무차별 대입 공격을 막아줍니다. ```mermaid flowchart LR - A[Your Private Keys] --> B[Split into Shares] - B --> C[Realm 1
Share A] - B --> D[Realm 2
Share B] - B --> E[Realm 3
Share C] - - subgraph Recovery - F[Your Passcode + Multiple Realms] --> G[Reconstruct Keys] + subgraph Storing + A[Your Private Keys] --> B[Split into Shares] + B --> C[Realm 1
Share A · HSM] + B --> D[Realm 2
Share B · HSM] + B --> E[Realm 3
Share C] end + + subgraph Recovering + F[Your Passcode + 2 of 3 Realms] --> G[Reconstruct Keys] + end + + E ~~~ F ``` -단일 당사자가 전체 비밀을 보유하지 않으면서도 복구 가능성(새 기기 + 패스코드)을 얻을 수 있습니다. +결과적으로: 사용자는 패스코드만으로 새 기기에서 자신의 키를 복구할 수 있고, 어떤 단일 realm도 전체 비밀을 보유하지 않으며, 하드웨어 기반 realm은 X 자신에 대해서도 그 제한을 강제합니다. -일반 경로에서는 키 백업 서버를 손수 구성하지 않습니다. Chat XDK에 백업 클라이언트가 포함되어 있으며, realm 구성은 공개 키 레코드의 **`juicebox_config`** 필드로 X API에서 제공됩니다. 최초 패스코드 저장 및 이후 잠금 해제는 Chat XDK 호출입니다—시작하기의 [기존 키로 초기화](/ko/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) 및 [키 생성 및 등록](/ko/xchat/getting-started#3-create-and-register-keys-first-time-setup)을 참고하세요. 일부 앱(특히 서버와 봇)은 보안 키 백업 대신 내보낸 키 blob을 사용합니다. 그 자료는 비밀번호처럼 보호하세요. +이 중 어떤 것도 사용자가 직접 구성할 필요가 없습니다. Chat XDK가 백업 클라이언트를 포함하고 있으며, realm 구성은 사용자의 공개 키 레코드와 함께 X 백엔드에서 전달됩니다. 패스코드 저장 및 잠금 해제는 Chat XDK 호출입니다. [기존 키로 초기화하기](/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys)와 [키 생성 및 등록](/xchat/getting-started#3-create-and-register-keys-first-time-setup)을 참고하세요. 서버와 봇은 종종 백업을 건너뛰고 대신 내보낸 키 blob을 사용합니다. 이를 비밀번호처럼 보호하세요. --- ## 서명 설명 -모든 X Chat 메시지에는 다음을 지원하는 **디지털 서명**이 포함됩니다: - -1. **진위성** — 발신자의 서명 개인 키로 생성되었음 -2. **무결성** — 서명 후 암호화된 내용이 수정되지 않았음 +모든 메시지의 서명은 수신자에게 두 가지 보장을 제공합니다: -### 서명 동작 방식(개념적) +1. **진위성(Authenticity)**: 발신자의 서명 개인 키 보유자가 생성한 것임 +2. **무결성(Integrity)**: 서명 이후 암호화된 내용이 수정되지 않았음 -| 동작 | 사용된 키 | 결과 | -|:-------|:---------|:-------| -| **서명** | 발신자의 서명 개인 키 | 정확히 이 암호화된 메시지에 결합된 서명 | -| **검증** | 발신자의 서명 공개 키 | 서명이 메시지 및 키와 일치함을 확인 | +서명된 내용 중 어떤 것이 변경되면 검증은 실패합니다. 물론 이 보장은 서명 키의 비밀성 만큼만 강력하며, 그렇기에 [키 저장](#secure-key-backup-distributed-key-storage)이 그토록 중요합니다. -서명 대상 자료 중 하나라도 변경되면 검증에 실패합니다. 오직 서명 개인 키를 가진 사람만이 해당 키에 대한 유효한 서명을 생성할 수 있습니다. +**앱에서.** XDK는 암호화할 때 서명하고 복호화할 때 검증합니다. 거부는 양쪽 끝에서 일어납니다. X Chat 자체가 검증할 수 없는 이벤트를 거부하고, 수신 시 XDK도 동일하게 처리하며, 이는 **기본적으로 필수**입니다(이를 비활성화하는 것은 권장하지 않습니다). 세부 사항은 [Chat XDK](/xchat/xchat-xdk)에 있습니다. -### 앱에서 - -Chat XDK는 발신 메시지를 암호화할 때 서명하며, 수신 메시지를 복호화할 때 (공개 키 API에서 얻은) 발신자의 공개 키 자료에 대해 검증합니다. 검증은 기본적으로 **필수**입니다: SDK는 명시적으로 검사를 비활성화하지 않는 한(권장하지 않음) 검증되지 않은 서명 이벤트를 거부합니다. 자세한 내용은 [Chat XDK](/ko/xchat/xchat-xdk) 레퍼런스에 있습니다. - -서명은 인용된 내용에도 적용됩니다. 답장은 인용하는 원본 **서명된** 메시지를 원시 형태로 포함합니다. Chat XDK가 답장을 복호화할 때 그 포함된 원본을 검증하고 인용을 이에 대조하여 결과를 `reply_preview_validation`(`Valid` / `Invalid`)으로 보고합니다. `Invalid` 결과는 인용이 서명된 원본과 일치하지 않는다는 의미입니다—답장 자체는 별도로 검증되지만, 인용된 자료는 신뢰할 수 없는 것으로 취급하세요—따라서 어떤 참여자도 다른 사람에게 조작된 말을 귀속시킬 수 없습니다. +서명은 인용된 콘텐츠도 포함합니다. 답장은 자신이 인용하는 원본 **서명된** 메시지를 원시 형태로 임베드합니다. Chat XDK가 답장을 복호화할 때, 임베드된 원본을 검증하고 인용을 그것과 비교하여, 그 결과를 `reply_preview_validation`(`Valid` / `Invalid`)로 보고합니다. `Invalid` 결과는 인용이 서명된 원본과 일치하지 않음을 의미합니다. 답장 자체는 별도로 검증되지만 인용된 자료는 신뢰할 수 없는 것으로 취급하세요. 이로써 어떤 참가자도 다른 사람에게 지어낸 말을 귀속시킬 수 없습니다. ### 서명된 상태 변경(액션 서명) -메시지만이 서명 대상은 아닙니다. 대화 상태를 변경하는 모든 호출—대화 키 추가 또는 순환, 그룹 생성, 멤버 추가—은 하나 이상의 **액션 서명(action signature)**을 포함해야 합니다: 발신자는 변경 사항이 정확히 무엇을 하는지를 기술하는 페이로드에 서명하며(키 변경의 경우 그 페이로드에는 새로운 대화 키 자체가 포함됨), 서명이 없거나 잘못된 형식이면 API는 요청을 거부합니다. +서명되는 것은 메시지만이 아닙니다. 대화의 모든 변경(그룹 생성, 멤버 추가, 키 회전)도 **액션 서명(action signatures)**을 포함해야 합니다. 발신자는 그 변경이 정확히 무엇을 하는지 기술하는 페이로드에 서명하며, API는 이 서명이 누락되거나 형식이 잘못된 요청을 거부합니다. XDK가 이를 대신 생성해 줍니다. -서버는 평문 대화 키를 결코 보관하지 않으므로 키 변경의 서명을 암호학적으로 검사할 수 없습니다. 서버는 서명된, 인코딩된 변경 설명이 수신한 요청과 일치하는지를 검증합니다. **암호학적** 검사는 경계에서 이루어집니다: 각 수신자의 Chat XDK가 키 변경 이벤트를 복호화할 때 발신자의 서명 공개 키에 대해 서명을 검증합니다. Chat XDK의 `prepare` 메서드가 이러한 서명을 생성해 줍니다—그룹 생성과 멤버 추가는 **두 개**를 반환하며(키 변경과 그룹 액션), 둘 모두를 전송해야 합니다. +**서버가 키 변경을 완전히 검증할 수 없는 이유.** 서버는 원시 대화 키를 결코 보유하지 않으므로(그것이 핵심입니다), 자신이 볼 수 없는 자료에 대한 서명을 확인할 수 없습니다. 서버는 확인할 수 있는 것—서명된 설명이 요청과 일치하는지—을 확인하며, 수신자가 키 변경을 풀 때 실제 암호학적 확인을 수행합니다. -서명은 이벤트 내용에 결합되어 있으며 불변입니다: 서명이 검증되지 않는 이벤트는 결코 나중에 유효해질 수 없습니다. 이를 어떻게 다룰지는 [문제 해결](/ko/xchat/troubleshooting)을 참고하세요. +이벤트는 불변입니다. 검증에 실패한 이벤트는 영구적으로 무효입니다. [문제 해결](/xchat/troubleshooting)을 참고하세요. --- -## 보안 속성 +## 보안 특성 + +X Chat이 무엇에 대해 보호하는지, 그리고 그만큼 중요한, 무엇에 대해 보호하지 않는지 살펴봅니다. -### X Chat이 방어하는 위협 +### X Chat이 보호하는 것 -| 위협 | 보호 | -|:-------|:-----------| -| **X가 메시지 본문을 읽음** | 내용은 X로 전송되기 전에 암호화됨 | -| **네트워크 도청자** | 전송 계층 보안과 종단 간 암호화된 내용 | -| **메시지 변조** | 서명이 수정을 감지 | -| **간단한 발신자 위장** | 유효한 서명은 발신자의 서명 개인 키가 필요 | -| **단일 서버 키 도난(보안 키 백업 사용 시)** | 조각들이 realm 간에 분할되고 패스코드로 보호 | +| 위협 | 보호 | 근거 | +|:-------|:-----------|:-----------| +| **X가 메시지 본문을 읽는 것** | 내용은 X에 도달하기 전에 암호화됨 | 대화 키는 참가자의 기기를 감싸지지 않은 상태로 떠나지 않음 | +| **네트워크 도청자** | 전송 계층 보안과 종단 간 암호화된 내용 | 표준 TLS와 위의 모든 것 | +| **메시지 변조** | 서명이 모든 수정을 감지함 | 모든 이벤트에 대한 서명 검증 | +| **발신자 위장** | 유효한 서명에는 발신자의 서명 개인 키가 필요함 | 서명 키의 비밀성과 사용자가 검증한 키 바인딩 | +| **백업 서버로부터의 키 도난** | 조각이 realm에 분산 저장되고 패스코드로 게이팅되며, 강한 추측 제한이 있음 | 어떤 단일 realm도 키를 재구성할 수 없음. HSM이 추측 제한을 하드웨어로 강제함 | -### X Chat이 **방어하지 않는** 위협 +### X Chat이 보호하지 않는 것, 그리고 그 이유 -| 위협 | 이유 | -|:-------|:--------| -| **손상된 기기** | 잠금 해제된 클라이언트에서 평문과 키가 노출될 수 있음 | -| **메타데이터** | X는 누가 누구에게 언제 메시지를 보냈는지 알 수 있음—메시지 텍스트는 아님 | -| **전방향 비밀성(forward secrecy)** | 아이덴티티 키가 손상되면 그 키로 감싸진 대화 키가 노출될 수 있음 | -| **포스트-컴프로마이즈 보안** | 키 순환은 히스토리를 다시 쓰지 않음 | +| 한계 | 정직한 설명 | +|:-----------|:-------------------| +| **손상된 기기** | 잠금 해제된 클라이언트는 평문과 원시 키를 보유합니다. 어떤 종단 간 설계도 손상된 엔드포인트에서는 살아남지 못합니다. | +| **메타데이터** | X는 암호문을 라우팅하기 위해 누가 누구에게 언제 메시지를 보냈는지 알아야 합니다. 암호화는 *무엇을*은 숨기지만, *누가* 또는 *언제*는 숨기지 못합니다. | +| **전방 비밀성(forward secrecy) 없음** | 대화 키는 수명이 긴 아이덴티티 키로 감싸집니다. 사용자의 아이덴티티 개인 키를 가진 공격자는 이전에 가로챈 봉투를 풀 수 있고, 그것으로 과거 암호문도 풀 수 있습니다. | +| **자동 사후 손상 회복 없음** | 회복은 가능하지만 자동이 아니라 의도적으로 이루어집니다. 공격자를 제거하면 대화 키가 회전되고, 손상된 기기를 복구할 때는 보통 새로운 아이덴티티 키와 새 대화 키를 생성하는 과정이 포함되므로, 훔친 키로도 새로운 것을 읽을 수 없습니다. 어떤 회전도 할 수 없는 것은 과거를 다시 쓰는 것이며, 손상이 처리되기 전 기간에는 사용자를 보호할 수 없습니다. | --- @@ -265,33 +225,37 @@ Chat XDK는 발신 메시지를 암호화할 때 서명하며, 수신 메시지 | 용어 | 정의 | |:-----|:-----------| -| **대칭 암호화** | 동일 키로 암호화와 복호화(메시지와 미디어 스트림에 사용) | -| **비대칭 암호화** | 암호화와 복호화에 서로 다른 키(대화 키 교환에 사용) | -| **공개 키** | 공유해도 안전; 누군가에게 *암호화*하거나 그들의 서명을 검증할 때 사용 | -| **개인 키** | 비밀로 유지해야 함; 복호화 또는 서명에 사용 | -| **키쌍** | 연결된 공개 키와 개인 키 | -| **ECDH / ECIES** | 아이덴티티 키를 통해 대화 키를 교환할 때 사용되는 알고리즘 | -| **ECDSA** | 메시지 작성 증명에 사용되는 서명 알고리즘 | -| **P-256** | X Chat에서 사용되는 타원 곡선(secp256r1) | -| **대화 키** | 하나의 대화에서 참여자들이 공유하는 대칭 키(시간에 따라 버전 관리됨) | -| **비밀 공유** | 재구성을 위해 여러 조각이 필요하도록 비밀을 분할 | -| **Realm** | 키 자료의 한 조각을 보관하는 독립된 보안 키 백업 서버 | +| **Symmetric encryption** | 동일한 키로 암호화하고 복호화(메시지와 미디어에 사용) | +| **Asymmetric encryption** | 공개 키로 암호화, 개인 키로 복호화(대화 키 전달에 사용) | +| **Public key** | 게시해도 안전. 누군가에게 *암호화하거나* 그들의 서명을 검증하는 데 사용 | +| **Private key** | 비밀로 유지되어야 함. 복호화 또는 서명에 사용 | +| **ECDH** | 키 *합의*: 두 당사자가 한쪽의 개인 키와 다른 쪽의 공개 키로부터 공유 비밀을 유도 | +| **ECIES** | ECDH 위에 구축된 하이브리드 암호화: 공유 비밀을 유도한 뒤 그 아래에서 대칭적으로 암호화. 대화 키를 감싸는 방식 | +| **ECDSA** | 메시지와 액션 서명에 사용되는 타원 곡선 서명 알고리즘 | +| **P-256** | 모든 X Chat 키페어가 사용하는 타원 곡선(secp256r1) | +| **Key binding** | 사용자의 아이덴티티 키를 서명 키에 묶는 게시된 서명. 조회한 레코드에 무언가를 감싸기 전에 검증됨 | +| **Conversation key** | 한 대화의 참가자들이 공유하는 대칭 키. 시간이 지남에 따라 버전이 관리됨 | +| **Wrapping** | 하나의 키를 다른 키 아래에서 암호화하는 것. 여기서는 아이덴티티 공개 키 아래에서 대화 키를 감싸는 것 | +| **Threshold secret sharing** | 비밀을 조각으로 나누어 충분한 부분집합만이 재구성할 수 있게 하는 것. 임계값 미만은 아무것도 알지 못함 | +| **Juicebox** | 보안 키 백업 뒤에 있는 오픈소스 프로토콜: 패스코드로 게이팅되고 강한 추측 제한을 가진 임계값 복구 | +| **HSM** | 하드웨어 보안 모듈: realm의 조각을 보유하고 추측 제한을 강제하는 변조 방지 하드웨어 | +| **Realm** | 사용자의 키 자료 조각 하나를 보유하는, 분리되고 격리된 보안 키 백업 서비스 | --- ## 다음 단계 - - 키, 전송, 수신을 단계별로 구현하기 + + 키를 구현하고, 단계별로 메시지를 보내고 받기 - + 암호화 SDK 메서드와 타입 - + 제품 개요 및 아키텍처 - + 암호화된 이벤트가 전달되는 방식 diff --git a/pt/xchat/cryptography-primer.mdx b/pt/xchat/cryptography-primer.mdx index af916ed61..63d9fe2a1 100644 --- a/pt/xchat/cryptography-primer.mdx +++ b/pt/xchat/cryptography-primer.mdx @@ -1,297 +1,261 @@ --- title: Introdução à Criptografia sidebarTitle: Introdução à Criptografia -description: Conheça os conceitos de ECDH, criptografia de chave pública e assinaturas digitais por trás da criptografia de ponta a ponta do X Chat, sem detalhes de implementação. -keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "digital signatures", "conversation keys"] +description: "Os conceitos por trás da criptografia de ponta a ponta do X Chat: como suas mensagens são protegidas." +keywords: ["X Chat cryptography", "E2EE primer", "encryption basics", "public key encryption", "ECDH", "ECIES", "digital signatures", "conversation keys"] --- -import { Button } from '/snippets/button.mdx'; +O X Chat é criptografado de ponta a ponta: as mensagens de um usuário, em texto simples, existem apenas em seus dispositivos. Esta página explica como isso funciona. -Esta introdução explica as ideias criptográficas por trás do X Chat em nível conceitual. Você não precisa desse aprofundamento para desenvolver — o [Chat XDK](/pt/xchat/xchat-xdk) faz a criptografia, descriptografia, assinatura e o armazenamento de chaves por você — mas o modelo mental ajuda quando você projeta seu app ou depura o comportamento. - -Quando estiver pronto para implementar, consulte [Primeiros passos](/pt/xchat/getting-started) para um passo a passo completo e a [referência da API](/x-api/chat/get-chat-conversations) na barra lateral para rotas individuais. -**Você não implementa esta criptografia por conta própria.** O Chat XDK cuida disso. Esta página é para entendimento, não uma lista de verificação de API. +**Esta página é informativa. Você não precisa desse conhecimento para desenvolver (o [Chat XDK](/xchat/xchat-xdk) executa cada operação aqui descrita para você).** --- ## O panorama geral -O X Chat usa um sistema de criptografia em camadas onde: +Vamos examinar todo o fluxo, desde a criação da conta até o envio e recebimento de mensagens. -1. As **mensagens** são criptografadas com uma **chave da conversa** (criptografia simétrica rápida) -2. As **chaves da conversa** são criptografadas para cada participante usando sua **chave pública de identidade** (troca de chaves assimétrica) -3. As **mensagens são assinadas** com a **chave de assinatura**, para que os destinatários possam verificar quem as enviou e que nada foi alterado + + + Aqui o Chat XDK gera dois pares de chaves no seu dispositivo: -A criptografia simétrica é eficiente para grandes volumes de tráfego de mensagens; a criptografia assimétrica é usada principalmente para **distribuir** com segurança as chaves de conversa. + - um **par de chaves de identidade**, para receber segredos + - um **par de chaves de assinatura**, para provar autoria -```mermaid -flowchart TB - subgraph "Message Encryption" - A[Your Message] --> B[Encrypt with
Conversation Key] - B --> C[Encrypted Message] - end - - subgraph "Key Distribution" - D[Conversation Key] --> E[Encrypt with
Recipient's Public Key] - E --> F[Encrypted Key
for Recipient] - end - - subgraph "Authentication" - C --> G[Sign with
Your Private Key] - G --> H[Signature] - end -``` + As metades privadas vão para o [backup seguro de chaves](#secure-key-backup-distributed-key-storage), que detalhamos mais adiante. O importante aqui é que elas só podem ser recuperadas com o seu código de acesso; o X não consegue recuperá-las. -No fluxo do produto, o X transporta **texto cifrado e envelopes de chave** — não conteúdo de mensagem legível nem a chave da conversa em bruto. Seu app usa o Chat XDK para criptografia e a [Chat API](/pt/xchat/introduction) (via XDK em Python/TypeScript ou HTTPS) para registrar chaves e enviar ou receber esses payloads criptografados. Consulte [Primeiros passos](/pt/xchat/getting-started) para entender como essas peças se encaixam. + As metades públicas são publicadas no backend do X através da API de **chave pública**, com uma assinatura amarrando as chaves de identidade e de assinatura entre si. +
+ + Para enviar uma mensagem a você, um remetente gera uma nova **chave de conversa**, uma chave simétrica que criptografará as mensagens. ---- + Ele busca sua chave pública no backend do X, verifica a assinatura sobre ela e criptografa a chave de conversa para a sua chave de identidade. -## Tipos de chave explicados + Esta é uma propriedade crucial da criptografia de chave pública: qualquer pessoa pode criptografar para sua chave pública; **apenas sua chave privada pode descriptografar, e somente você a detém**. Portanto, o X pode armazenar e entregar a cópia criptografada, mas nunca abri-la. (Para os esquemas exatos utilizados, veja o [glossário](#glossary).) -O X Chat usa três tipos de material de chave, cada um com um propósito específico. + Por que não simplesmente criptografar as mensagens diretamente para sua chave pública? Velocidade: a criptografia de chave pública é muito mais custosa do que a criptografia de chave simétrica, então trocar uma chave permite melhor eficiência para as mensagens subsequentes. + + + Quando alguém envia uma mensagem para você, você receberá a chave de conversa, criptografada com sua chave pública de identidade, e as mensagens criptografadas com a chave de conversa. -### 1. Par de chaves de identidade + Você usa sua chave privada de identidade para descriptografar a chave de conversa (novamente, apenas você detém essa chave) e, em seguida, usa a chave de conversa resultante para descriptografar as mensagens. -**Propósito:** trocar com segurança chaves de conversa entre usuários + De tempos em tempos, as chaves em uma conversa são rotacionadas (uma nova chave simétrica é compartilhada), por diferentes motivos. Portanto, cada chave de conversa tem uma versão, para que os participantes sempre saibam que estão usando a chave correta. + + + A criptografia permite que qualquer pessoa envie uma mensagem que somente você possa descriptografar. A assinatura é, em certo sentido, o oposto: permite que você (e somente você) assine uma mensagem, e que qualquer pessoa verifique a assinatura. Na prática, a chave privada é necessária para assinar, e a chave pública pode ser usada para verificar. -| Componente | Descrição | -|:-----------|:----------| -| **Chave pública de identidade** | Compartilhada com outros; usada para criptografar chaves de conversa *para* você | -| **Chave privada de identidade** | Mantida em segredo; usada para descriptografar chaves de conversa enviadas *para* você | + No X Chat, todo remetente assina sua mensagem. As assinaturas provam tanto quem assinou a mensagem quanto os bytes exatos assinados, então todos os destinatários podem verificar que exatamente essa mensagem foi o que o remetente digitou. Novamente, o XDK cuida disso para você; cobrimos os detalhes em [Assinaturas explicadas](#signatures-explained). + +
-Quando alguém adiciona você a uma conversa, essa pessoa criptografa a chave da conversa usando sua chave pública de identidade. Apenas sua chave privada de identidade pode descriptografá-la. +--- -As metades públicas são registradas e descobertas por meio das APIs de **chave pública** da plataforma (veja Chaves de criptografia na referência de API). As metades privadas ficam no Chat XDK (por exemplo, via [backup seguro de chave](#secure-key-backup-distributed-key-storage) ou um blob de chave cuidadosamente protegido). +## Juntando tudo -### 2. Par de chaves de assinatura +O X Chat combina três ferramentas criptográficas padrão, cada uma fazendo a única tarefa que faz bem: -**Propósito:** provar que você é o autor de uma mensagem +1. Uma **chave de conversa** criptografa mensagens: simétrica, rápida o suficiente para todo o tráfego de mensagens e mídia. +2. Um **par de chaves de identidade** entrega chaves de conversa a cada participante sem que mais ninguém (incluindo o X) as veja. +3. Um **par de chaves de assinatura** prova autoria: cada mensagem carrega uma assinatura que os destinatários verificam. -| Componente | Descrição | -|:-----------|:----------| -| **Chave pública de assinatura** | Compartilhada com outros; usada para verificar suas assinaturas | -| **Chave privada de assinatura** | Mantida em segredo; usada para assinar suas mensagens | +```mermaid +flowchart TB + subgraph "Message Encryption" + A[Your Message] --> B[Encrypt with
Conversation Key] + B --> C[Encrypted Message] + end -Quando você envia uma mensagem, ela é assinada com sua chave privada de assinatura. Os destinatários verificam usando sua chave pública de assinatura (também publicada pelas APIs de chave pública). O Chat XDK assina como parte da criptografia de uma mensagem e pode verificar na descriptografia quando você fornece o material de chave pública do remetente. + subgraph "Key Delivery" + D[Conversation Key] --> E[Wrap to Recipient's
Identity Public Key] + E --> F[Encrypted Key Copy
for Recipient] + end -### 3. Chave da conversa + subgraph "Authentication" + C --> G[Sign with Your
Signing Private Key] + G --> H[Signature] + end +``` -**Propósito:** criptografar e descriptografar mensagens (e [mídia](/pt/xchat/media)) dentro de uma conversa específica +O X transporta e armazena apenas **texto cifrado e chaves encapsuladas**, nada que ele possa abrir. O XDK faz a criptografia; a [Chat API](/xchat/introduction) registra chaves e movimenta payloads criptografados ([Primeiros passos](/xchat/getting-started)). -| Propriedade | Descrição | -|:------------|:----------| -| **Simétrica** | A mesma chave criptografa e descriptografa | -| **Por conversa** | Cada conversa tem sua própria chave | -| **Compartilhada entre participantes** | Todos os participantes que devem ler a conversa têm uma cópia | -| **Versionada** | As chaves podem ser rotacionadas; os apps devem rastrear versões ao longo do tempo | +O elenco completo: -As chaves de conversa são geradas quando uma conversa é configurada ou quando as chaves são rotacionadas. Cada participante recebe uma **cópia criptografada** da chave, produzida com sua chave pública de identidade. Depois de descriptografar sua cópia uma vez, você guarda a chave da conversa em **bruto** e a usa para criptografia rápida de mensagens (e [mídia](/pt/xchat/media)). A configuração dessas cópias para uma conversa é feita por meio do Chat XDK juntamente com os endpoints de **chave** de conversa — abordados em [Primeiros passos](/pt/xchat/getting-started#4-set-up-conversation-keys). +| Chave | Quem a detém | O que ela faz | +|:----|:-------------|:-------------| +| **Identity keypair** | Metade privada: somente você. Metade pública: publicada | Recebe chaves de conversa encapsuladas | +| **Signing keypair** | Metade privada: somente você. Metade pública: publicada | Assina mensagens e mudanças de estado; outros verificam | +| **Conversation key** | Cada participante de uma conversa | Criptografa mensagens e mídia; versionada, rotacionada | --- -## Como a criptografia funciona (conceitualmente) +## Um exemplo prático -### Enviando uma mensagem +Vamos percorrer o que realmente acontece quando você cria um grupo com Bob e Carol. - - Você digita: "Olá, tudo bem?" - - - Seu app usa a chave da conversa em bruto para este chat (obtida na configuração ou em um evento anterior de distribuição de chaves), para a versão de chave correta. - - - O Chat XDK criptografa sua mensagem com a chave da conversa. O resultado é texto cifrado que é inútil sem essa chave. + + O XDK gera uma nova chave de conversa aleatória. Até aqui ela existe apenas na memória do seu dispositivo. - - O Chat XDK assina o payload criptografado com sua chave privada de assinatura, provando que você é o autor deste conteúdo exato. + + Seu app busca as chaves públicas de Bob e Carol no backend do X e verifica a assinatura em cada uma. Se uma assinatura não confere, você para; nunca criptografe para uma chave que você não conseguiu verificar. - - Seu app envia o payload criptografado e a assinatura para o X por meio do endpoint **send message** da Chat API. O X armazena e entrega bytes que ele não consegue ler em texto simples. - - - -### Recebendo uma mensagem - - - - Seu app recebe texto cifrado do X — via [webhooks ou um activity stream](/pt/xchat/real-time-events), ou lendo os **eventos** da conversa para obter o histórico. + + O XDK encapsula a chave de conversa três vezes: para a chave pública de identidade de Bob, para a de Carol e para a sua (para que seus outros dispositivos também possam lê-la). - - Use sua chave em bruto em cache, ou obtenha-a descriptografando sua cópia a partir de um evento de distribuição de chave (mudança de chave), caso seja nova ou tenha sido rotacionada. + + O XDK assina um payload que descreve exatamente esta mudança: o grupo, seus membros, as chaves encapsuladas. Criar um grupo requer **duas** [assinaturas de ação](#signed-state-changes-action-signatures); o XDK produz ambas para você. - - O Chat XDK verifica a assinatura usando a chave pública de assinatura do remetente (e a vinculação de identidade relacionada), para que você saiba quem a enviou e que ela não foi modificada. + + Seu app envia via POST as cópias encapsuladas e assinaturas para o X. O servidor armazena três blobs criptografados que ele não pode abrir. Em nenhum momento a chave de conversa em bruto saiu do seu dispositivo! - - O Chat XDK descriptografa com a chave da conversa. Agora você pode ler: "Olá, tudo bem?" + + O XDK de Bob desencapsula sua cópia com sua chave privada de identidade, verifica que a mudança de chave veio de você e mantém a chave de conversa em bruto. -A implementação de criptografia, envio, recebimento e descriptografia está em [Primeiros passos](/pt/xchat/getting-started) e na referência do [Chat XDK](/pt/xchat/xchat-xdk). - ---- - -## Distribuição de chaves explicada - -Um desafio central em criptografia de ponta a ponta é a **distribuição de chaves**: como os participantes obtêm a chave da conversa **sem** que o X (ou um observador) veja essa chave em texto claro. - -### Configuração inicial da chave +Essa é a configuração única. A partir daqui, cada mensagem segue os mesmos dois fluxos: -Quando uma conversa é preparada para envio de mensagens: +**Envio.** O XDK criptografa sua mensagem com a chave de conversa atual, assina-a, e seu app envia via POST ambas ao endpoint **send message**. O X armazena e entrega bytes que ele não pode ler. -1. O Chat XDK gera uma chave de conversa aleatória -2. O Chat XDK criptografa essa chave para a **chave pública de identidade de cada participante** -3. Seu app publica essas cópias criptografadas por meio das APIs de Chat do X -4. Cada participante descriptografa **sua** cópia com sua chave privada de identidade (no Chat XDK) +**Recebimento.** O texto cifrado chega via [webhooks ou um stream de atividades](/xchat/real-time-events), ou lendo os **eventos** da conversa para obter o histórico. O XDK verifica primeiro a assinatura do remetente e então descriptografa com sua chave de conversa armazenada (se a chave foi rotacionada, um evento **key change** entrega sua nova cópia encapsulada). Se a verificação falhar, a mensagem é rejeitada. -O X só lida com as cópias **empacotadas**, nunca com a chave da conversa em bruto. - -### Eventos de mudança de chave - -Quando a chave da conversa é rotacionada (por exemplo, quando a composição do grupo muda), os participantes recebem um evento de **mudança de chave** com novas cópias criptografadas para cada membro. - -Seu app deve: - -1. Notar material de mudança de chave em eventos ao vivo ou no histórico da conversa -2. Descriptografar e armazenar a nova chave da conversa (e a versão) -3. Usar a versão mais recente para envios subsequentes - -[Primeiros passos](/pt/xchat/getting-started#6-receive-and-decrypt) e [Eventos em tempo real](/pt/xchat/real-time-events) descrevem onde esses eventos aparecem na prática. +A implementação está em [Primeiros passos](/xchat/getting-started) e na referência do [Chat XDK](/xchat/xchat-xdk). --- -## Backup seguro de chave: armazenamento distribuído de chaves +## Backup seguro de chaves: armazenamento distribuído de chaves -Suas chaves **privadas** de identidade e assinatura devem ser armazenadas com cuidado. O X Chat inclui um sistema de **backup seguro de chave** para que as chaves possam ser recuperadas com um código de acesso entre dispositivos, sem que nenhum servidor detenha o segredo completo. +Dissemos anteriormente que suas chaves privadas são salvas no **backup seguro de chaves**, recuperáveis somente com seu código de acesso. Vamos ver como isso funciona, porque é a parte sobre a qual as pessoas mais se mostram céticas: como podem chaves ser copiadas em backup sem que o X seja capaz de lê-las? ### O problema com o armazenamento tradicional de chaves | Abordagem | Problema | -|:----------|:---------| -| Armazenar apenas no dispositivo | Perder o dispositivo = perder as chaves = perder o acesso ao histórico de mensagens | +|:---------|:--------| +| Armazenar somente no dispositivo | Perder o dispositivo = perder as chaves = perder acesso ao histórico de mensagens | | Armazenar em um backup em nuvem comum | O provedor pode acessar o material da chave | -| Lembrar uma chave longa | As pessoas não conseguem memorizar de forma confiável chaves de alta entropia | +| Memorizar uma chave longa | As pessoas não conseguem memorizar segredos de alta entropia | + +### Como o backup seguro de chaves resolve isso + +O X Chat utiliza o protocolo open-source [**Juicebox**](https://juicebox.xyz), que combina **compartilhamento de segredo com limiar** (threshold secret sharing) com proteção por código de acesso. O protocolo completo está especificado lá; a versão resumida: -### Como o backup seguro de chave resolve isso +**Armazenando (uma vez, na criação da conta).** O XDK divide suas chaves privadas em partes (shares) e as distribui a três **realms**, serviços separados isolados uns dos outros. Todos os três são operados pelo X, então o isolamento por si só não significaria muito. É aí que entra o hardware: dois dos realms residem dentro de **hardware security modules** (HSMs), hardware resistente a violações que não entregará sua parte a ninguém, nem mesmo a um administrador do X com acesso total ao servidor. Uma parte sozinha não revela nada, e a recuperação requer partes de **dois dos três** realms, então toda recuperação possível passa por pelo menos um HSM: não há caminho apenas por software até suas chaves. O software do HSM e a **key ceremony** que o provisionou são publicamente documentados. -O backup seguro de chave combina **compartilhamento de segredo** com **proteção por código de acesso**: +**Recuperando (novo dispositivo).** Você digita seu código de acesso, e o XDK prova a cada realm que você o conhece. O protocolo Juicebox torna isso possível sem que o código de acesso jamais saia do seu dispositivo. Cada realm que verifica você libera sua parte de suas chaves e, quando dois dos três respondem, o XDK reconstrói suas chaves no seu dispositivo. -1. As chaves privadas são **divididas em partes (shares)** -2. As partes são mantidas por **realms independentes** (servidores separados) -3. **Nenhum realm sozinho** tem informação suficiente para reconstruir as chaves -4. A recuperação exige seu **código de acesso** e a cooperação de **realms suficientes** -5. Códigos incorretos têm **limitação de taxa** para retardar tentativas +**Limites de tentativas.** Cada realm permite no máximo **20 tentativas incorretas de código de acesso**. Na 20ª tentativa incorreta, sua parte da chave é excluída do realm. Isso é imposto por hardware pelos HSMs e protege contra qualquer ataque de força bruta. ```mermaid flowchart LR - A[Your Private Keys] --> B[Split into Shares] - B --> C[Realm 1
Share A] - B --> D[Realm 2
Share B] - B --> E[Realm 3
Share C] - - subgraph Recovery - F[Your Passcode + Multiple Realms] --> G[Reconstruct Keys] + subgraph Storing + A[Your Private Keys] --> B[Split into Shares] + B --> C[Realm 1
Share A · HSM] + B --> D[Realm 2
Share B · HSM] + B --> E[Realm 3
Share C] end + + subgraph Recovering + F[Your Passcode + 2 of 3 Realms] --> G[Reconstruct Keys] + end + + E ~~~ F ``` -Você obtém capacidade de recuperação (novo dispositivo + código de acesso) sem que um único participante detenha o segredo inteiro. +O resultado: você pode recuperar suas chaves em um novo dispositivo com apenas seu código de acesso, nenhum realm sozinho detém o segredo inteiro, e os realms apoiados em hardware impõem seus limites até mesmo contra o próprio X. -Você não configura os servidores de backup de chave manualmente no caminho normal. O Chat XDK inclui o cliente de backup; a configuração dos realms vem da API do X pelo campo **`juicebox_config`** do seu registro de chave pública. O armazenamento inicial do código de acesso e o desbloqueio posterior são chamadas do Chat XDK — veja [inicializar com chaves existentes](/pt/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) e [criar e registrar chaves](/pt/xchat/getting-started#3-create-and-register-keys-first-time-setup) em Primeiros passos. Alguns apps (especialmente servidores e bots) usam um blob de chave exportado em vez do backup seguro de chave; proteja esse material como uma senha. +Você não configura nada disso manualmente. O Chat XDK inclui o cliente de backup, e a configuração dos realms chega do backend do X junto com o seu registro de chave pública. O armazenamento e o desbloqueio via código de acesso são chamadas do Chat XDK; veja [inicializar com chaves existentes](/xchat/getting-started#2-initialize-the-chat-xdk-with-existing-keys) e [criar e registrar chaves](/xchat/getting-started#3-create-and-register-keys-first-time-setup). Servidores e bots frequentemente pulam o backup e usam um blob de chave exportado; proteja-o como uma senha. --- ## Assinaturas explicadas -Toda mensagem do X Chat inclui uma **assinatura digital** que apoia: - -1. **Autenticidade** — foi produzida com a chave privada de assinatura do remetente -2. **Integridade** — o conteúdo criptografado não foi modificado após a assinatura +A assinatura de cada mensagem oferece aos destinatários duas garantias: -### Como as assinaturas funcionam (conceitualmente) +1. **Autenticidade**: produzida pelo detentor da chave privada de assinatura do remetente +2. **Integridade**: o conteúdo criptografado não foi modificado após a assinatura -| Ação | Chave usada | Resultado | -|:-----|:------------|:----------| -| **Assinar** | Chave privada de assinatura do remetente | Uma assinatura vinculada a esta mensagem criptografada exata | -| **Verificar** | Chave pública de assinatura do remetente | Confirma que a assinatura corresponde à mensagem e à chave | +Se qualquer coisa no conteúdo assinado mudar, a verificação falha. Claro, essa garantia é forte apenas na medida em que a chave de assinatura permaneça secreta, e é por isso que o [armazenamento de chaves](#secure-key-backup-distributed-key-storage) importa tanto. -Se qualquer coisa no material assinado mudar, a verificação falha. Apenas alguém com a chave privada de assinatura pode produzir uma assinatura válida para essa chave. +**No seu app.** O XDK assina quando você criptografa e verifica quando você descriptografa. A rejeição acontece em ambas as extremidades: o próprio X Chat rejeita eventos que não consegue verificar, e o XDK faz o mesmo no recebimento, **obrigatório por padrão** (desabilitar isso não é recomendado). Detalhes: [Chat XDK](/xchat/xchat-xdk). -### No seu app - -O Chat XDK assina quando você criptografa mensagens de saída e verifica quando descriptografa as de entrada, comparando com o material de chave pública do remetente (das APIs de chave pública). A verificação é **obrigatória por padrão**: o SDK rejeita eventos assinados não verificados, a menos que você desabilite explicitamente a checagem (não recomendado). Detalhes estão na referência do [Chat XDK](/pt/xchat/xchat-xdk). - -As assinaturas também cobrem conteúdo citado. Uma resposta incorpora a mensagem original **assinada** em bruto que ela cita; quando o Chat XDK descriptografa a resposta, ele verifica essa original incorporada e compara a citação com ela, reportando o resultado como `reply_preview_validation` (`Valid` / `Invalid`). Um resultado `Invalid` significa que a citação não corresponde ao original assinado — trate o material citado como não confiável, mesmo que a resposta em si seja verificada separadamente — para que nenhum participante possa atribuir palavras falsas a outro. +As assinaturas também cobrem conteúdo citado. Uma resposta embute a mensagem original **assinada** em bruto que ela cita; quando o Chat XDK descriptografa a resposta, ele verifica essa original embutida e compara a citação com ela, reportando o resultado como `reply_preview_validation` (`Valid` / `Invalid`). Um resultado `Invalid` significa que a citação não corresponde à original assinada — trate o material citado como não confiável, mesmo que a própria resposta seja verificada separadamente — para que nenhum participante possa atribuir palavras fabricadas a outro. ### Mudanças de estado assinadas (assinaturas de ação) -Mensagens não são o único material assinado. Toda chamada que muda o estado da conversa — adicionar ou rotacionar chaves de conversa, criar um grupo, adicionar membros — deve carregar uma ou mais **assinaturas de ação**: o remetente assina um payload descrevendo exatamente o que a mudança faz (para uma mudança de chave, esse payload inclui a própria nova chave da conversa), e a API rejeita a solicitação se as assinaturas estiverem ausentes ou malformadas. +Mensagens não são a única coisa assinada. Toda mudança em uma conversa (criar um grupo, adicionar membros, rotacionar uma chave) também deve carregar **assinaturas de ação**: o remetente assina um payload descrevendo exatamente o que a mudança faz, e a API rejeita solicitações onde estas estejam ausentes ou malformadas. O XDK as produz para você. -Como o servidor nunca detém a chave da conversa em texto claro, ele não pode verificar criptograficamente a assinatura de uma mudança de chave; ele valida que a descrição assinada e codificada da mudança corresponde à solicitação recebida. A verificação **criptográfica** acontece nas extremidades: o Chat XDK de cada destinatário verifica a assinatura contra a chave pública de assinatura do remetente ao descriptografar o evento de mudança de chave. Os métodos `prepare` do Chat XDK produzem essas assinaturas para você — criação de grupo e adição de membros retornam **duas** (a mudança de chave mais a ação de grupo), e ambas devem ser enviadas. +**Por que o servidor não pode verificar totalmente uma mudança de chave.** O servidor nunca detém a chave de conversa em bruto (esse é o ponto), então ele não pode verificar uma assinatura sobre material que ele não pode ver. Ele verifica o que pode, que a descrição assinada corresponde à solicitação, e os destinatários fazem a verificação criptográfica de verdade quando desencapsulam a mudança de chave. -As assinaturas são vinculadas ao conteúdo do evento e são imutáveis: um evento cuja assinatura não verifica nunca poderá se tornar válido depois. Veja [Solução de problemas](/pt/xchat/troubleshooting) para saber como lidar com esses casos. +Os eventos são imutáveis: um que falhe na verificação é permanentemente inválido. Veja [Solução de problemas](/xchat/troubleshooting). --- ## Propriedades de segurança -### Contra o que o X Chat protege +Aqui está do que o X Chat protege e, tão importante quanto, do que ele não protege. + +### Do que o X Chat protege -| Ameaça | Proteção | -|:-------|:---------| -| **O X ler o corpo das mensagens** | O conteúdo é criptografado antes de ser enviado ao X | -| **Interceptadores de rede** | Segurança de transporte mais conteúdo criptografado de ponta a ponta | -| **Adulteração de mensagens** | Assinaturas detectam modificação | -| **Falsificação trivial de remetente** | Assinaturas válidas exigem a chave privada de assinatura do remetente | -| **Roubo de chave em um único servidor (com backup seguro de chave)** | As partes são divididas entre realms e protegidas por código de acesso | +| Ameaça | Proteção | Baseado em | +|:-------|:-----------|:-----------| +| **X lendo corpos de mensagens** | O conteúdo é criptografado antes de chegar ao X | Chaves de conversa nunca saem desencapsuladas dos dispositivos dos participantes | +| **Bisbilhoteiros de rede** | Segurança de transporte mais conteúdo criptografado de ponta a ponta | TLS padrão, mais tudo acima | +| **Adulteração de mensagens** | Assinaturas detectam qualquer modificação | Verificação de assinatura em todo evento | +| **Falsificação de identidade do remetente** | Uma assinatura válida requer a chave privada de assinatura do remetente | Sigilo da chave de assinatura, mais o key binding que você verificou | +| **Roubo de chave em um servidor de backup** | As partes são divididas entre realms e protegidas por código de acesso, com um limite rígido de tentativas | Nenhum realm sozinho pode reconstruir as chaves; HSMs impõem o limite de tentativas em hardware | -### Contra o que o X Chat **não** protege +### Do que o X Chat não protege, e por quê -| Ameaça | Por quê | -|:-------|:--------| -| **Dispositivo comprometido** | Texto simples e chaves podem ser expostos em um cliente desbloqueado | -| **Metadados** | O X pode saber quem enviou mensagens para quem e quando — não o texto da mensagem | -| **Sigilo futuro (forward secrecy)** | Comprometer chaves de identidade pode expor chaves de conversa empacotadas com essas chaves | -| **Segurança pós-comprometimento** | Rotacionar chaves não reescreve o histórico | +| Limitação | A versão honesta | +|:-----------|:-------------------| +| **Um dispositivo comprometido** | Um cliente desbloqueado detém texto simples e chaves em bruto. Nenhum design de ponta a ponta sobrevive a um endpoint comprometido. | +| **Metadados** | O X precisa saber quem enviou mensagem para quem, e quando, para rotear texto cifrado. A criptografia esconde o *o quê*, não o *quem* ou *quando*. | +| **Sem forward secrecy** | Chaves de conversa são encapsuladas para chaves de identidade de longa duração: um atacante com sua chave privada de identidade pode desencapsular envelopes previamente capturados e, com eles, texto cifrado passado. | +| **Sem cicatrização automática pós-comprometimento** | A recuperação funciona, mas é deliberada, não automática: remover um atacante rotaciona a chave de conversa, e recuperar um dispositivo comprometido geralmente inclui gerar uma nova chave de identidade e novas chaves de conversa, de modo que mesmo chaves roubadas não leem nada novo. O que nenhuma rotação pode fazer é reescrever o passado, ou protegê-lo na janela antes de o comprometimento ser tratado. | --- ## Glossário | Termo | Definição | -|:------|:----------| -| **Criptografia simétrica** | A mesma chave criptografa e descriptografa (usada para mensagens e fluxos de mídia) | -| **Criptografia assimétrica** | Chaves diferentes para criptografar e descriptografar (usada para trocar chaves de conversa) | -| **Chave pública** | Segura para compartilhar; usada para criptografar *para* alguém ou verificar suas assinaturas | -| **Chave privada** | Deve permanecer secreta; usada para descriptografar ou assinar | -| **Par de chaves (keypair)** | Uma chave pública e uma chave privada vinculadas | -| **ECDH / ECIES** | Algoritmos usados ao trocar chaves de conversa via chaves de identidade | -| **ECDSA** | Algoritmo de assinatura usado para autoria de mensagens | -| **P-256** | Curva elíptica usada no X Chat (secp256r1) | -| **Chave da conversa** | Chave simétrica compartilhada pelos participantes de uma conversa (versionada ao longo do tempo) | -| **Compartilhamento de segredo** | Dividir um segredo de modo que várias partes sejam necessárias para reconstruí-lo | -| **Realm** | Um servidor de backup seguro de chave independente que detém uma parte do seu material de chave | +|:-----|:-----------| +| **Symmetric encryption** | A mesma chave criptografa e descriptografa (usada para mensagens e mídia) | +| **Asymmetric encryption** | Chave pública para criptografar, chave privada para descriptografar (usada para entregar chaves de conversa) | +| **Public key** | Segura para publicar; usada para criptografar *para* alguém ou verificar suas assinaturas | +| **Private key** | Deve permanecer secreta; usada para descriptografar ou assinar | +| **ECDH** | *Acordo* de chaves: duas partes derivam um segredo compartilhado da chave privada de uma e da chave pública da outra | +| **ECIES** | Criptografia híbrida construída sobre ECDH: deriva um segredo compartilhado, criptografa simetricamente sob ele. Como as chaves de conversa são encapsuladas | +| **ECDSA** | O algoritmo de assinatura de curvas elípticas usado para mensagens e assinaturas de ação | +| **P-256** | A curva elíptica (secp256r1) que todos os pares de chaves do X Chat usam | +| **Key binding** | A assinatura publicada que amarra a chave de identidade de um usuário à sua chave de assinatura; verificada antes de encapsular qualquer coisa para um registro buscado | +| **Conversation key** | Chave simétrica compartilhada pelos participantes de uma conversa, versionada ao longo do tempo | +| **Wrapping** | Criptografar uma chave sob outra; aqui, uma chave de conversa sob uma chave pública de identidade | +| **Threshold secret sharing** | Dividir um segredo em partes de modo que apenas um subconjunto suficiente possa reconstruí-lo; menos que o limiar não aprende nada | +| **Juicebox** | O protocolo open-source por trás do backup seguro de chaves: recuperação com limiar protegida por código de acesso, com limites rígidos de tentativas | +| **HSM** | Hardware security module: hardware resistente a violações que detém a parte de um realm e impõe seu limite de tentativas | +| **Realm** | Um serviço de backup seguro de chaves separado e isolado que detém uma parte do seu material de chave | --- ## Próximos passos - + Implemente chaves, envio e recebimento passo a passo - + Métodos e tipos do SDK de criptografia - + Visão geral do produto e arquitetura - - Como os eventos criptografados são entregues + + Como eventos criptografados são entregues