vaazhen/chaos-e2ee-messenger
GitHub: vaazhen/chaos-e2ee-messenger
一个基于 Spring Boot、React 与 Electron 构建的全栈实时端到端加密通讯应用,支持多设备加密消息收发、音视频通话信令与自托管部署。
Stars: 18 | Forks: 1
# Chaos Messenger
支持 Web 和桌面端的多设备端到端加密通讯应用。
React · Electron · Spring Boot · PostgreSQL · Redis · Kafka/Redpanda · Docker · Kubernetes
[俄语版本](README.ru.md) · [验证报告](VALIDATION_REPORT.md) · [安全审计](SECURITY_AUDIT_EN.md)
## 功能
- 单聊、群聊和保存的消息;
- 回复、编辑、删除、表态以及已读/已送达状态;
- 加密附件和阅后即焚消息;
- 输入状态、在线状态和 WebSocket 更新;
- 通过 WebRTC 进行音视频通话信令传输;
- 邮箱/密码和手机号认证;
- 活跃设备管理和基于设备的端到端加密 (E2EE) 投递;
- 支持加密备份;
- Web 客户端和 Electron 桌面客户端;
- Docker Compose、Kubernetes 清单和可观测性配置。
## 端到端加密
每个客户端设备都拥有独立的加密身份。客户端使用类似 X3DH 的预共享密钥交换机制建立会话,并使用基于 WebCrypto 的 Double Ratchet 实现来加密消息。
后端会接收并存储:
- 设备公钥和预共享密钥;
- 加密的消息信封;
- 加密的附件负载;
- 账户、设备、聊天和投递元数据。
后端不会接收消息明文或客户端私钥。
### 设备验证
对于每个远程设备,可以通过带外方式比对安全码。已验证的设备具有以下信任状态之一:
```
UNVERIFIED -> VERIFIED -> KEY_CHANGED
```
当先前已验证设备的身份密钥发生更改时,加密操作将被阻止,直到再次对该设备进行显式验证。
### 客户端密钥存储
私钥身份密钥、预共享密钥和棘轮会话作为加密的 IndexedDB 记录进行存储。包装密钥是不可提取的 WebCrypto 密钥。棘轮状态变更会在并发操作间进行串行化处理,以防止消息索引重用。
访问令牌保存在进程内存中。刷新令牌通过 `Secure`、`HttpOnly`、`SameSite=Strict` cookie 传递,并由后端进行轮换。
端到端加密无法保护已经被入侵的终端。在受信任域中运行的 JavaScript、恶意构建的应用程序、浏览器扩展或操作系统恶意软件,都可以在客户端运行时访问明文。
## 实时投递
当启用 Kafka 时,后端会使用事务性发件箱。设备事件会持久化保存,并附带一个单调递增的序列号。
重新连接后,客户端将:
1. 读取上次存储的游标;
2. 从 `/api/realtime/sync` 请求遗漏的事件;
3. 按顺序应用持久化事件;
4. 处理在恢复期间缓存的 WebSocket 事件;
5. 存储新的游标。
实时投递保证至少一次。事件包含一个 `eventId`,客户端会对重复投递进行去重。
## 架构
```
flowchart LR
WEB[React web client] --> EDGE[Caddy / Nginx / Ingress]
DESKTOP[Electron client] --> EDGE
EDGE --> API[Spring Boot backend]
API --> PG[(PostgreSQL)]
API --> REDIS[(Redis)]
API --> OUTBOX[Transactional outbox]
OUTBOX --> KAFKA[Kafka / Redpanda]
KAFKA --> REALTIME[Realtime consumer]
REALTIME --> EDGE
API --> ATTACHMENTS[(Encrypted attachment storage)]
API --> OBS[Actuator / Prometheus / Loki]
OBS --> GRAFANA[Grafana]
```
## 技术栈
| 层级 | 技术 |
|---|---|
| Web | React 18, Vite 5, WebCrypto, IndexedDB, STOMP/SockJS |
| 桌面端 | Electron 33, electron-builder |
| 后端 | Java 17, Spring Boot 3.5, Spring Security, JPA/Hibernate |
| 数据 | PostgreSQL 16, Redis 7, Flyway |
| 事件 | 兼容 Kafka 的代理 / Redpanda, 事务性发件箱 |
| 可观测性 | Actuator, Prometheus, Grafana, Loki, Promtail |
| 部署 | Docker Compose, Kubernetes/Kustomize, GitHub Actions |
## 快速开始
### 环境要求
- Docker Engine;
- Docker Compose v2;
- 至少 4 GB 的可用内存以运行完整的本地技术栈。
### 配置
```
cp .env.example .env
```
生成强密钥并替换所有 `CHANGE_ME` 的值:
```
openssl rand -base64 32 # POSTGRES_PASSWORD
openssl rand -base64 32 # REDIS_PASSWORD
openssl rand -base64 48 # JWT_SECRET
openssl rand -base64 32 # GRAFANA_ADMIN_PASSWORD
```
设置:
```
DOMAIN=localhost
CORS_ORIGINS=https://localhost
```
对于公共部署,请使用真实的 DNS 名称和匹配的 HTTPS 源。
### 运行
```
docker compose up --build -d
docker compose ps
docker compose logs -f backend frontend caddy
```
打开:
```
https://localhost
```
Caddy 会对本地名称使用其本地 CA,并为有效的公共域名获取公共 TLS 证书。
停止技术栈:
```
docker compose down
```
同时删除本地数据:
```
docker compose down -v
```
## 本地开发
### 后端
```
cd backend
./mvnw spring-boot:run
```
可以通过以下命令启动开发依赖项:
```
cd backend
docker compose -f docker-compose.dev.yml up -d
```
### 前端
```
cd frontend
npm ci
npm run dev
```
Vite 开发服务器会将 `/api` 和 `/ws` 代理到 `http://localhost:8080`。
## Electron
创建桌面端环境文件:
```
cd frontend
cp .env.electron.example .env.electron
```
设置绝对安全的 endpoint:
```
VITE_BACKEND_URL=https://messenger.example.com
VITE_API_BASE=https://messenger.example.com/api
VITE_WS_URL=wss://messenger.example.com/ws
```
构建:
```
npm run electron:build
```
当缺少必需的 endpoint 或使用不安全的协议时,构建将会失败。公共安装程序应进行代码签名;macOS 构建还应进行公证。
## 配置
主要环境变量:
| 变量 | 用途 |
|---|---|
| `POSTGRES_PASSWORD` | PostgreSQL 密码 |
| `REDIS_PASSWORD` | Redis 密码 |
| `JWT_SECRET` | JWT 签名密钥,至少 32 个字符 |
| `DOMAIN` | Caddy 使用的公共主机名 |
| `CORS_ORIGINS` | 精确受信任的前端源 |
| `CHAOS_DEMO_ENABLED` | 启用可选的演示 endpoint |
| `VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY` | Web Push 凭证 |
| `CHAOS_KAFKA_ENABLED` | 启用 Kafka/发件箱投递 |
| `KAFKA_BOOTSTRAP_SERVERS` | 兼容 Kafka 的代理地址 |
| `CHAOS_ATTACHMENTS_STORAGE_PATH` | 加密附件的存储路径 |
| `CHAOS_ATTACHMENTS_MAX_BYTES` | 加密附件的最大大小 |
有关完整的本地配置,请参见 `.env.example`、`backend/.env.example` 和 `frontend/.env.example`。
## 测试
### 后端
```
cd backend
./mvnw verify
```
### 前端
```
cd frontend
npm ci
npm run lint
npm test
npm run test:coverage
npm run build
```
打包的源代码已通过 **154 个通过的前端测试和 3 个特意跳过的测试**的检查。确切结果和环境限制记录在 [VALIDATION_REPORT.md](VALIDATION_REPORT.md) 中。
## Kubernetes
`k8s/` 目录包含:
- 命名空间和配置;
- 后端和前端的 Deployment/Service;
- Ingress;
- 资源请求和限制;
- 存活/就绪探针;
- 水平 Pod 自动扩缩容;
- PodDisruptionBudgets;
- 密钥模板。
在替换镜像名称、主机名和密钥值后执行应用:
```
kubectl apply -k k8s/
```
对于公共生产环境部署,请使用托管型或基于 Operator 的 PostgreSQL、Redis 和 Kafka,经过测试的备份/PITR、外部密钥管理以及独立的安全测试。
## 安全说明
- 不要提交 `.env` 文件或真实的凭证。
- 将 `/actuator` 和 Prometheus endpoint 保留在内部网络中。
- 仅通过 HTTPS 提供 Web 应用程序服务。
- 使用精确的 CORS 源;不要使用全局通配符。
- 通过密钥管理器轮换 JWT、数据库、Redis 和 VAPID 密钥。
- 在每次发布前运行后端测试套件、集成测试和数据库迁移。
- 在将该系统用于高风险通信之前,请获取独立的加密审查和渗透测试。
有关详细的安全和发布检查清单,请参见 [SECURITY_AUDIT_EN.md](SECURITY_AUDIT_EN.md) 和 [PRODUCTION_READINESS.md](PRODUCTION_READINESS.md)。
## 许可证
基于 [Apache License 2.0](LICENSE) 授权。标签:Electron, JS文件枚举, React, Spring Boot, Syscalls, WebRTC, 即时通讯, 子域名突变, 搜索引擎查询, 测试用例, 端到端加密, 自定义脚本, 自定义请求头, 请求拦截