feat(e2e): 端对端加密完全对齐老项目 — cipher_guard_sdk 修正 + EncryptionManager 集成
Some checks failed
CI / Lint (push) Has been cancelled

修正 cipher_guard_sdk 4 个关键密码学差异使其与老 Flutter 项目 (im-client-im-dev) 和 iOS
EncryptionManager 完全互操作:

1. AES: 显式 SIC/CTR 模式 + 16 zero-byte IV(原 SDK 用随机 IV + KDF 派生密钥)
2. RSA: bare RSAEngine 无 PKCS1 padding(原 SDK 用 PKCS1Encoding)
3. Session key: 32-char alphanumeric ASCII(原 SDK 用 base64 random bytes)
4. Wire format: base64(ciphertext) 无 IV 前缀

新增 EncryptionManager:
- Per-chat round-based key chain(最多 10 rounds/chat,FIFO 淘汰)
- 登录后自动 setup:RSA 密钥对生成/存储 + 公钥上传 + chat 密钥拉取解密
- API 集成:cipher/v2/key/my, key/set, chat/my
- 消息加密返回 JSON envelope {"round":N,"data":"<base64>"}
- 消息解密兼容 JSON envelope + legacy raw base64

集成到消息流:
- SendMessageUseCase: 发送前加密 content → wireContent
- WsMessageService: 收到消息后解密 content + lastMsg
- 无密钥时 fallback 到明文(对齐 iOS 行为)

注意:/app/api/cipher/v2/key/set 仍为预发布接口,仅测试阶段使用

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
pp-bot
2026-04-14 21:44:00 +09:00
parent e8f58212e6
commit 52a3f0f45c
18 changed files with 1307 additions and 367 deletions

View File

@@ -69,6 +69,7 @@ final wsMessageServiceProvider = Provider<WsMessageService>((ref) {
messageRepo: ref.read(messageRepositoryProvider),
chatRepo: ref.read(chatRepositoryProvider),
typingManager: ref.read(typingIndicatorManagerProvider),
encryptionManager: ref.read(encryptionManagerProvider),
);
service.start();
@@ -91,6 +92,7 @@ final sendMessageUseCaseProvider = Provider<SendMessageUseCase>((ref) {
messageRepo: ref.read(messageRepositoryProvider),
chatRepo: ref.read(chatRepositoryProvider),
currentUid: uid,
encryptionManager: ref.read(encryptionManagerProvider),
);
});

View File

@@ -1,6 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:networks_sdk/networks_sdk.dart';
import 'package:im_app/core/services/encryption_manager.dart';
import 'package:im_app/data/remote/send_message_request.dart';
import 'package:im_app/domain/entities/message.dart';
import 'package:im_app/domain/repositories/chat_repository.dart';
@@ -25,6 +26,7 @@ class SendMessageUseCase {
final NetworksSdkApi _apiClient;
final MessageRepository _messageRepo;
final ChatRepository _chatRepo;
final EncryptionManager? _encryptionManager;
final int currentUid;
SendMessageUseCase({
@@ -32,9 +34,11 @@ class SendMessageUseCase {
required MessageRepository messageRepo,
required ChatRepository chatRepo,
required this.currentUid,
EncryptionManager? encryptionManager,
}) : _apiClient = apiClient,
_messageRepo = messageRepo,
_chatRepo = chatRepo;
_chatRepo = chatRepo,
_encryptionManager = encryptionManager;
Future<void> execute({
required int chatId,
@@ -56,13 +60,25 @@ class SendMessageUseCase {
),
);
// 2. HTTP 发送
// 2. E2E 加密(对齐 iOS MessageHistoryService.sendMessage
// wireContent = EncryptionManager.encryptContent(content, chatId) ?? content
String wireContent = content;
if (_encryptionManager != null && _encryptionManager.isSetup) {
final encrypted =
await _encryptionManager.encryptContent(content, chatId: chatId);
if (encrypted != null) {
wireContent = encrypted;
}
// null = no key for chat → send plaintext (对齐老项目 fallback)
}
// 3. HTTP 发送
SendMessageResponse? resp;
try {
resp = await _apiClient.executeRequest(
SendMessageRequest(
chatId: chatId,
content: content,
content: wireContent,
typ: typ,
sendTime: sendTime,
),