You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Open-IM-Server/virgil_chat_server_design.md

10 KiB

Virgil Security 接入到聊天系统设计方案(服务器)

1. 服务器设计目标

服务端的目标不是参与解密,而是提供 业务承载层

  • 业务身份认证
  • 设备管理
  • Virgil JWT 签发
  • 单聊/群聊会话管理
  • 密文消息接入与路由
  • 离线同步
  • 文件上传/下载票据
  • 群成员关系与群密钥版本索引
  • 风控与设备吊销

2. 服务器总体架构

flowchart LR
    subgraph Backend["业务服务端"]
        B1["API Gateway"]
        B2["Auth Service"]
        B3["Virgil JWT Service"]
        B4["Conversation Service"]
        B5["Message Router / Sync"]
        B6["Group Service"]
        B7["Push Service"]
        B8["File Ticket Service"]
        B9["Risk / Device Service"]
        B10["Metadata DB"]
    end

    subgraph Virgil["Virgil Cloud"]
        V1["Cards / Public Key Directory"]
        V2["Restore Related Services"]
    end

    subgraph OSS["Object Storage / CDN"]
        O1["Encrypted File Objects"]
    end

    B1 --> B2
    B1 --> B3
    B1 --> B4
    B1 --> B5
    B1 --> B6
    B1 --> B8
    B1 --> B9

    B2 --> B10
    B3 --> B10
    B4 --> B10
    B5 --> B10
    B6 --> B10
    B8 --> O1
    B9 --> B10

    B3 --> V1
    B3 --> V2

3. 服务器职责边界

3.1 服务端应该负责什么

  • 用户登录与 token
  • 设备注册与吊销
  • Virgil JWT 签发
  • 会话与群组元数据
  • 密文消息存储
  • 消息序列号与游标
  • 离线消息投递
  • 已读/已送达状态
  • 文件票据
  • 群成员变更事件
  • 风控控制

3.2 服务端不应该负责什么

  • 私钥保存
  • 文本明文解析
  • 文件明文解析
  • 群密钥管理的明文操作
  • 替客户端做消息加解密

4. 推荐服务拆分

api-gateway
auth-service
virgil-jwt-service
conversation-service
message-service
group-service
sync-service
push-service
file-ticket-service
risk-device-service

各服务说明

api-gateway

  • 统一入口
  • 鉴权
  • 请求限流
  • trace 注入

auth-service

  • 登录
  • refresh
  • logout

virgil-jwt-service

  • 生成 Virgil JWT
  • user/device 到 virgil identity 的映射
  • 风控前置校验

conversation-service

  • 单聊会话
  • 会话设置
  • 会话列表

message-service

  • 接收密文 envelope
  • 分配 message_id / seq
  • 存储与 fanout

group-service

  • 创建群
  • 加人/踢人/退群
  • 群资料
  • 维护 group_key_version

sync-service

  • bootstrap
  • 增量消息
  • 群事件同步

push-service

  • message.new
  • message.recall
  • group.member_changed
  • device.revoked

file-ticket-service

  • 上传票据
  • 下载票据
  • 文件元信息

risk-device-service

  • 设备状态
  • 完整性校验
  • 风险拦截

5. 服务端数据模型

5.1 用户与设备

erDiagram
    USER ||--o{ DEVICE : owns
    USER {
      string user_id
      string status
      int64 created_at
    }
    DEVICE {
      string device_id
      string user_id
      string platform
      string device_model
      string app_version
      string virgil_identity
      string status
      int64 last_seen_at
    }

5.2 会话与消息

erDiagram
    CONVERSATION ||--o{ MESSAGE : contains
    CONVERSATION {
      string conversation_id
      string type
      string peer_key
      string group_id
      int64 created_at
    }
    MESSAGE {
      string message_id
      string conversation_id
      string chat_type
      string sender_user_id
      string sender_device_id
      string receiver_user_id
      string group_id
      int64 group_key_version
      string content_type
      int envelope_version
      string cipher_suite
      bytes ciphertext
      bytes signature
      int64 seq
      int64 server_timestamp
    }

5.3 群与群事件

erDiagram
    GROUP ||--o{ GROUP_MEMBER : has
    GROUP ||--o{ GROUP_KEY_EVENT : emits
    GROUP {
      string group_id
      string conversation_id
      string owner_user_id
      string name
      int64 group_key_version
      string status
    }
    GROUP_MEMBER {
      string group_id
      string user_id
      string role
      string status
      int64 join_version
      int64 leave_version
    }
    GROUP_KEY_EVENT {
      string event_id
      string group_id
      int64 group_key_version
      string event_type
      string operator_user_id
      int64 created_at
    }

6. 服务端接口设计

6.1 认证与设备

登录

POST /api/v1/auth/login

刷新 token

POST /api/v1/auth/refresh

登出

POST /api/v1/auth/logout

注册设备

POST /api/v1/devices/register

查询设备列表

GET /api/v1/devices

吊销设备

POST /api/v1/devices/{device_id}:revoke

6.2 Virgil JWT

获取 Virgil JWT

POST /api/v1/security/virgil-jwt

请求:

{
  "device_id": "ios_a1"
}

响应:

{
  "virgil_jwt": "virgil_jwt_xxx",
  "expires_in": 3600,
  "virgil_identity": "u_1001:ios_a1"
}

6.3 会话

创建/获取单聊

POST /api/v1/conversations/single

会话列表

GET /api/v1/conversations

会话详情

GET /api/v1/conversations/{conversation_id}

会话设置

POST /api/v1/conversations/{conversation_id}/settings

6.4 消息

发送消息

POST /api/v1/messages

批量发送

POST /api/v1/messages:batchSend

拉取指定消息

GET /api/v1/messages/{message_id}

撤回消息

POST /api/v1/messages/{message_id}:recall

仅自己删除

POST /api/v1/messages/{message_id}:deleteForMe

6.5 群组

创建群

POST /api/v1/groups

群详情

GET /api/v1/groups/{group_id}

群上下文

GET /api/v1/groups/{group_id}/context

群成员列表

GET /api/v1/groups/{group_id}/members

加人

POST /api/v1/groups/{group_id}/members:add

移除成员

POST /api/v1/groups/{group_id}/members:remove

退群

POST /api/v1/groups/{group_id}:leave

解散群

POST /api/v1/groups/{group_id}:dismiss

修改群资料

POST /api/v1/groups/{group_id}/profile

6.6 文件

申请上传票据

POST /api/v1/files/upload-ticket

上传完成

POST /api/v1/files/{file_id}:complete

获取下载票据

POST /api/v1/files/{file_id}/download-ticket

获取文件元信息

GET /api/v1/files/{file_id}

6.7 同步

冷启动 bootstrap

GET /api/v1/sync/bootstrap

增量消息同步

GET /api/v1/sync/messages

群事件同步

GET /api/v1/sync/group-events

6.8 回执与状态

已送达/已读

POST /api/v1/messages/ack

批量已读

POST /api/v1/conversations/{conversation_id}:markRead

输入中

POST /api/v1/conversations/{conversation_id}/typing

6.9 风控与安全

预检查

POST /api/v1/security/precheck

设备完整性上报

POST /api/v1/security/integrity-report

7. 服务端核心流程

7.1 签发 Virgil JWT

sequenceDiagram
    participant C as 客户端
    participant J as Virgil JWT Service
    participant A as Auth Service
    participant R as Risk / Device Service

    C->>J: /security/virgil-jwt
    J->>A: 校验 access_token
    A-->>J: 用户有效

    J->>R: 校验 device_id / 风险状态
    R-->>J: 允许或拒绝

    J-->>C: 返回 virgil_jwt

7.2 消息接收与路由

sequenceDiagram
    participant C as 客户端
    participant M as Message Service
    participant S as Sync Service
    participant P as Push Service
    participant DB as Metadata DB

    C->>M: POST /messages
    M->>DB: 存储 envelope
    M->>DB: 分配 message_id / seq
    M->>S: 写离线同步流
    M->>P: 触发新消息推送
    M-->>C: 返回 accepted

7.3 群成员变更

sequenceDiagram
    participant A as 管理员客户端
    participant G as Group Service
    participant DB as Metadata DB
    participant S as Sync Service
    participant P as Push Service

    A->>G: /groups/{id}/members:add
    G->>DB: 更新群成员
    G->>DB: group_key_version + 1
    G->>S: 写入 group event
    G->>P: 推送 group.member_changed
    G-->>A: 返回最新 group_key_version

8. 服务端幂等与校验

8.1 幂等设计

发消息幂等键

推荐:

sender_user_id + sender_device_id + client_message_id

创建群幂等

推荐使用:

Idempotency-Key: <uuid>

8.2 消息接口校验项

  • 当前用户是会话参与者
  • sender_device_id 属于当前用户
  • 单聊的 receiver_user_id 与会话匹配
  • 群聊的 group_id 与会话匹配
  • 当前用户是群成员
  • group_key_version 合法
  • ciphertext 长度不超过限制

8.3 Virgil JWT 接口校验项

  • 业务 token 有效
  • device_id 属于当前用户
  • 设备状态为 active
  • 未被吊销
  • 风控未阻断

9. WebSocket / 推送事件建议

WebSocket 事件

  • message.new
  • message.recall
  • message.ack
  • group.member_changed
  • group.profile_changed
  • device.revoked
  • security.force_logout

推送原则

推送中不要放消息明文,建议只放:

  • 会话 ID
  • 发送方昵称
  • 占位提示

10. 服务端风险点

  • 若服务端误记录明文日志,会破坏 E2EE 边界
  • 若文件下载链接长期有效,文件密文泄露面会扩大
  • 若群成员变更后未提升 group_key_version,客户端可能使用旧上下文
  • 若被吊销设备仍可获取 Virgil JWT会造成安全失控
  • 若推送带明文,会绕过加密链路

11. 推荐实施路径

阶段 1单聊 MVP

实现:

  • 登录
  • Virgil JWT
  • 单聊消息发送
  • 增量同步
  • 已读回执

阶段 2群聊

实现:

  • 创建群
  • 群成员管理
  • group_key_version
  • 群事件同步

阶段 3文件与恢复

实现:

  • 文件票据
  • 加密文件上传下载
  • 新设备恢复
  • 风控增强

12. 服务器总结

服务器在 Virgil Security 接入中的核心定位是:

  • 不参与消息解密
  • 不保存私钥
  • 只处理密文、元数据和业务控制逻辑

具体来说,服务器负责:

  • 身份认证
  • 设备管理
  • Virgil JWT 签发
  • 密文消息接入、存储、路由
  • 会话与群成员关系
  • 文件票据
  • 同步与推送
  • 风控和设备吊销

这样才能既保留现有聊天系统的业务能力,又维持端到端加密的安全边界。