版本:2026-08 范围:Senvra 备份与还原 V1,写入格式以
SNVRBKP3为准,并保留对SNVRBKP2的只读兼容。 目标:让用户可以安全地迁移或长期保存数据,同时避免备份文件、错误提示、交互文案泄露空间身份。
1. 方案概览
Senvra 的备份设计不是简单地把数据库和媒体文件打包导出,而是把备份看作一次独立的加密发布流程。导出时不落地明文临时文件,还原时不直接覆盖空间,而是经过校验、解密、查重、临时导入和原子提交几个阶段。
flowchart LR
A[当前空间数据] --> B[导出清单构建]
B --> C[逐项读取媒体与元数据]
C --> D[分块 AES-256-GCM 加密]
D --> E[SNVRBKP3 流式写入]
E --> F[原子落盘为 .senvrabackup]
G[.senvrabackup] --> H[Header 与 AAD 校验]
H --> I[凭据派生与解密]
I --> J[中性查重]
J --> K[临时导入区]
K --> L[原子提交到当前空间]
核心原则:
| 原则 | 设计选择 |
|---|---|
| 不泄露来源空间 | 外层 Header 禁止写入 sourceSpaceID、scope、backupID 等可识别字段 |
| 不暂存明文 | 导出和还原均采用流式处理,明文只存在于内存中的短生命周期缓冲 |
| 不跨空间恢复身份 | 还原只支持“导入当前空间”,不展示“备份来自哪个空间” |
| 不信任文件结构 | Header、Manifest、Note、Attachment、Chunk 都必须被认证和归属校验 |
| 不牺牲交互隐私 | 长耗时任务显示中性的 Privacy Shield,避免露出相册内容或空间状态 |
2. 威胁模型
备份文件通常会被放进 iCloud、移动硬盘、聊天文件、NAS 或第三方网盘,暴露面比 App 沙盒更大。因此备份格式必须假设攻击者可以长期持有 .senvrabackup 文件,并反复进行离线分析。
mindmap
root((Backup Threat Model))
离线攻击
暴力破解密码
重放旧 Header
篡改 Manifest
身份泄露
空间 ID 暴露
文件名暴露
错误提示暴露路径
数据完整性
媒体块被替换
Note 与 Attachment 关系被伪造
导入中断留下半成品
体验风险
长任务期间露出敏感缩略图
大文件导出卡顿
低磁盘导致损坏备份
防护重点不是“文件后缀看起来私密”,而是确保备份文件在离线环境下仍然只暴露最少元信息,并且任何篡改都会在解密或导入前被发现。
3. 密钥与凭据模型
Senvra 使用双凭据模型。私密空间以用户保存的 Access Key 为基础,再叠加 Backup Password;公共空间不要求用户理解空间密钥,而是使用随机 Backup Key 来隔离备份加密材料。
flowchart TB
subgraph PrivateSpace[私密空间备份]
A1[Access Key] --> C1[KDF]
B1[Backup Password] --> C1
C1 --> D1[Backup Encryption Key]
end
subgraph PublicSpace[公共空间备份]
A2[Random Backup Key] --> C2[KDF]
B2[Backup Password 可选/按产品策略] --> C2
C2 --> D2[Backup Encryption Key]
end
D1 --> E[AES-256-GCM 分块加密]
D2 --> E
推荐实现约束:
| 项目 | 约束 |
|---|---|
| KDF | PBKDF2,默认 600k 迭代,并为后续 Argon2 或更高迭代预留参数字段 |
| 数据加密 | AES-256-GCM |
| 分块大小 | 默认 8 MiB,每块独立 nonce 与 tag |
| 认证数据 | Header canonical bytes、版本号、chunk index、manifest digest 等纳入 AAD |
| 密钥生命周期 | 派生密钥只在任务内存活,任务取消或失败后立即释放引用 |
4. SNVRBKP3 文件结构
SNVRBKP3 是当前写入格式。它的关键变化是强化 Header/AAD 认证,并将 Manifest、Note、Attachment 的归属关系纳入导入前校验。
flowchart LR
A[Magic<br/>SNVRBKP] --> B[Version<br/>3]
B --> C[Header Length]
C --> D[Public Header]
D --> E[Salt<br/>KDF Params]
E --> F[Manifest Digest]
F --> G[Encrypted Manifest]
G --> H[Encrypted Chunks]
H --> I[Final Auth Trailer]
外层 Header 只允许放置解密和兼容所需的中性字段。
| 允许字段 | 用途 |
|---|---|
magic | 识别备份文件类型 |
version | 选择解析器和兼容路径 |
kdf | 描述 KDF 算法与参数 |
salt | 密钥派生随机盐 |
chunkSize | 流式解密的块大小 |
createdAt | 可选,中性时间信息 |
| 禁止字段 | 风险 |
|---|---|
sourceSpaceID | 直接泄露来源空间身份 |
| scope / space type | 暗示用户的私密空间结构 |
backupID | 可能被跨文件关联追踪 |
| 原始文件名 / 系统路径 | 可能泄露内容语义或设备信息 |
5. 导出流程
导出流程以“清单先行、流式写入、失败清理”为主线。系统先构建待导出的逻辑清单,再逐项读取数据库记录和媒体文件,边读边加密写入目标文件,不创建明文压缩包。
sequenceDiagram
participant UI as Backup UI
participant App as AppModel
participant Store as VaultStore
participant Crypto as Crypto Pipeline
participant File as Backup Writer
UI->>App: 用户确认导出
App->>Store: 请求快照与导出清单
Store-->>App: Notes / Attachments / Media refs
App->>Crypto: 初始化 KDF 与 Header AAD
loop 每个媒体或元数据块
App->>Store: 流式读取
Store-->>Crypto: 明文缓冲
Crypto-->>File: 密文块 + tag
end
File->>File: fsync + 原子 rename
App-->>UI: 完成或中性失败信息
性能策略:
| 场景 | 策略 |
|---|---|
| 大媒体文件 | 固定 8 MiB 分块,避免一次性读入内存 |
| 大量小附件 | 批量构建清单,减少数据库往返 |
| 低磁盘 | 导出前预估空间,导出中监控写入失败并清理临时文件 |
| 任务取消 | 停止读取、销毁密钥引用、删除未完成临时备份 |
| App 失活 | 进入中性遮罩,避免任务期间暴露内容缩略图 |
6. 还原流程
还原不是“恢复一个空间”,而是“把备份内容导入当前空间”。这个产品边界可以避免用户从 UI 文案或数据结构里推断出备份来源空间。
flowchart TD
A[选择 .senvrabackup] --> B{Magic / Version 合法?}
B -- 否 --> X[中性失败提示]
B -- 是 --> C[读取 Header 与 KDF 参数]
C --> D[输入 Access Key / Backup Password]
D --> E{Header AAD 校验通过?}
E -- 否 --> X
E -- 是 --> F[解密 Manifest]
F --> G{归属关系校验}
G -- 否 --> X
G -- 是 --> H[中性查重]
H --> I[写入临时导入区]
I --> J{全部块校验通过?}
J -- 否 --> Y[清理临时导入区]
J -- 是 --> K[原子提交到当前空间]
K --> L[完成]
导入前必须完成三类检查:
| 检查 | 目的 |
|---|---|
| Header/AAD 认证 | 防止攻击者替换版本、KDF 参数或 Header |
| Manifest digest | 防止清单被替换、裁剪或重排 |
| Note/Attachment 归属 | 防止附件被挂到错误 Note,或伪造孤儿记录 |
查重逻辑必须保持中性:可以判断“已存在相同内容”并跳过重复项,但不展示来源空间、原始路径、原始文件名等敏感上下文。
7. Privacy Shield
备份和还原属于长耗时任务。用户一旦进入后台、锁屏、切换 App、触发录屏风险,界面应该切换到中性的 Privacy Shield,而不是继续展示相册网格、文件名或空间状态。
stateDiagram-v2
[*] --> Idle
Idle --> Exporting: 开始备份
Idle --> Importing: 开始导入
Exporting --> Shielded: App 失活 / 锁屏 / 风险状态
Importing --> Shielded: App 失活 / 锁屏 / 风险状态
Shielded --> Exporting: 回到安全前台
Shielded --> Importing: 回到安全前台
Exporting --> Finished
Importing --> Finished
Exporting --> Failed
Importing --> Failed
Failed --> Idle
Finished --> Idle
界面文案应保持中性,例如:
| 不推荐 | 推荐 |
|---|---|
| 正在恢复私密空间 | 正在导入备份 |
| 来自 XXX 空间的备份已恢复 | 已导入可用内容 |
文件 IMG_0001.mov 解密失败 | 部分内容无法导入 |
/var/mobile/... 写入失败 | 存储空间不足或文件不可用 |
8. 原子化与失败恢复
导入流程必须保证“要么全部提交,要么看起来什么都没发生”。用户不应该在失败后看到半张图片、半条 Note 或孤立附件。
flowchart LR
A[创建导入事务] --> B[写临时数据库记录]
B --> C[写临时媒体文件]
C --> D[校验所有 tag 与 digest]
D --> E{校验通过?}
E -- 是 --> F[批量提交记录]
F --> G[移动媒体到正式目录]
G --> H[提交事务]
E -- 否 --> I[回滚数据库]
I --> J[删除临时媒体]
失败处理规则:
| 阶段 | 失败动作 |
|---|---|
| 凭据错误 | 不暴露是 Access Key 还是 Password 错,只提示无法打开备份 |
| Header 校验失败 | 停止解析,避免继续读取被篡改结构 |
| 分块解密失败 | 删除当前临时文件,标记任务失败 |
| 导入提交失败 | 回滚数据库事务,并清理临时媒体目录 |
| 用户取消 | 尽快停止 I/O,清理临时产物,界面回到安全状态 |
9. 兼容策略
flowchart LR
A[SNVRBKP2<br/>只读兼容] --> B[SNVRBKP3<br/>当前写入格式]
B --> C[Future<br/>新 KDF / 分块索引 / 压缩策略]
兼容原则:
| 版本 | 策略 |
|---|---|
SNVRBKP3 | 默认导出格式,完整安全能力 |
SNVRBKP2 | 只读导入,不再生成 |
| 未知更高版本 | 不尝试降级解析,提示当前版本暂不支持 |
| 损坏或伪造版本 | 返回中性失败,不展示底层异常 |
10. 验收红线
上线前至少满足以下红线:
- 外层 Header 不包含
sourceSpaceID、scope、backupID、原始文件名、系统路径。 - 导出流程不创建明文 zip、明文 tar、明文 sqlite 副本或可恢复的明文临时目录。
SNVRBKP3的 Header、Manifest、Chunk 均参与认证,任意篡改都能失败。- Note 与 Attachment 的归属关系在导入前验证,不能出现跨记录挂载。
- 还原只能导入当前空间,UI 不出现“恢复到原空间”或“来自某空间”的暗示。
- 导入提交具备事务边界,失败后不能留下半成品。
- 低磁盘、强制中断、用户取消后,会清理临时文件。
- 错误提示不包含文件名、路径、空间名、内部 ID 或系统异常原文。
- 长耗时任务在失活、锁屏、录屏风险下进入 Privacy Shield。
11. 用户路径
journey
title 用户备份与迁移体验
section 导出
选择备份: 5: 用户
设置备份密码: 4: 用户
保存 Access Key 或 Backup Key: 3: 用户
等待导出完成: 4: 用户
section 保存
把 .senvrabackup 放到可信位置: 4: 用户
记录凭据: 3: 用户
section 导入
选择备份文件: 5: 用户
输入凭据: 3: 用户
导入当前空间: 5: 用户
体验设计的重点是让用户明确知道两件事:
- 备份文件本身已经加密,但丢失凭据就无法恢复。
- 还原会导入当前空间,不会在 UI 上暴露备份原本属于哪个空间。
12. 实现检查清单
| 模块 | 检查项 | 状态 |
|---|---|---|
| Backup Writer | 流式写入、原子 rename、失败清理 | 必须 |
| Crypto | PBKDF2 参数、AES-GCM chunk、AAD 绑定 | 必须 |
| Manifest | Digest、记录归属、版本兼容字段 | 必须 |
| Restore Pipeline | 临时导入区、查重、事务提交 | 必须 |
| UI | 中性文案、Privacy Shield、进度反馈 | 必须 |
| Error Boundary | 过滤系统路径、文件名、内部 ID | 必须 |
| Compatibility | SNVRBKP2 只读、未知版本拒绝 | 必须 |
| Disk Guard | 导出/导入前容量预检,失败后清理 | 必须 |
13. 总结
Senvra 的备份方案核心不是“导出一个文件”,而是把敏感数据从 App 沙盒带到更不可信的外部环境时,仍然保持加密、认证、低泄露和可恢复的工程边界。
这套方案用 SNVRBKP3 解决格式可信问题,用双凭据模型解决离线攻击问题,用流式加密解决明文暂存和大文件性能问题,用当前空间导入与中性文案解决身份泄露问题。最终目标是让备份文件可以长期保存、跨设备迁移,同时不让用户承担理解内部空间结构的成本。