Skip to main content
그룹 채팅은 1:1 X Chat과 동일한 암호화 모델을 사용합니다: 멤버가 공유하는 하나의 대화 키를 각 멤버의 신원 공개 키로 래핑하고, Chat XDK가 메시지를 암호화하고 서명합니다. 달라지는 것은 멤버십, 대화를 생성하는 방식, 그리고 흔히 대화의 암호화된 제목/아바타 필드입니다. 1:1 흐름은 시작하기에 있습니다. 엔드포인트 세부 사항은 API 참조 → 대화 및 메시지 아래에 있습니다.

그룹과 1:1의 차이점

암호화는 여전히: 키와 페이로드에는 Chat XDK를, 그룹 생성, 참가자 키 래핑 게시, 메시지 전송, 이벤트 로드에는 X API를 사용합니다.

그룹 생성 및 키 설정

  1. POST /2/chat/conversations/group/initialize로 그룹 ID를 발급받습니다 — 응답의 data.conversation_id가 이후 모든 곳에서 사용하는 g-접두사 ID입니다.
  2. 각 멤버의 신원 공개 키와 public_key_version을 로드합니다 (암호화 키 아래 GET 공개 키 경로; GET /2/users/public_keys는 한 요청으로 여러 사용자를 가져옴). 사용하기 전에 verify_key_binding으로 각 레코드를 검증하세요 (시작하기의 경고 참조).
  3. 모든 멤버(자신 포함), g-접두사 ID, 멤버/관리자 ID 목록으로 **prepare_group_create**를 한 번 실행합니다. 한 번의 호출로 대화 키를 생성하고, 모든 멤버에게 래핑하고, set_identity의 세션 신원으로 생성에 서명합니다 — 두 개의 action signature(대화 키 변경과 그룹 생성)를 반환합니다.
  4. 그룹 멤버/관리자, conversation_key_version, conversation_participant_keys(SDK encrypted_key → API encrypted_conversation_key), 그리고 두 개 모두action_signatures와 함께 POST /2/chat/conversations/group을 호출합니다. 검증 실패는 안정적이고 사람이 읽을 수 있는 메시지로 반환됩니다. 예: "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에 전달한 것과 바이트 단위로 동일해야 합니다 — 그렇지 않으면 호출이 서명 검증에 실패합니다.
참가자 키와 action signature의 본문 매핑(message_id, encoded_message_event_detail, 중첩된 message_event_signature)은 시작하기 — 대화 키의 키 POST와 동일합니다. 멤버십이 변경되면, 새 멤버 ID와 함께 현재 로스터(멤버, 관리자, 대기 중인 멤버, 설정된 경우 현재 제목/아바타/TTL)를 사용해 **prepare_group_members_change**를 호출하세요. 대화 키를 교체하며, 그룹 생성처럼 두 개의 action signature를 반환합니다 — 모두 멤버 추가(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과 동일합니다:
  • 전송: encrypt_message → 메시지 전송 API (시작하기)
  • 수신: 이벤트 API 또는 실시간 전달decrypt_event / decrypt_events
  • 미디어: 그룹 대화 ID와 함께 미디어
멤버십 기반 교체 이후에는 항상 최신 키 버전으로 암호화하세요.

떠난 멤버로 인한 키 변경

그룹의 키 변경 이벤트는 이를 수행한 사람 — 종종 생성자나 관리자 — 이 서명합니다. 그 멤버가 이후에 그룹을 떠나거나(또는 계정을 비활성화하면), 공개 키 엔드포인트가 그들의 키 반환을 중단하므로 검증된 복호화 경로(서명 키를 사용한 decrypt_events)는 해당 키 변경 이벤트에서 signature missing or no matching signing key로 실패합니다. 이벤트가 손상된 것이 아니라, 검증 자료가 더 이상 제공되지 않을 뿐입니다. 수명이 긴 그룹은 이를 예상하고, 검증할 수 없는 키 변경 이벤트에 대해서는 **extract_conversation_keys**로 폴백해야 합니다. 이 경로는 서명 검사를 건너뛰고, 당신의 신원 키로 복호화하여 대화 키를 복구합니다. 다음 이유로 보안 모델은 유지됩니다:
  • 당신의 신원 키로 암호화된 키 자료만 복구할 수 있습니다 — 제3자가 당신이 읽을 수 있는 키를 주입할 수 없습니다
  • 모든 메시지는 여전히 각 발신자에 대해 서명 검증되므로, 메시지 작성자 정보에는 영향이 없습니다
검증된 경로를 우선하세요: decrypt_events(set_cache_keys(true)가 활성화된 경우 SDK의 키 캐시에도 공급됨)를 사용하고, 그것이 거부한 키 변경 이벤트에 대해서만 extract_conversation_keys를 사용하세요.

체크리스트

  1. POST /2/chat/conversations/group/initialize로 g-접두사 ID를 발급받습니다
  2. 모든 멤버로 prepare_group_create를 호출; 참가자 키 래핑과 두 개 모두의 action signature를 POST /2/chat/conversations/group에 POST
  3. 원시 키 + 버전을 캐시; 키 변경 이벤트 시 업데이트
  4. 멤버십 변경 시 prepare_group_members_change(두 개의 서명) → POST /2/chat/conversations/{id}/members
  5. 필드가 암호문일 때 decrypt로 그룹 메타데이터를 복호화
  6. 1:1과 동일한 패턴으로 송수신