Skip to main content
Envía y recibe mensajes directos cifrados de extremo a extremo en X: configura claves, inicializa una conversación, envía un mensaje y descifra el tráfico entrante. Las apps de X Chat usan dos piezas en conjunto:
Requisitos previos
  • Cuenta de desarrollador y una app configurada para OAuth 2.0
  • Token de acceso de usuario con dm.read, dm.write, tweet.read y users.read

1. Instalar dependencias

El paquete de PyPI es chatxdk; impórtalo como chat_xdk. Requiere Python 3.10+.
Crea un cliente de la API con tu token de acceso OAuth 2.0 de usuario:

2. Inicializar el Chat XDK con claves existentes

Este paso carga claves que ya tienes—úsalo cuando esta identidad ya haya completado la configuración inicial antes:
  • Copia de seguridad segura de claves: construye el SDK con el juicebox_config de tu registro de public-key, luego unlock con tu código de acceso para recuperar las claves privadas (por ejemplo, en un nuevo dispositivo).
  • Blob de claves: import_keys con un blob que exportaste previamente mediante export_keys, pasando junto a él la versión de clave registrada (Rust y Go llaman a esta variante import_keys_with_version / ImportKeysWithVersion).
Luego llama a set_identity(user_id, signing_key_version) una vez, con tu ID de usuario y el public_key_version de tu registro. Esto almacena la identidad de la sesión: cada llamada posterior de encrypt y prepare firma como esta identidad, así que nunca pasas un ID de remitente ni una versión de clave de firma por llamada. ¿Configurando por primera vez? Construye el SDK de la misma forma pero omite unlock/import_keys, y continúa al paso 3 para crear, respaldar y registrar tus claves.
Los ejemplos de servidor y bot suelen usar un blob de claves (export_keys / import_keys). Las apps de cliente suelen usar copia de seguridad segura de claves (setup / unlock con un código de acceso). Consulta la referencia del Chat XDK para ambas rutas.
¿Traes tus propias claves? import_keys solo acepta el blob opaco producido por export_keys del Chat XDK—es una serialización privada y versionada del estado completo de la clave, no claves P-256 en bruto o codificadas en PEM. No puedes construir este blob por tu cuenta: genera claves mediante generate_keypairs (paso 3), exporta el blob una vez y guárdalo codificado en base64. Los blobs artesanales o modificados fallan al importar.

3. Crear y registrar claves (configuración inicial)

Omite este paso si cargaste claves existentes en el paso 2. En caso contrario, la configuración única para una nueva identidad hace tres cosas:
  1. Crear los pares de clavesgenerate_keypairs produce los pares de claves de identidad y de firma.
  2. Almacenar las claves privadassetup con un código de acceso las escribe en la copia de seguridad segura de claves (clientes), o export_keys devuelve un blob de claves para que lo guardes de forma segura (servidores y bots).
  3. Registrar las claves públicas — POST al payload de registro al endpoint add-public-key para que otros puedan cifrar hacia ti y verificar tus firmas.
Termina llamando a set_identity con la versión de clave del registro, para que esta sesión firme como la nueva identidad.
Los scripts de registro único listos para ejecutar para cada binding están en chat-xdk/examples (Python, TypeScript, Go, Rust, C# y Java). Úsalos en lugar de armar el flujo a mano cuando solo necesites incorporar una nueva identidad.
Usa un código de acceso robusto para la copia de seguridad segura de claves. Perder el código de acceso o un blob de claves desprotegido puede impedir descifrar mensajes pasados.

4. Configurar claves de conversación

Llama a prepare_conversation_key_change con la clave pública de identidad de cada participante; la identidad del remitente proviene de la sesión que configuraste en el paso 2. Una llamada genera una nueva clave de conversación, la cifra para cada participante y firma el cambio. Envía el resultado con POST al endpoint add conversation keys (POST /2/chat/conversations/{id}/keys)—el cuerpo necesita conversation_key_version, conversation_participant_keys (SDK encrypted_key → API encrypted_conversation_key) y action_signatures (obligatorio; la API rechaza la llamada sin ellas). Guarda la clave de conversación en bruto para enviar. La respuesta devuelve el ID canónico de la conversación (data.conversation_id—el par unido por guion para un 1:1, o el ID con prefijo g para un grupo) y el data.sequence_id del cambio de clave. Usa ese ID devuelto para solicitudes posteriores en lugar de reconstruirlo del lado del cliente. La misma llamada también rota claves más tarde: pasa el ID de conversación existente a prepare_conversation_key_change y haz POST con la versión de clave más reciente. Rota cuando sospeches que la clave de conversación fue expuesta—la rotación protege solo los mensajes futuros; los mensajes cifrados con versiones anteriores de la clave siguen siendo legibles para cualquiera que tenga esas versiones.
Verifica las claves obtenidas antes de envolverlas. prepare_conversation_key_change cifra la nueva clave de conversación con cualquier clave pública que pases. Verifica primero cada registro obtenido con verify_key_binding(identity, signing, signature)—pasando los campos public_key, signing_public_key e identity_public_key_signature del registro desde la API de public-keys—para que una clave de identidad sustituida no pueda recibir la clave de conversación.

5. Enviar un mensaje

Cifra con la clave de conversación en bruto del paso 4. El SDK genera el ID del mensaje (un UUID), lo incrusta en el evento firmado y lo devuelve en el payload—nunca lo generas tú mismo. En la solicitud de envío, mapea: Usa un ID de conversación con guiones en la ruta de la URL cuando la API lo requiera (:-). El SDK en sí es flexible: encrypt_message y encrypt_reply aceptan el ID en cualquier forma que tengas—A:B de eventos, A-B de listados o rutas URL (en cualquier orden), o simplemente el user id del destinatario—y lo canonicaliza antes de firmar. Los IDs de grupo (con prefijo g) se pasan sin cambios.
Los snippets pasan la clave de conversación explícitamente porque en este flujo acabas de crearla en el paso 4. Una vez que la caché de claves esté activada y una pasada de decrypt_events haya verificado la clave de la conversación (paso 6), basta con encrypt_message(conversation_id, text)—el SDK completa con la última clave verificada. Los reintentos deben reenviar el mismo payload cifrado, para que nunca se genere un ID dos veces.

6. Recibir y descifrar

Usa webhooks o el activity stream para el tráfico en vivo, o pagina los events de conversación para el historial.
  • Campos del payload en vivo: encoded_event, opcional conversation_key_change_event
  • Historial: GET /2/chat/conversations/{id}/events — prefiere decrypt_events en todos los eventos más meta.conversation_key_events
  • Descifrar necesita las claves de firma de los remitentes para que el SDK pueda verificar quién escribió cada mensaje. Estas son las claves públicas de los demás participantes — obténlas del mismo endpoint public-keys que usaste en el paso 4 y mapea los campos a SigningKeyEntry (los snippets a continuación incluyen el mapeo)
  • Puedes pasar las claves de firma (y, para decrypt_event, las claves de conversación) en cada llamada, o configurar dos almacenes de sesión opcionales una vez y usar las formas de llamada breves. Los snippets a continuación usan los almacenes: set_signing_keys(entries) guarda las claves de los participantes, y set_cache_keys(true) (desactivado por defecto) mantiene la última clave verificada por firma de cada conversación para que las llamadas posteriores puedan omitir los argumentos de clave. Ambos estilos verifican de forma idéntica
  • JavaScript usa tipos de evento en camelCase (message); otros lenguajes usan "Message" y campos en snake_case en JSON
¿Serverless o multi-instancia? El almacén de claves de firma y la caché de claves viven en la memoria de la instancia del SDK. Donde eso no encaja—una invocación descifra, otra envía—pasa las claves explícitamente en su lugar: decrypt_events(events, signing_keys), decrypt_event(event_b64, conversation_keys, signing_keys), y las anulaciones conversation_key/conversation_key_version en los métodos de cifrado. Persiste tú mismo las conversation_keys devueltas por decrypt_events y vuelve a pasarlas.
Bots completos de poll-and-reply para cada lenguaje: chat-xdk/examples.

Buenas prácticas

  • Mantén el almacén de claves de firma actualizado: vuelve a llamar a set_signing_keys con el conjunto completo de participantes cuando un remitente registre una nueva versión de clave, y refresca ante fallos de verificación de firma
  • Deduplica las entregas en vivo con event_uuid