djx-y-z/openmls_dart

GitHub: djx-y-z/openmls_dart

OpenMLS 的 Dart 绑定库,为 Flutter 和跨平台应用提供符合 RFC 9420 标准的可扩展端到端加密群组消息传递能力。

Stars: 9 | Forks: 4

# openmls - 适用于 Dart 的 MLS 协议 [![pub package](https://img.shields.io/pub/v/openmls.svg)](https://pub.dev/packages/openmls) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/09/097271ca091990be630ef6043309cc48240faa054413384202036fa2efedb2d2.svg)](https://github.com/djx-y-z/openmls_dart/actions/workflows/test.yml) [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/djx-y-z/a5b2cf3b4ecf95155f76512df95d74c2/raw/coverage.json)](https://gist.github.com/djx-y-z/a5b2cf3b4ecf95155f76512df95d74c2) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Dart](https://img.shields.io/badge/dart-%3E%3D3.10.0-brightgreen.svg)](https://dart.dev) [![Flutter](https://img.shields.io/badge/flutter-%3E%3D3.38.0-blue.svg)](https://flutter.dev) [![openmls](https://img.shields.io/badge/openmls-v0.8.1-orange.svg)](https://github.com/openmls/openmls) [OpenMLS](https://github.com/openmls/openmls) 的 Dart 绑定,提供用于安全群组消息传递的消息层安全协议 ([RFC 9420](https://www.rfc-editor.org/rfc/rfc9420.html)) 的 Rust 实现。 ## 平台支持 | | Android | iOS | macOS | Linux | Windows | Web | |-------------|---------|-------|--------|------------|---------|-----| | **支持情况** | SDK 24+ | 13.0+ | 10.15+ | arm64, x64 | x64 | WASM | | **架构** | arm64, armv7, x64 | arm64 | arm64, x64 | arm64, x64 | x64 | wasm32 | ## 功能特性 - **MLS 协议 (RFC 9420)**:提供前向安全和后向安全的安全群组消息传递 - **群组密钥协商**:高效的基于树的群组密钥协商 (TreeKEM) - **后量子 (实验性)**:混合 X-Wing 密码套件 (ML-KEM-768 + X25519) — 请参阅 [后量子支持](#post-quantum-support-experimental) - **加密存储**:所有 MLS 状态均处于静态加密 — 原生平台使用 SQLCipher,WASM 使用 Web Crypto AES-256-GCM - **Basic 与 X.509 凭证**:支持这两种凭证类型 - **Flutter 与 CLI 支持**:适用于 Flutter 应用和独立的 Dart CLI 应用程序 - **自动构建**:通过构建钩子自动下载原生库 - **高性能**:通过 Flutter Rust Bridge 直接与 Rust 集成 ## 后量子支持 (实验性) `MlsCiphersuite.mls256XwingChacha20Poly1305Sha256Ed25519` 密码套件使用 **X-Wing** 混合 KEM ([draft-connolly-cfrg-xwing-kem](https://datatracker.ietf.org/doc/draft-connolly-cfrg-xwing-kem/)): ML-KEM-768 与 X25519 相结合,因此只要 *任一* 组件保持未被攻破,群组密钥就是保密的。它可以防范“现在收集,以后解密” (harvest-now-decrypt-later) 的攻击。 该套件的 HPKE 操作运行在 [libcrux](https://github.com/cryspen/libcrux) 上(经过形式化验证的 ML-KEM);所有经典套件继续在 RustCrypto 上保持不变地运行。 **使用前必读 — 诚实的局限性:** - **实验性,未标准化。** 该密码套件值 (0x004D) **未在 IANA 注册**,并且源自已过期的个人草案。IETF MLS 工作组正在标准化 *不同的* 后量子套件;当官方套件发布时,使用 X-Wing 的群组将需要进行迁移。我们将追踪官方套件并提供迁移方案。 - **互操作性有限。** 只有基于 OpenMLS 的技术栈(以及 ts-mls)支持此套件。请在所有客户端都使用此库或 OpenMLS 的封闭式部署中使用它 — 不适用于跨供应商的联合部署。 - **libcrux 版本低于 1.0 且未完全经过审计。** 它的 ML-KEM 源码已经过形式化验证(hax/F*:正确性、密钥独立性和抗 panic 特性),但编译后的二进制文件不包含任何抗侧信道攻击的验证,并且维护者自己也建议在生产环境使用前进行咨询。 - X-Wing 结构本身已经过同行评审 ([如果 ML-KEM-768 或 X25519 成立,则具有 IND-CCA 安全性](https://eprint.iacr.org/2024/039)) 并且其传输格式在各草案版本中一直保持稳定。 ## 实现状态 | 类别 | 状态 | 描述 | |----------|:------:|-------------| | 群组生命周期 | 完成 | 创建、加入 (Welcome, external commit)、离开、检查 | | 成员管理 | 完成 | 添加、移除、交换成员 | | 消息传递 | 完成 | 使用 AAD 加密/解密应用消息 | | 提案 | 完成 | 添加、移除、自我更新、PSK、自定义、群组上下文扩展 | | 提交 | 完成 | 待定提案、灵活提交、合并/清除 | | 密钥包 | 完成 | 使用选项创建 (生命周期、最后手段凭证) | | 凭证 | 完成 | Basic 和 X.509 凭证类型 | | 状态查询 | 完成 | 成员、epoch、扩展、ratchet tree、群组信息、PSK 导出 | | 存储 | 完成 | 通过 `MlsEngine` 进行静态加密 (SQLCipher / Web Crypto) |
完整的 API 参考 **密钥包**: `createKeyPackage`, `createKeyPackageWithOptions` **群组生命周期**: `createGroup`, `createGroupWithBuilder`, `joinGroupFromWelcome`, `joinGroupFromWelcomeWithOptions`, `inspectWelcome`, `joinGroupExternalCommit`, `joinGroupExternalCommitV2` **状态查询**: `groupId`, `groupEpoch`, `groupIsActive`, `groupMembers`, `groupCiphersuite`, `groupOwnIndex`, `groupCredential`, `groupExtensions`, `groupPendingProposals`, `groupHasPendingProposals`, `groupMemberAt`, `groupMemberLeafIndex`, `groupOwnLeafNode`, `groupConfirmationTag`, `exportRatchetTree`, `exportGroupInfo`, `exportSecret`, `exportGroupContext`, `getPastResumptionPsk` **变更操作**: `addMembers`, `addMembersWithoutUpdate`, `removeMembers`, `selfUpdate`, `selfUpdateWithNewSigner`, `swapMembers`, `leaveGroup`, `leaveGroupViaSelfRemove` **提案**: `proposeAdd`, `proposeRemove`, `proposeSelfUpdate`, `proposeExternalPsk`, `proposeGroupContextExtensions`, `proposeCustomProposal`, `proposeRemoveMemberByCredential` **提交/合并**: `commitToPendingProposals`, `mergePendingCommit`, `clearPendingCommit`, `clearPendingProposals`, `setConfiguration`, `updateGroupContextExtensions`, `flexibleCommit` **消息**: `createMessage`, `processMessage`, `processMessageWithInspect`, `mlsMessageExtractGroupId`, `mlsMessageExtractEpoch`, `mlsMessageContentType`
## 安装说明 将其添加到您的 `pubspec.yaml` 中: ``` dependencies: openmls: ^x.x.x ``` 在构建期间,原生库会通过 Dart 构建钩子自动下载。 最终用户**无需 Rust 环境** — 预编译的二进制文件将从 GitHub Releases 下载。 ## 用法 ``` import 'dart:convert'; import 'dart:typed_data'; import 'package:openmls/openmls.dart'; void main() async { // Initialize the library await Openmls.init(); // Create an MlsEngine with encrypted storage. // - Native: SQLCipher database at the given file path // - Web: IndexedDB with AES-256-GCM encryption via Web Crypto API // Use ":memory:" for ephemeral in-memory storage (testing). final encryptionKey = Uint8List(32); // 32-byte key — store in platform secure storage! final engine = await MlsEngine.create( dbPath: ':memory:', encryptionKey: encryptionKey, ); // Generate signing key pair final ciphersuite = MlsCiphersuite.mls128DhkemX25519Aes128GcmSha256Ed25519; final keyPair = MlsSignatureKeyPair.generate(ciphersuite: ciphersuite); final signerBytes = serializeSigner( ciphersuite: ciphersuite, privateKey: keyPair.privateKey(), publicKey: keyPair.publicKey(), ); // Create a group final config = MlsGroupConfig.defaultConfig(ciphersuite: ciphersuite); final group = await engine.createGroup( config: config, signerBytes: signerBytes, credentialIdentity: utf8.encode('alice'), signerPublicKey: keyPair.publicKey(), ); print('Created group: ${group.groupId}'); // Close engine (releases DB connection and encryption key resources) await engine.close(); // Clean up FRB runtime (optional, for CLI apps exiting) Openmls.cleanup(); } ``` ## 存储 所有 MLS 状态都通过 `MlsEngine` 存储在 Rust 管理的加密数据库中: | 平台 | 后端 | 加密方式 | |----------|---------|------------| | 原生 (iOS, Android, macOS, Linux, Windows) | SQLCipher | AES-256 全库加密 | | Web (WASM) | IndexedDB | 通过 `crypto.subtle` 进行基于值的 AES-256-GCM 加密 | ``` // Create engine with a 32-byte encryption key. // Store the key in platform secure storage (Keychain, Android Keystore, etc.) final engine = await MlsEngine.create( dbPath: 'mls_data.db', // file path on native, IDB name on web encryptionKey: myKey, // 32-byte AES-256 key ); // All operations go through the engine final group = await engine.createGroup(...); await engine.addMembers(...); // Close the engine to release the DB connection and encryption key resources. // After close, all operations fail with "MlsEngine is closed". // Useful for screen lock / app background scenarios. await engine.close(); // Re-create from secure storage on unlock final engine2 = await MlsEngine.create(dbPath: 'mls_data.db', encryptionKey: myKey); ``` 在 WASM 上,加密密钥通过 Web Crypto API 作为**不可提取的 `CryptoKey`** 导入。原始密钥字节在导入后会立即从 WASM 内存中清零。 ## 已知局限 ### Web:不支持 `flutter build web --wasm` (dart2wasm) 此包适用于标准的 `flutter build web` (dart2js) 目标。当宿主应用程序使用 `flutter build web --wasm` / `flutter run -d chrome --wasm` (dart2wasm) 编译时,它目前**无法**使用。对 Rust 端的调用会失败并提示: ``` Type 'JSValue' is not a subtype of type 'List' in type cast ``` 这是 [`flutter_rust_bridge`](https://github.com/fzyzcjy/flutter_rust_bridge) 中的上游限制 — 它生成的 Dart 解码器依赖于隐式 JS 数组转换,这在 dart2js 上有效,但在 dart2wasm 下会失败。这种模式硬编码在 FRB 的代码生成模板中,因此它会影响所有基于 FRB 的 Dart 包,而不仅仅是这个包。上游追踪:[flutter_rust_bridge#2575](https://github.com/fzyzcjy/flutter_rust_bridge/issues/2575)。 | 命令 | 状态 | |---------|--------| | `flutter run -d chrome` | 可用 (dart2js) | | `flutter build web` | 可用 (dart2js) | | `flutter run -d chrome --wasm` | 不受支持 (dart2wasm) | | `flutter build web --wasm` | 不受支持 (dart2wasm) | openmls 的 Rust 核心在这两种模式下均以 `.wasm` 模块交付 — `--wasm` 仅更改 *Dart* 代码的编译目标。加密性能和功能是等效的。 ## 从源码构建 ### 面向最终用户 **无需设置!** 预编译的原生库会在 `flutter build` 期间自动从 GitHub Releases 下载。 ### 面向贡献者 / 源码构建 如果您想从源码构建(或预编译的二进制文件不可用): - [Flutter](https://flutter.dev/) 3.38+ - [FVM](https://fvm.app/) (可选,用于版本管理) - **Rust 工具链** (1.88+): - [rustup](https://rustup.rs/) - Rust 工具链安装程序 - `cargo` - Rust 包管理器(随 rustup 一起安装) ### 设置 ``` # Clone 仓库 git clone https://github.com/djx-y-z/openmls_dart.git cd openmls_dart # 安装 FVM 及依赖 make setup # 生成 Dart bindings make codegen # 构建 native library make build # 运行测试 make test # 查看所有可用命令 make help ``` ### 开发 Rust API 1. 在 `rust/src/api/` 中添加您的 Rust 函数: ``` // rust/src/api/greeting.rs pub fn greet(name: String) -> String { format!("Hello, {}!", name) } ``` 2. 在 `rust/src/api/mod.rs` 中注册该模块: ``` pub mod greeting; ``` 3. 生成 Dart 绑定: ``` make codegen ``` 4. 构建并测试: ``` make build make test ``` ### 构建原生库 原生库已预构建,并通过构建钩子自动下载。 如果您需要在本地构建它们: ``` # 为当前平台构建 make build # 使用特定 target 构建 make build ARGS="--target aarch64-apple-darwin" # 为 Android 构建 make build-android # 为 Web (WASM) 构建 make build-web ``` ## CI / 版本管理 ``` # 检查新的 openmls 版本 make check-new-openmls-version # 检查新的 copier template 版本 make check-template-updates # 检查 deployment target 一致性 (iOS/macOS/Android) make check-targets # 更新 Cargo.lock 依赖 make rust-update # 生成 AI 支持的 changelog 条目(需要 AI_MODELS_TOKEN) make update-changelog ARGS="--version v1.0.0" ``` CI 每天会自动检查 openmls 的新版本,并创建包含以下内容的 PR: - 更新后的 `pubspec.yaml` 和版本徽章 - 更新后的 `Cargo.lock` (如果成功) - 重新生成的 FRB 绑定 (如果成功) - AI 生成的 CHANGELOG 条目 (如果配置了 `AI_MODELS_TOKEN` 密钥) 它每天还会检查 copier 模板更新,并创建包含更新日志和说明的通知 PR。 ## 架构 ``` ┌─────────────────────────────────────────────────┐ │ OpenMLS (Rust crate) │ Core MLS implementation ├─────────────────────────────────────────────────┤ │ MlsEngine + EncryptedDb (Rust) │ Encrypted storage layer ├─────────────────────────────────────────────────┤ │ rust/src/api/*.rs (Rust wrappers) │ FRB-annotated functions ├─────────────────────────────────────────────────┤ │ lib/src/rust/*.dart (FRB generated) │ Auto-generated Dart API ├─────────────────────────────────────────────────┤ │ Your Dart application code │ Uses MlsEngine └─────────────────────────────────────────────────┘ ``` ## 安全说明 **关键属性:** - **MLS 协议 (RFC 9420)** - 具有前向安全和后向安全特性的标准化群组密钥协商 - **Rust 实现** - 所有加密操作均在 Rust 中运行 (带有 RustCrypto 后端的 OpenMLS;实验性的 X-Wing 后量子 KEM 委派给 libcrux) - **静态加密** - 所有 MLS 状态均通过 SQLCipher (原生) 或 Web Crypto AES-256-GCM (WASM) 进行加密 - **WASM 上的 Web Crypto** - 加密密钥通过 `crypto.subtle` 存储为不可提取的 `CryptoKey` — 原始字节永远不会保留在 WASM 内存中 - **内存安全** - Rust 的所有权模型可防止与内存相关的漏洞 - wrapper 层中**没有 `unsafe` 代码** (单线程 WASM 上的 `CryptoKey` 的 `Send + Sync` 除外) **最佳实践:** - 使库保持更新至最新版本 - 将 32 字节的加密密钥存储在平台安全存储中 (Keychain, Android Keystore, `flutter_secure_storage`) - 切勿记录或暴露序列化的密钥材料 (`signer.serialize()`, 私钥) - 对敏感数据 (序列化的密钥、共享密钥) 使用 `SecureBytes.wrap()` 或 `.zeroize()` — 参阅 [SECURITY.md](SECURITY.md) - 按顺序处理 MLS 消息,以保持群组状态的一致性 - **Web 部署:** 启用严格的 CSP 头 (`script-src 'self'`) 并通过 HTTPS 提供服务 有关完整的安全准则,请参阅 [SECURITY.md](SECURITY.md)。 ## 安全性 有关安全策略和报告漏洞,请参阅 [SECURITY.md](SECURITY.md)。 ## 许可证 本项目基于 MIT 许可证授权 - 有关详细信息,请参阅LICENSE](LICENSE) 文件。 ## 相关项目 - [OpenMLS](https://github.com/openmls/openmls) - 底层的 Rust MLS 库 - [RFC 9420](https://www.rfc-editor.org/rfc/rfc9420.html) - 消息层安全协议 - [Flutter Rust Bridge](https://cjycode.com/flutter_rust_bridge/) - Dart/Flutter <-> Rust 绑定生成器
标签:Dart, Flutter, MLS协议, 可视化界面, 安全通信, 密码学, 手动系统调用, 端到端加密