Skip to main content
O Chat XDK cuida do gerenciamento de chaves, criptografia, descriptografia e assinatura do X Chat. Ele não chama a API HTTP do X — combine-o com o XDK de Python ou TypeScript, ou com HTTPS e um token de acesso de usuário. Passo a passo do app: Primeiros passos. Bots de exemplo: chat-xdk/examples.

Instalação

O pacote no PyPI é chatxdk; importe-o como chat_xdk. Requer Python 3.10+.

Início rápido

Carregue as chaves, defina sua identidade uma vez, descriptografe um backlog, descriptografe um evento ao vivo, criptografe uma mensagem. Conecte o corpo de envio a POST /2/chat/conversations/{id}/messages como em Primeiros passos. Os snippets usam os dois armazenamentos de sessão opcionais para as formas mais curtas de chamada: set_signing_keys guarda as chaves públicas dos outros participantes (buscadas do endpoint de chaves públicas) para que chamadas de descriptografia possam verificar remetentes sem um argumento por chamada, e set_cache_keys(true) permite que o SDK lembre a chave verificada de cada conversa, de modo que chamadas de criptografia só precisam do ID da conversa e do texto. Pule qualquer um e passe os mesmos valores por chamada — ambos os estilos verificam de forma idêntica; veja Descriptografar.

Ciclo de vida e chaves

Construa o SDK, armazene chaves privadas (backup seguro de chave protegido por código de acesso ou um blob de chave local), registre as chaves públicas com a Chat API e chame set_identity(user_id, signing_key_version) após o unlock ou o import — isso define o remetente e a versão de chave de assinatura padrão de cada ação assinada, para que os métodos de criptografia e preparação funcionem sem argumentos de identidade por chamada. Chame generate_keypairs uma vez por identidade de dispositivo/app; poste o payload de registro no endpoint de chaves públicas. Use setup / unlock (e os helpers de código de acesso relacionados) para backup seguro de chave em cada binding. export_keys / import_keys (persistência de blob de chave em bruto para bots e servidores) estão disponíveis apenas nos bindings nativos — Python, Go, .NET, JVM e Rust. O binding JS/WASM não expõe exportação ou importação de chave em bruto: em um navegador, qualquer script que alcance a instância pode exfiltrar a identidade, então o JS mantém as chaves dentro do backup seguro de chave. Um servidor JS que queira evitar uma viagem ao realm de backup por requisição deve reutilizar uma instância Chat desbloqueada entre requisições, ou executar um binding nativo onde blobs de chave são suportados. O SDK também precisa da versão que a API do X reporta para sua chave pública registrada, para que entradas de mudança de chave direcionadas a outras versões sejam ignoradas. set_identity a registra junto com o ID de usuário; import_keys a aceita diretamente como um argumento opcional (Rust e Go usam import_keys_with_version / ImportKeysWithVersion).
A configuração do backup seguro de chave aceita três formatos: o objeto juicebox_config da API do X (recomendado — passado literalmente), um wrapper completo sdk_config ou um token_map puro. Opcional: a verificação de assinatura está ligada por padrão (reject_unverified = true) — chame set_reject_unverified(false) para desabilitá-la (não recomendado); update_config se a configuração do realm de backup mudar; is_unlocked / has_identity_key para estado de UI. As listas completas de campos estão nos stubs do repositório chat-xdk.

Chaves de conversa

Três métodos prepare, cada um faz com que uma chamada realize tudo o que uma mudança de chave precisa: gerar uma nova chave de conversa, criptografá-la para cada participante (a partir das chaves públicas que você passa) e assinar a mudança. A identidade do remetente e a versão de chave de assinatura vêm da sessão (set_identity); defina sender_id / signing_key_version nos parâmetros para sobrescrever. Todos retornam o mesmo formato PreparedConversationChange, pronto para POST — renomeie o campo do SDK encrypted_key para encrypted_conversation_key em conversation_participant_keys e mapeie as assinaturas de ação para o campo obrigatório action_signatures do corpo. Guarde os bytes da chave em bruto para encrypt_message e mídia; nunca passe o envelope criptografado da API para a criptografia.
Verifique as chaves obtidas antes de empacotar. Os métodos prepare criptografam a nova chave da conversa para quaisquer chaves públicas que você passar. Antes de passá-las, chame verify_key_binding(identity, signing, signature) em cada registro obtido — seus campos public_key, signing_public_key e identity_public_key_signature da API de chaves públicas — para que uma chave de identidade substituída não possa receber a chave da conversa.
Use extract_conversation_keys em payloads de eventos de mudança de chave para reconstruir { keys, latest_version }. decrypt_conversation_key desempacota um único blob ECIES.
Para criação de grupo e adição de membros, passe os parâmetros que cada método precisa (listas de IDs de membros/administradores para prepare_group_create; nova + composição atual para prepare_group_members_change) — veja Grupos para exemplos. Ambos retornam duas assinaturas de ação; o POST deve incluir as duas.

Descriptografar

decrypt_events é para histórico e backlog: extrai as chaves de conversa do fluxo, retorna mensagens descriptografadas e coleta erros por evento em vez de falhar o lote inteiro. decrypt_event é para um único evento ao vivo; lança/aciona exceção em caso de falha. Passe chaves de assinatura para que o SDK possa verificar remetentes. Mapeie os campos da API de chaves públicas para SigningKeyEntry: public_key_versionpublic_key_version (mesmo nome), signing_public_keypublic_key, public_keyidentity_public_key, mais identity_public_key_signature e user_id. Dois armazenamentos de sessão opcionais permitem omitir os argumentos de chave por chamada:
  • set_signing_keys(entries) armazena as chaves de assinatura dos participantes; uma chamada de descriptografia que omita (ou passe vazio) o argumento de chaves de assinatura usa o armazenamento no lugar. A verificação em si permanece inalterada — chaves entram no armazenamento apenas por essa chamada, nunca a partir dos eventos que estão sendo descriptografados. Cada chamada substitui o conjunto anterior.
  • set_cache_keys(true) habilita o cache de chave de conversa (desligado por padrão). Enquanto habilitado, decrypt_events faz cache, por conversa, da chave mais recente cuja mudança de chave tinha uma assinatura válida; decrypt_event recorre a ela quando seu argumento de chaves de conversa é omitido, e os helpers de criptografia resolvem uma chave de conversa omitida a partir dele. Desabilitar limpa o cache.
Um argumento explícito e não vazio sempre prevalece sobre os armazenamentos. Argumentos explícitos por chamada continuam sendo cidadãos de primeira classe — e são a escolha certa para deployments serverless ou multi-instância, onde uma requisição pode cair em uma instância nova cujos armazenamentos estão vazios. A verificação é obrigatória por padrão: omitir chaves de assinatura nunca a pula. Sem nada passado e nada armazenado, eventos assinados falham (coletados em errors para decrypt_events, lançados para decrypt_event). Para de fato pular a verificação, você deve primeiro chamar set_reject_unverified(false) (não recomendado em produção).

Helpers de criptografia e envio

encrypt_message(conversation_id, text) monta o texto cifrado assinado para uma mensagem de texto; opcionais entities, attachments (via media_hash_key), should_notify e ttl_msec. A identidade do remetente é resolvida a partir da sessão (set_identity) e a chave da conversa, a partir do cache opcional de chaves (set_cache_keys) — ou passe sender_id / signing_key_version e conversation_key + conversation_key_version explicitamente. O SDK gera o message_id (um UUID incorporado no evento assinado) e o retorna no payload — nunca crie o seu próprio; reutilize o mesmo payload em retentativas para que um ID nunca seja gerado duas vezes. Mapeie o payload para o corpo send-message: message_idmessage_id, encrypted_contentencoded_message_create_event, encoded_event_signatureencoded_message_event_signature. Respostas são baseadas em eventos. encrypt_reply(conversation_id, text, reply_to_event) recebe o evento em bruto codificado em base64 sendo respondido. O SDK deriva o preview citado (sequence id, remetente, texto, entidades, anexos) a partir dele e incorpora o original assinado na mensagem enviada para que os destinatários possam validar a citação. Passe reply_to_ckces — os eventos brutos de mudança de chave — quando o original foi criptografado em uma versão de chave mais antiga que a resposta. Quando o original foi editado, passe o evento de edição em bruto como reply_to_edit_event: o preview então cita o que a mensagem diz agora (seu texto e entidades vêm da edição), e a edição viaja junto com o original para o destinatário verificar. Os campos explícitos reply_to_* permanecem como overrides para callers que não têm mais o evento em bruto. Reações também são baseadas em eventos. encrypt_add_reaction(target_event, emoji) e encrypt_remove_reaction(...) derivam o ID da conversa e o sequence id alvo a partir do evento em bruto sendo reagido; os mesmos parâmetros podem adicionar e depois remover uma reação. Defina conversation_id e target_message_sequence_id explicitamente apenas quando você não tiver mais o evento em bruto. No lado do recebimento, uma mensagem descriptografada que cita uma resposta traz reply_preview_validation ("Valid" / "Invalid"; o binding JS usa 'valid' / 'invalid'): o SDK verificou a assinatura do original incorporado contra suas chaves de assinatura — nunca contra uma chave carregada no evento — descriptografou-o e comparou o conteúdo citado e o autor com ele. Quando o preview incorpora um evento de edição, o SDK verifica a edição da mesma forma (mesma conversa, mesmo autor do original) e confere o texto citado contra o conteúdo editado, em vez do texto pré-edição. O campo está ausente quando a mensagem não traz preview ou o preview não incorpora um original. Trate previews Invalid como não confiáveis: a mensagem em si é autêntica, mas o material citado não é — renderize as citações apenas a partir do original validado. encrypt / decrypt são para metadados UTF-8 sob a chave da conversa (por exemplo, um nome de grupo criptografado) — não envelopes de mensagem. encrypt_stream / decrypt_stream criptografam bytes de anexo; veja Mídia. Os sign / verify / verify_key_binding de baixo nível dão suporte a fluxos avançados; mudanças de chave de conversa, criações de grupo e adições de membros são assinadas pelos métodos prepare. O ID de conversa passado para encrypt_message / encrypt_reply pode ser qualquer forma que você tenha — A:B de eventos, A-B de listagens ou caminhos de URL (em qualquer ordem), ou o ID de usuário do destinatário puro — o SDK o canoniza antes de assinar. IDs de grupo (com prefixo g) passam sem alteração.

Streams de mídia

Criptografe os bytes de arquivo com a mesma chave de conversa usada para texto, faça upload pelas APIs de mídia de Chat e anexe media_hash_key em encrypt_message. Isso não é o modelo de mídia de Posts (expansions=attachments.media_keys). Fluxo completo de upload/download: Mídia.

Streaming incremental para mídia grande

Para arquivos grandes, evite manter o payload inteiro em memória: stream_encryptor() / stream_decryptor() retornam um StreamEncryptor / StreamDecryptor que você alimenta em chunks (cerca de 1 MB cada) com push(chunk) e depois chama finish() uma vez ao final. Na descriptografia, finish() detecta um stream truncado (falha se a entrada terminou antes do frame final), então não trate o texto simples empurrado como completo até que ele seja bem-sucedido.
Apenas JS/WASM: finish() consome e libera o objeto WASM subjacente — nunca chame free() depois de finish() (lança erro). Chame free() apenas para abandonar um stream antes de finalizar (por exemplo, em um caminho de erro).

Utilitários

Helpers de base64/hex, detecção de MIME e dimensões de imagem estão disponíveis como funções em nível de módulo (Python/JS/Rust/Go) ou ChatXdkUtilities (C#/Java) — úteis ao construir metadados de anexo sem trazer bibliotecas extras.

Tipos importantes

Estes tipos conceituais aparecem em todas as linguagens (os nomes exatos dos campos diferem; JS frequentemente usa discriminadores de evento em camelCase como message):
  • SendPayload — valor de retorno de encrypt_message e dos outros helpers de criptografia: o message_id gerado pelo SDK (um UUID incorporado no evento assinado — envie-o como message_id da mensagem e guarde-o para deduplicação), encrypted_content, encoded_event_signature, metadados da assinatura, conversation_key_version e should_notify. Mapeie para o corpo de envio da Chat API.
  • PublicKeyRegistrationPayload — saída de generate_keypairs / getters de chave pública para a API add-public-key.
  • SigningKeyEntry — material público do remetente passado para descriptografia para verificação de assinatura, ou armazenado via set_signing_keys.
  • PreparedConversationChange — saída dos três métodos prepare: o conversation_id derivado ou passado, os bytes brutos de conversation_key, conversation_key_version, participant_keys (user_id, encrypted_key, public_key_version) e action_signatures (message_id, encoded_message_event_detail, signature, signature_version, public_key_version, opcional signature_payload — omitido em assinaturas de mudança de chave porque esse payload incorpora a chave em texto claro).
  • DecryptEventsResult — mensagens, erros opcionais e conversation_keys extraídas. Mensagens descriptografadas que citam uma resposta trazem reply_preview_validation (veja Helpers de criptografia e envio).
Para listas completas de campos, use os stubs de linguagem no repositório chat-xdk (docs/API.md, *.pyi, index.d.ts).

Erros

Python normalmente lança ValueError com uma mensagem descritiva (por exemplo, um código de acesso inválido). TypeScript/JavaScript lança Error. Go retorna (value, error). Prefira decrypt_events para histórico, para que um evento ruim não aborte o lote; inspecione a coleção de erros para falhas parciais. Alguns erros de verificação são permanentes. Assinaturas são imutáveis e verificadas reconstruindo o payload assinado a partir do próprio evento, então um evento antigo que falha com signature missing or no matching signing key ou com um mismatch de ECDSA falhará em toda carga futura — nenhuma retentativa, atualização de chave ou chamada de API pode consertá-lo. Trate esses casos como tombstones, não como erros transitórios. Rotacionar a chave da conversa inicia um histórico limpo e verificável a partir desse ponto.

Próximos passos

Primeiros passos

Conecte o Chat XDK à Chat API

Mídia

Criptografia em stream e REST de mídia

Eventos em tempo real

Entrega via webhooks e activity

Solução de problemas

Falhas comuns