Skip to main content
This primer explains the cryptographic ideas behind X Chat at a conceptual level. You do not need this depth to build—the Chat XDK performs encryption, decryption, signing, and key storage for you—but the mental model helps when you design your app or debug behavior. When you are ready to implement, use Getting Started for a full walkthrough and the API reference in the sidebar for individual routes.
You don’t implement this cryptography yourself. The Chat XDK handles it. This page is for understanding, not an API checklist.

The big picture

X Chat uses a layered encryption system where:
  1. Messages are encrypted with a conversation key (fast symmetric encryption)
  2. Conversation keys are encrypted to each participant using their identity public key (asymmetric key exchange)
  3. Messages are signed so recipients can verify who sent them and that nothing was altered
Symmetric encryption is efficient for lots of message traffic; asymmetric encryption is used mainly to distribute conversation keys safely. In the product flow, X transports ciphertext and key envelopes—not readable message content or the raw conversation key. Your app uses the Chat XDK for crypto and the Chat API (via the XDK in Python/TypeScript, or HTTPS) to register keys and send or receive those encrypted payloads. See Getting Started for how those pieces fit together.

Key types explained

X Chat uses three kinds of key material, each with a specific purpose.

1. Identity keypair

Purpose: Securely exchange conversation keys between users When someone adds you to a conversation, they encrypt the conversation key using your identity public key. Only your identity private key can decrypt it. Public halves are registered and discovered through the platform’s public-key APIs (see Encryption keys under API reference). Private halves stay in the Chat XDK (for example via Juicebox or a carefully protected key blob).

2. Signing keypair

Purpose: Prove that you authored a message When you send a message, it is signed with your signing private key. Recipients verify using your signing public key (also published through the public-key APIs). The Chat XDK signs as part of encrypting a message and can verify on decrypt when you supply the sender’s public key material.

3. Conversation key

Purpose: Encrypt and decrypt messages (and media) within a specific conversation Conversation keys are generated when a conversation is set up or when keys rotate. Each participant gets an encrypted copy of the key, produced with their identity public key. After you decrypt your copy once, you keep the raw conversation key and use it for fast message (and media) encryption. Setting up those copies for a conversation is done through the Chat XDK together with conversation key endpoints—walked through in Getting Started.

How encryption works (conceptually)

Sending a message

1

Start with plaintext

You type: “Hello, how are you?”
2

Get the conversation key

Your app uses the raw conversation key for this chat (from setup or from an earlier key-distribution event), for the right key version.
3

Encrypt the message

The Chat XDK encrypts your message with the conversation key. The result is ciphertext that is useless without that key.
4

Sign the message

The Chat XDK signs the encrypted payload with your signing private key, proving you authored this exact content.
5

Send to X

Your app sends the encrypted payload and signature to X through the Chat API send message endpoint. X stores and delivers bytes it cannot read as plaintext.

Receiving a message

1

Receive encrypted data

Your app receives ciphertext from X—via webhooks or an activity stream, or by reading conversation events for history.
2

Get the conversation key

Use your cached raw key, or obtain it by decrypting your copy from a key-distribution (key change) event if this is new or rotated.
3

Verify the signature

The Chat XDK checks the signature using the sender’s signing public key (and related identity binding), so you know who sent it and that it was not modified.
4

Decrypt the message

The Chat XDK decrypts with the conversation key. You can now read: “Hello, how are you?”
Implementation of encrypt, send, receive, and decrypt is in Getting Started and the Chat XDK reference.

Key distribution explained

A central challenge in end-to-end encryption is key distribution: how participants get the conversation key without X (or an observer) seeing that key in the clear.

Initial key setup

When a conversation is prepared for messaging:
  1. The Chat XDK generates a random conversation key
  2. The Chat XDK encrypts that key to each participant’s identity public key
  3. Your app publishes those encrypted copies through X’s Chat APIs
  4. Each participant decrypts their copy with their identity private key (in the Chat XDK)
X only ever handles the wrapped copies, not the raw conversation key.

Key change events

When the conversation key rotates (for example when membership changes), participants receive a key change event with new encrypted copies for each member. Your app should:
  1. Notice key-change material on live events or in conversation history
  2. Decrypt and store the new conversation key (and version)
  3. Use the latest version for subsequent sends
Getting Started and Real-time events describe where those events appear in practice.

Juicebox: distributed key storage

Your private identity and signing keys must be stored carefully. X Chat integrates Juicebox so keys can be recovered with a PIN across devices without giving any single server the full secret.

The problem with traditional key storage

How Juicebox solves it

Juicebox combines secret sharing with PIN protection:
  1. Private keys are split into shares
  2. Shares are held by independent realms (separate servers)
  3. No single realm has enough information to reconstruct the keys alone
  4. Recovery requires your PIN and cooperation from enough realms
  5. Wrong PINs are rate-limited to slow guessing
You get recoverability (new device + PIN) without a single party holding the whole secret.
You do not configure Juicebox servers by hand for the normal path. The Chat XDK includes the Juicebox client; realm configuration comes from the X API as juicebox_config on your public-key record. First-time PIN storage and later unlock are Chat XDK calls—see Getting Started and register public keys. Some apps (especially servers and bots) use an exported key blob instead of Juicebox; protect that material like a password.

Signatures explained

Every X Chat message includes a digital signature that supports:
  1. Authenticity — it was produced with the sender’s signing private key
  2. Integrity — the encrypted content was not modified after signing

How signatures work (conceptually)

If anything in the signed material changes, verification fails. Only someone with the signing private key can produce a valid signature for that key.

In your app

The Chat XDK signs when you encrypt outbound messages and verifies when you decrypt inbound ones against the sender’s public key material (from the public-key APIs). Verification is mandatory by default: the SDK rejects unverified signed events unless you explicitly disable the check (not recommended). Details are in the Chat XDK reference.

Signed state changes (action signatures)

Messages are not the only signed material. Every call that changes conversation state—adding or rotating conversation keys, creating a group, adding members—must carry one or more action signatures: the sender signs a payload describing exactly what the change does (for a key change, that payload includes the new conversation key itself), and the API rejects the request if the signatures are missing or malformed. Because the server never holds the plaintext conversation key, it cannot check a key change’s signature cryptographically; it validates that the signed, encoded description of the change matches the request it received. The cryptographic check happens at the edges: each recipient’s Chat XDK verifies the signature against the sender’s signing public key when it decrypts the key-change event. The Chat XDK’s prepare methods produce these signatures for you—group creates and member adds return two (the key change plus the group action), and both must be sent. Signatures are bound to the event contents and are immutable: an event whose signature does not verify can never become valid later. See Troubleshooting for how to treat those.

Security properties

What X Chat protects against

What X Chat does not protect against


Glossary


Next steps

Getting Started

Implement keys, send, and receive step by step

Chat XDK Reference

Encryption SDK methods and types

Introduction

Product overview and architecture

Real-time events

How encrypted events are delivered