feat(e2e): 端对端加密完全对齐老项目 — cipher_guard_sdk 修正 + EncryptionManager 集成
Some checks failed
CI / Lint (push) Has been cancelled
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:
@@ -1,8 +1,10 @@
|
||||
import 'package:cipher_guard_sdk/cipher_guard_sdk.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:im_app/core/foundation/device_info.dart';
|
||||
import 'package:im_app/core/services/app_initializer.dart';
|
||||
import 'package:im_app/core/services/encryption_manager.dart';
|
||||
import 'package:im_app/app/di/network_provider.dart';
|
||||
|
||||
// ── 认证 ──────────────────────────────────────────────────────────────────────
|
||||
@@ -26,32 +28,60 @@ class AuthNotifier extends ChangeNotifier {
|
||||
/// 登录用户的 UID,登录成功后由 LoginViewModel 写入
|
||||
int? get currentUid => _currentUid;
|
||||
|
||||
/// E2E EncryptionManager — 由外部注入(见 LoginViewModel)
|
||||
EncryptionManager? _encryptionManager;
|
||||
NetworksSdkApi? _api;
|
||||
|
||||
void setEncryptionDeps(EncryptionManager encMgr, NetworksSdkApi api) {
|
||||
_encryptionManager = encMgr;
|
||||
_api = api;
|
||||
}
|
||||
|
||||
void login({required int uid}) {
|
||||
_isLoggedIn = true;
|
||||
_currentUid = uid;
|
||||
// TODO: 接入 cipher_guard_sdk 后,在此处完成 RSA 密钥注入:
|
||||
// 1. 从安全存储(keychain / secure storage)读取公私钥对(只读一次)
|
||||
// 2. cipherSdk.setActiveKeyPair(publicKey: pubPem, privateKey: privPem)
|
||||
// 须在 notifyListeners() 之前完成,确保路由跳转后 onEncryptRequest 回调触发时密钥已就绪。
|
||||
notifyListeners();
|
||||
// E2E setup: 对齐 iOS AppCoordinator.onLogin → EncryptionManager.setup()
|
||||
if (_encryptionManager != null && _api != null) {
|
||||
_encryptionManager!.setup(_api!);
|
||||
}
|
||||
}
|
||||
|
||||
void logout() {
|
||||
_isLoggedIn = false;
|
||||
_currentUid = null;
|
||||
// TODO: 接入 cipher_guard_sdk 后,退出登录时清除内存密钥:
|
||||
// cipherSdk.clearActiveKeyPair()
|
||||
// cipherSdk.clearDerivedKeyCache()
|
||||
// E2E teardown: 清除所有加密密钥
|
||||
_encryptionManager?.clearKeys();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// 登录状态 Provider
|
||||
///
|
||||
/// 使用 [Provider] 持有 [AuthNotifier] 单例。
|
||||
/// go_router 通过 [GoRouter.refreshListenable] 直接监听 [AuthNotifier](ChangeNotifier),
|
||||
/// Riverpod 侧不需要响应式更新(导航由 go_router 接管)。
|
||||
final authNotifierProvider = Provider<AuthNotifier>((ref) => AuthNotifier());
|
||||
/// 自动注入 EncryptionManager + API client,login() 后自动触发 E2E setup。
|
||||
final authNotifierProvider = Provider<AuthNotifier>((ref) {
|
||||
final auth = AuthNotifier();
|
||||
auth.setEncryptionDeps(
|
||||
ref.read(encryptionManagerProvider),
|
||||
ref.read(networkSdkApiProvider),
|
||||
);
|
||||
return auth;
|
||||
});
|
||||
|
||||
// ── E2E 加密 ────────────────────────────────────────────────────────────────
|
||||
|
||||
/// CipherGuardSdkApi 单例 — 对齐老项目加密引擎
|
||||
final cipherSdkProvider = Provider<CipherGuardSdkApi>((ref) {
|
||||
return CipherGuardSdkApi();
|
||||
});
|
||||
|
||||
/// EncryptionManager 单例 — per-chat key chain + API integration
|
||||
///
|
||||
/// 登录后调用 `encMgr.setup(api)` 启动 E2E,退出时调用 `encMgr.clearKeys()`。
|
||||
/// 对齐 iOS EncryptionManager + 老项目 EncryptionMgr。
|
||||
final encryptionManagerProvider = Provider<EncryptionManager>((ref) {
|
||||
return EncryptionManager(cipherSdk: ref.read(cipherSdkProvider));
|
||||
});
|
||||
|
||||
// ── 主题 ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user