安全、加密与隐私边界
本页描述当前源码可确认的防护、数据可见性和已知实现边界。它不是独立安全审计报告,也不表示生产部署、客户端权限、外部依赖或端到端安全已经全部验收。维护者应以实际构建、配置回读和完整双设备路径的结果更新状态。
登录与凭据分层
Account 负责账号身份与授权,聊天服务负责业务会话。原生登录有 App→聊天服务的 S256 proof 和聊天服务→Account 的 S256 PKCE;state 与一次性 ticket 绑定,ticket 有效期 60 秒,聊天会话默认 24 小时。App 不需要存储机密 OIDC 客户端 secret。正式回调为 https://chat.thestarline.cn/auth/callback,自定义 scheme 只接收受 proof 约束的一次性 ticket。
服务端仅保存 state、ticket 和聊天 token 的 SHA-256 摘要,业务请求按未过期 token 摘要鉴权;原始 token 仍是持有即授权的凭据,客户端和日志系统须保护。原生回调需验证 scheme、host、state、参数唯一性和到期时间。仅仅“浏览器打开了 Account 页面”不算登录完成。
iOS 使用 Keychain 的 AfterFirstUnlockThisDeviceOnly 保存会话和原生授权待完成状态。Android 使用 Keystore 支持的本地加密存储。设备安全存储与服务器端会话到期是互补措施,设备已解锁、恶意软件、屏幕录制、系统备份和权限边界仍需单独评估。/auth/logout 成功时只撤销当前聊天 session,不等于所有 Account 登录和其他设备都已撤销。两端退出均会清除本机状态并忽略远端退出失败,网络失败时旧 session 可能继续有效直至到期;Account 改密码或撤销其自身会话没有自动联动撤销聊天 session 的实现。
服务端权限是核心约束
每个聊天资源都先验证 Bearer 用户,再检查会话双方、群当前成员或内容可见性。单聊发送、发起或接听通话、开始或更新位置、MLS 准备与应用事件等还会检查好友和任一方向屏蔽。群主权限用于邀请、改名、移除和解散,不能仅靠隐藏客户端按钮实现。
媒体下载要求所有者或可见消息授权;新事下载要求所有者或可见帖子授权。不可见资源通常使用 404 避免直接返回内容。普通单聊历史媒体的可见消息授权不重新检查is_friend或block,删好友/屏蔽不保证撤销原来仍可见的媒体;群消息授权分支要求当前成员,但所有者下载分支独立。不要把发送限制当历史读取限制。依据:chat-service/src/database.mjs:239-254。星企企业接口按组织成员、管理员与所有者执行独立检查,个人聊天身份不能绕过组织边界。返回 401、403、404、409 的具体语义见API 参考。
哪些数据是服务端可读的
| 数据 | 当前实现 |
|---|---|
| 普通聊天正文、附件与贴纸 | 正文与原始媒体 BLOB 在服务端保存;主聊天链路尚未全量改用 MLS |
| MLS application 内容 | 已建立并激活的 MLS 范围存储应用密文;设备负责解密与发送者验证 |
| 新事文字、图片、视频、评论 | 服务端可读,依赖访问控制和可见范围 |
| 实时位置 | 经度、纬度、精度与时间在服务端可读保存 |
| 个人资料联系电话 | 服务端 AES-256-GCM 加密保存;按可见性解密返回 |
| 手机号查找索引 | HMAC-SHA256 摘要,登录后有效期 24 小时 |
| 来电推送 | 通话、聊天范围、模式、来电人名称及可选群名;不含聊天正文和媒体凭证 |
HTTPS 保护传输,磁盘加密保护本地存储,服务端加密保护特定字段,MLS 保护特定会话内容;它们的信任主体不同。当前不能把普通附件、实时位置、新事、通话媒体统称为端到端加密。代码中的上传接口没有客户端附件密钥、密文封装或附件解密协议。
MLS 的已实现约束
Rust 核心使用 OpenMLS,固定 MLS 1.0 与 X25519、AES-128-GCM、SHA-256、Ed25519 对应的固定套件。服务端校验密钥包的协议、签名、套件以及账号/设备身份,已注册设备不能静默改签名公钥;密钥包使用一次性领取标记。服务端解析消息类型与群 ID,终端负责 MLS 消息验证、解密和发送者身份核对,服务端格式校验不能代替终端认证。
iOS 独立传输器在首次见到设备时固定签名公钥,已知设备换钥时拒绝继续;解密所得发送者与服务端 user/device 元数据不一致时失败。此为代码中的信任固定机制,不能据此宣称已经提供可供用户线下核对的完整安全号码体验或第三方目录透明性。
设备或成员变化使现有加密范围 blocked,服务端暂停应用密文发送;新 Commit、必要 Welcome 和确认完成后才激活。preparing/active/blocked 范围禁止旧明文发送接口。加密状态丢失时不得静默生成新密钥假装旧设备,也不得跳过失败的消息来推进 sequence。
Rust 状态快照使用 AES-256-GCM、随机 nonce 和固定附加认证数据封装,iOS 还将游标、待发密文、邀请与确认纳入加密 checkpoint;封装密钥存入设备安全存储。原生文件写入使用临时文件、同步与替换流程。恢复校验失败表示状态不可用,不能把它显示成“没有聊天记录”。这些机制仍需结合断电、进程中断、设备迁移和回滚测试验收。
个人资料、新事和位置控制
资料手机号可见范围为 private、selected、friends、everyone;everyone 仍是已登录聊天 API 用户。指定用户必须为当前好友,最多 100 位,双方屏蔽后不可通过这些规则获取手机号。可展示联系电话与 Account 已验证手机号查找索引不同,修改资料不等于修改 Account 安全手机号。
新事的 friends、selected、public、private 在每次读取时结合当前好友、屏蔽和个人隐藏判定,public 仍需要登录。点赞、评论和通知会产生参与关系元数据。隐藏新事、删除个人消息、删除个人聊天和解散群的语义不同;个人视图隐藏不承诺数据库、备份或另一端同时擦除。
实时位置必须显式开始,客户端应允许停止并说明系统位置权限。位置表没有自动到期字段,界面要呈现最后更新时间;用户停止本机定位采集与服务器删除共享记录是两个需要协调的动作。IP 城市只返回粗略结果,可信代理只接受 allowlist 中上游覆盖的单个 X-Real-IP,不能把任意 X-Forwarded-For 当可信地址。
输入限制、日志和公开资料
JSON 默认最大 16 KiB,不同媒体与加密接口有专用上限;普通上传、贴纸数量、账号空间、新事媒体、查找和识别分别受限。文字长度、规范 base64、文件名和 MIME 校验能减少异常输入,但文件头检查不等于恶意文件扫描,当前文档不承诺存在未实现的病毒扫描或内容安全服务。
公开文档仅发布接口契约与合成示例,不发布真实 token、客户端 secret、APNs/LiveKit 凭据、用户资料、数据库、附件、服务器地址或私有部署位置。机器人可索引文档不代表业务 API 免鉴权,也不授权访问个人数据。排错时使用错误码、请求阶段和已脱敏时间线,避免记录 verifier、票据、访问令牌、授权码和推送 token。
当前验收范围
可以确认的是源码中的路由、状态、输入限制、权限与加密实现。当前主聊天尚未全量接入 MLS,Android 未见同等 MLS 发送链路;真实跨网络音视频、后台系统来电和生产 APNs 仍需独立验收。当前权威 Account 主源码没有记忆转出 redeem 路由;App 工作树中的历史副本包含实现,也不能据此认定当前服务支持。安全承诺应以这些边界为准,测试依据见测试,运营配置见运维。