feat(api): bind encrypted workspaces to accounts and devices
This commit is contained in:
1 parent
019b15041a
commit
c7d8ef15bc
49 files changed
+1904
-278
No files matched your search
+21
-8
@@ -2,6 +2,8 @@
|
||||
|
||||
## 1. 组件
|
||||
|
||||
账号、设备、频道、thread 与内容加密的统一边界见 [account-channel-architecture.md](account-channel-architecture.md)。该文档明确账号成员与设备会话分离、按账号领取频道密钥包及加密文件目录。
|
||||
|
||||
```
|
||||
浏览器 (React, 独立托管或 API 同源嵌入) 服务端 (.NET 10, NativeAOT)
|
||||
┌──────────────────────────────┐ ┌─────────────────────────────┐
|
||||
@@ -9,10 +11,10 @@
|
||||
│ @webdrop/core (加解密、帧) │ 密文 + 令牌 │ 鉴权: 只比对令牌哈希 │
|
||||
│ Worker: 流式加解密 │◄───────────►│ 日志: 分配 seq、幂等、推送 │
|
||||
│ IndexedDB: 发送队列、本地收藏 │ │ BackgroundService: 过期清理 │
|
||||
│ Service Worker: 流式下载 │ └──────┬───────────┬──────────┘
|
||||
│ OPFS: 逐块写入临时文件 │ └──────┬───────────┬──────────┘
|
||||
└──────────────────────────────┘ │ │
|
||||
SQLite IBlobStore
|
||||
(元数据、日志) (磁盘,预留 S3)
|
||||
SQLite IBlobStore
|
||||
(频道、账号密文库) (磁盘,预留 S3)
|
||||
```
|
||||
|
||||
服务端没有解密函数,也没有任何能触达明文或 K 的代码路径。可选的 `WebDrop.Frontend` 模块只提供嵌入的静态资源,不访问频道存储或加解密代码。
|
||||
@@ -42,7 +44,7 @@
|
||||
| 全球化 | `InvariantGlobalization=true` |
|
||||
| 库 | 所有项目标记 `IsAotCompatible=true`,把 IL2026、IL3050 等 AOT 和裁剪警告视为错误 |
|
||||
| HTTP/3 | `CreateSlimBuilder` 不含 HTTP/3。服务进程本身**暂不内置 QUIC**,由反向代理终结 HTTP/3,后端用 HTTP/1.1 或 HTTP/2;`WebDrop:EnableHttp3` 只是在 `/info` 里通告。需要内置时再接入 Kestrel 的 QUIC(依赖原生 msquic) |
|
||||
| 密码学 | 服务端只做 SHA-256 和常量时间比较,`System.Security.Cryptography` 在 AOT 下可用 |
|
||||
| 密码学 | 内容加解密在客户端;服务端做令牌 SHA-256、登录/加入密码的加盐 PBKDF2 与常量时间比较,全部兼容 AOT |
|
||||
|
||||
**验证结果**(win-x64,.NET 10.0.204):
|
||||
- Slim builder、Minimal API、原生 WebSocket、SSE、`BackgroundService`、`Microsoft.Data.Sqlite`(随包的 e_sqlite3 原生库,SQLite 3.53)在 NativeAOT 下都能正常运行。
|
||||
@@ -55,11 +57,17 @@
|
||||
|
||||
## 4. 存储模型
|
||||
|
||||
应用契约 2 使用 `DataDir/v2/webdrop.db` 和 `DataDir/v2/blobs`,仅包含当前表结构,不维护旧 schema/旧账号保险库/旧频道认领/旧明文负载的迁移或兼容模型。开发数据可以重新创建,历史目录不自动导入。浏览器采用新的按账号/访客隔离的数据库命名空间。
|
||||
|
||||
SQLite 存元数据和小帧,磁盘存大帧。
|
||||
|
||||
| 表 | 字段 |
|
||||
|---|---|
|
||||
| `channels` | `id` PK, `mode`, `settings`(JSON), `read_hash`, `write_hash`, `owner_hash`, `created_at`, `expires_at`, `last_seq`, `compacted_through`, `bytes` |
|
||||
| `channels` | `id` PK, `mode`(内容加密选项), `creator_account`, `settings`, 能力令牌哈希, 加入密码哈希/salt, 时间、序号、字节数 |
|
||||
| `channel_members` | 频道 ID + username,频道内 owner/member 角色、加入时间;创建者自动为 owner |
|
||||
| `channel_invitations` | 频道 ID + username、客户端加密的邀请 payload、时间 |
|
||||
| `channel_join_denials` | 被移除的账号或设备标识,再次邀请账号时清除账号禁入 |
|
||||
| `accounts/account_sessions` | 登录 salt、登录凭据慢哈希及独立 salt、邀请公钥、保险库密文/revision;随机 session token 的 SHA-256 与过期时间 |
|
||||
| `shares` | `id` PK(与频道共用全局 id 空间), `settings`(JSON), `read_hash`, `owner_hash`(封存时清空), `creator_endpoint_hash`, `created_at`, `expires_at`, `sealed_at`, `manifest_item_id`, `bytes` |
|
||||
| `seats` | `channel_id`, `endpoint_hash`, `label` BLOB, `joined_at`;PK(`channel_id`, `endpoint_hash`) |
|
||||
| `share_visitors` | `share_id`, `endpoint_hash`, `joined_at`;PK(`share_id`, `endpoint_hash`),创建者终端不写入此表 |
|
||||
@@ -97,8 +105,10 @@ SQLite 存元数据和小帧,磁盘存大帧。
|
||||
- 加解密在 Worker 里流式处理,文件不整份进内存。
|
||||
- 发送队列落在 IndexedDB,恢复网络后自动补发,依赖协议的幂等追加。
|
||||
- 条目预览在沙箱 iframe 中渲染;raw 内容只当文本展示或下载。
|
||||
- 下载大文件使用 Service Worker 流式写入,兼容没有 File System Access API 的 iOS Safari。
|
||||
- 本地「我的频道」:链接和密钥保存在 IndexedDB,只在本机。
|
||||
- 下载大文件优先使用 OPFS 流式写入临时文件,认证完成后提供文件;不支持 OPFS 时回退 Blob,限制 64 MiB。
|
||||
- 首页先注册/登录;公开频道/分享链接可按规则由访客访问。创建与管理在服务端绑定账号,频道内成员角色与设备席位分开。所有写入都检查账号或访客设备、频道角色/席位和能力权限。
|
||||
- IndexedDB 按账号与访客分库;切换时中止后台订阅并清空内存。保险库只同步资源凭据、草稿清单和移除墓碑;设备 S、设备标签、缓存、原始文件和 outbox 保留在本机。新设备生成独立 S 后重新加入。
|
||||
- 一个 Channel/Thread 模型共用日志、权限与生命周期;内容是否端到端加密只切换客户端封装加解密。结构 CONTROL 记录不按普通内容 TTL/max_items 清理,随频道删除。
|
||||
|
||||
## 7. 阶段划分
|
||||
|
||||
@@ -111,7 +121,8 @@ SQLite 存元数据和小帧,磁盘存大帧。
|
||||
| 4 | 文件:流式加解密、GATED 拉取、下载计数、预览、粘贴和拖拽 | 100 MB 文件往返一致,下载计数正确 |
|
||||
| 5 | GB 级文件:并行上传和断点续传 | 中途断网后续传成功,内存占用平稳 |
|
||||
| 6 | PWA、Web Share Target、二维码和短配对码(PAKE) | 手机端走通 |
|
||||
| 7 | 可选账号、配额;CLI | 另行设计 |
|
||||
| 7 | 账号登录、客户端加密资源保险库 | 已实现客户端派生口令 verifier/保险库密钥、SQLite opaque vault、资源同步;口令丢失时明确告知无法恢复 |
|
||||
| 8 | thread、虚拟文件夹与 IRC 风格聊天 | 已实现沿用频道加密日志,消息按 thread 归属并展示发送设备,文件夹元数据由客户端加密 |
|
||||
|
||||
每个阶段开始前,先更新 protocol.md 和测试向量,再改代码。
|
||||
|
||||
@@ -122,3 +133,5 @@ SQLite 存元数据和小帧,磁盘存大帧。
|
||||
- 服务端日志中没有 K、令牌和频道 id 明文。
|
||||
- 抓包确认请求里没有 K 和明文。
|
||||
- AOT 发布产物能在没有 .NET 运行时的机器上运行。
|
||||
|
||||
界面术语采用「空间 → 频道分组 → 频道 → 文件夹/聊天」。内部 Channel/Thread 命名保留,分别映射空间/频道;分组沿用加密 CONTROL 日志,不引入新的成员或密钥体系。
|
||||
Reference in new issue
Block a user