Skip to main content
グループチャットは 1:1 の X Chat と同じ暗号化モデルを使用します:1 つの会話鍵をメンバーで共有し、各メンバーのアイデンティティ公開鍵でラップし、Chat XDK によってメッセージを暗号化・署名します。変わるのはメンバーシップ会話の作成方法、そしてしばしば会話上の暗号化されたタイトル/アバターフィールドです。 1:1 のフローははじめににあります。エンドポイントの詳細は API リファレンス → Conversations and messages にあります。

グループが 1:1 と異なる点

暗号処理は変わりません:鍵とペイロードには Chat XDK、グループの作成、参加者向け鍵ラップの公開、メッセージの送信、イベントのロードには X API

グループを作成して鍵を確立する

  1. POST /2/chat/conversations/group/initialize でグループ ID を発行します——レスポンスの data.conversation_id が、以降どこでも使う g プレフィックス付きの ID です。
  2. 各メンバーのアイデンティティ公開鍵と public_key_version をロードします(Encryption keys の下の公開鍵 GET ルート。GET /2/users/public_keys は複数のユーザーを 1 回のリクエストで取得します)。使用前に各レコードを verify_key_binding で検証してください(はじめに の警告を参照)。
  3. prepare_group_create を、すべてのメンバー(自分自身を含む)、g プレフィックス付きの ID、メンバー/管理者の ID リストとともに一度実行します。この 1 回の呼び出しで会話鍵を生成し、すべてのメンバー向けにラップし、set_identity からのセッションアイデンティティで作成に署名します——2 つのアクション署名を返します(会話鍵の変更とグループ作成)。
  4. POST /2/chat/conversations/group に、グループメンバー/管理者、conversation_key_versionconversation_participant_keys(SDK の encrypted_key → API の encrypted_conversation_key)、および 両方の action_signatures を渡します。検証失敗は安定した人間可読メッセージとして返されます。例:"Too many members: adding these members would exceed the allowed group size.""Cannot add all members: one or more of the requested members cannot be added to this conversation." など。
  5. 暗号化/復号のために生の会話鍵とバージョンを保持します。
prepare_group_create は渡した titleavatar_url に署名し、それらをグループ作成イベントに逐語的に埋め込みます。サーバーはそれらをリクエストと照合するので、POST ボディの group_name / group_avatar_url の値は SDK に渡したものとバイト単位で同一でなければなりません——さもないと署名検証で呼び出しが失敗します。
参加者鍵とアクション署名(message_idencoded_message_event_detail、ネストされた message_event_signature)のボディマッピングは、はじめに — 会話鍵 の keys POST と同じです。 メンバーシップが変わるときは、新しいメンバー ID と現在の名簿(メンバー、管理者、保留中のメンバー、および現在のタイトル/アバター/TTL が設定されていればそれら)とともに prepare_group_members_change を呼び出します。会話鍵をローテーションし、グループ作成と同様に2 つのアクション署名を返します——すべてを add members(POST /2/chat/conversations/{id}/members)に POST してください。その後、鍵変更トラフィックが来ることを想定してください:はじめにの鍵ローテーションと同じように扱ってください(extract_conversation_keys / decrypt_events、その後に最新バージョンで暗号化)。 prepare_group_members_change は渡した名簿にのみラップされた新しい会話鍵を生成するため、新規メンバーは新しい鍵バージョンを受け取り、以前のバージョンで送られたメッセージを復号することはできません。逆は成り立ちません:ローテーションは以前のバージョンへのアクセスを取り消しません——古い鍵を既に持っている人は誰でも、その鍵で暗号化されたメッセージを引き続き読めます。会話鍵が漏えいした疑いがある場合は prepare_conversation_key_change でローテーションしてください。これは将来のメッセージのみを保護します。

暗号化されたグループメタデータ

一部の会話フィールド(たとえば表示アバター URL)は会話鍵で暗号化されたまま届く場合があります。これは encrypt_message ではなく、Chat XDK の汎用 encrypt / decrypt ペアです(UTF-8 文字列を入力、base64 暗号文を出力、生の会話鍵を使用)。 あるフィールドが暗号化されて保存されるかどうかは、それを書き込むクライアントが決定します:prepare_group_create はあなたが渡したタイトルをそのまま署名して送信します(会話鍵はその呼び出しが生成するまで存在しないので、作成時のタイトルはその鍵で暗号化できません)。フィールドが暗号文になっている会話を読むときは、そのフィールドが書き込まれた時点で有効だった鍵バージョンで decrypt を使って復号してください。
そのメタデータに該当する現在の会話鍵バージョンを使用してください。鍵がローテーションされている場合は、フィールドが書き込まれた時点で有効だった鍵バージョンで復号してください(あるいはメタデータがローテーション時に常に書き直されるならプロダクトのルールに従ってください)。

メッセージとイベント

生の会話鍵を持っていれば、グループでの送受信は 1:1 と同じです。 メンバーシップ由来のローテーション後は、常に最新の鍵バージョンで暗号化してください。

チェックリスト

  1. POST /2/chat/conversations/group/initialize で g プレフィックス付きの ID を発行する
  2. すべてのメンバーで prepare_group_create。参加者鍵ラップと両方のアクション署名を POST /2/chat/conversations/group に POST する
  3. 生の鍵 + バージョンをキャッシュし、鍵変更イベントで更新する
  4. メンバーシップ変更時は prepare_group_members_change(2 つの署名)→ POST /2/chat/conversations/{id}/members
  5. フィールドが暗号文の場合はグループメタデータを decrypt で復号する
  6. 送受信は 1:1 と同じパターンで行う