Zumpyx's Blog

文件交换系统构思

安全设计加密文件传输隐私架构

本文由早期草稿整理扩展。当前是可落地的设计构思,尚未对应某一开源实现;算法与流程已对齐表述,并补上威胁模型、密钥管理与失败恢复。

1. 目标与非目标

1.1 想解决什么

不依赖双方同时在线的专用中继服务器、也不希望明文经过「自己可控的中心存储」的前提下,完成单文件的点对点交换:

  • 载荷只以密文形式出现在多个互不相关的匿名/半匿名中转站
  • 密钥与下载线索走另一条信令通道(草稿里用 note.ms 一类可写即焚页面);
  • 加解密与密钥保管尽量落在双方各自的小型硬件设备上,减少在通用 PC 上暴露明文与主密钥的时间。

1.2 明确不做

非目标 说明
大流量同步盘 不做多文件目录同步,单次任务 = 一个文件
完美匿名对抗国家级对手 中转站与信令仍可能被关联分析
实时双向聊天 只做文件投递 + 状态机
中心化账号体系 不引入统一用户 ID 服务

1.3 设计原则

  1. 密钥与载荷分离:密文分卷上中转站,密钥材料只走信令。
  2. 多层不同算法:对称层叠加 + 分卷,单点泄露不至于「一键还原」。
  3. 分卷分散托管:三个分卷三个站,少一卷则无法解压还原。
  4. 短时信令:note 页写入后尽快取走清空,降低信令驻留。
  5. 状态可观测:收发 UI 用阶段条表达进度,便于人工值守。

2. 角色与组件

┌─────────────┐         信令(加密元数据)          ┌─────────────┐
│  设备 A     │ ──── note 路径 / 轮询 ──────────► │  设备 B     │
│ (发送侧)    │                                   │ (接收侧)    │
└──────┬──────┘                                   └──────▲──────┘
       │ 密文分卷 ×3                                      │ 下载分卷 ×3
       ▼                                                  │
  中转站1 / 中转站2 / 中转站3  ────────────────────────────┘
组件 职责
硬件设备 本地生成/保管密钥、加解密、分卷、上传下载、轮询信令
信令面 存放 RSA 加密后的元数据 JSON(密钥、哈希、链接)
载荷面 三个互异的匿名文件中转,各存一个 7z 分卷
控制 UI 展示发送/接收阶段(可跑在设备 Web UI 或配对 App)

设备对:预先绑定的一对设备(A↔B)。可扩展多对,用「设备对号」区分。


3. 威胁模型(简要)

对手能力 假设 本方案应对思路
单个中转站运营方 可见一个分卷密文 缺另外两卷 + 外层密钥,无法还原
信令页被第三方先读到 可见 RSA 密文 无私钥则无法解元数据
网络窃听 可见 HTTPS/中转流量 载荷已是多层密文
设备被物理拿走 可能有密钥与明文 需设备 PIN/安全元件;明文尽快删
全球被动关联 时间与体量关联三站+信令 降风险:随机延迟、体积填充、多通道;不能指望绝对抗关联
note 类服务被封/投毒 可用性、完整性 双信令备份、元数据带 HMAC/签名

不防:两端设备都被植入木马;用户主动把明文再拷到不可信电脑且长期存放。


4. 密钥与标识

4.1 非对称密钥(长期,按设备对)

草稿表述易混,这里定成清晰模型:

  • 每台设备持有自己的 RSA-4096(或 X25519 + 签名用 Ed25519,实现阶段可升级)密钥对。
  • 发往 B 的元数据:用 B 的公钥加密(只有 B 能解)。
  • 可选:元数据外层再由 A 签名,B 验签防伪造信令。

若坚持「RSA A 组 / B 组」双组密钥,建议语义固定为:

名称 含义
设备身份密钥 长期,出厂/初始化生成,私钥不出安全芯片
会话封装 每次发送用接收方身份公钥封装对称会话密钥

4.2 对称会话密钥(每次发送临时生成)

每次任务独立生成三把互不复用的随机密钥:

密钥 算法 长度 用途
(K_1) ChaCha20-Poly1305(AEAD) 256-bit 明文 → *.secretdata1
(K_2) SM4-GCM(或 SM4-CTR+HMAC) 128-bit secretdata1*.secretdata2
(K_3) 7z 加密(AES-256,p7zip 实际能力) ≥256-bit 口令材料 分卷压缩包

与草稿 UI 对齐说明:早期草稿里「流程写 ChaCha20 / 界面写 AES256」不一致。实现上建议:

  • 内容加密层明确用 ChaCha20-Poly1305 + SM4-AEAD;
  • 分卷层使用 7z 自带 AES-256;
  • UI 文案与真实算法一致,避免运维误判。

4.3 随机数与「公共熵」

草稿:用 BTC 现价 + ETH 持持仓等作种子,欧意/火币双备。

更稳妥的做法:

  1. 主熵:设备 TRNG / getrandom / 安全芯片。
  2. 辅助熵(可选):多源行情 API 的哈希混入,抗「单一 RNG 实现烂」——不能替代系统 CSPRNG。
  3. S:设备对初始化时协商或预置,写入安全存储。

通道路径示例:

path = hex( SHA256( date_utc + channel_id + pair_id + S ) )
信令 URL = https://note.ms/{path}   # 或自建等价「可写短文本」服务

建议用 SHA-256 而非 MD5;日期用 UTC 并约定切换点(如每日 00:00 UTC),避免双方时区不一致。

4.4 通道

  • 每对设备可配置多个 channel_id(业务隔离:合同、影像、应急…)。
  • 设备循环轮询当日路径;可同时监听「今日 + 昨日」防止跨日边界丢信令。

5. 元数据格式(信令明文 JSON)

RSA/ECIES 封装前的明文示例:

{
  "v": 1,
  "pair_id": "AB-001",
  "channel_id": 3,
  "task_id": "01J…",
  "filename": "report.pdf",
  "filesize": 10485760,
  "created_at": "2026-07-20T12:00:00Z",
  "k1": "<base64>",
  "k2": "<base64>",
  "k3": "<base64-or-passphrase>",
  "parts": [
    {
      "idx": 1,
      "sha256": "…",
      "url": "https://mirror-a.example/…",
      "expires_at": "2026-07-21T12:00:00Z"
    },
    { "idx": 2, "sha256": "…", "url": "…", "expires_at": "…" },
    { "idx": 3, "sha256": "…", "url": "…", "expires_at": "…" }
  ],
  "note": "optional human hint"
}

封装:ciphertext = RSA-OAEP(B_pub, json) 或「随机 DEK + RSA 封 DEK」以支持更长 JSON。
信令页只写密文;B 取走后立即清空


6. 发送流程(设备 A → B)

6.1 步骤

  1. 用户在 A 侧选定单个文件,创建任务 task_id
  2. 设备生成 (K_1,K_2,K_3)。
  3. 一层:ChaCha20-Poly1305 加密明文 → file.secretdata1
  4. 二层:SM4-GCM 加密 → file.secretdata2
  5. 三层:p7zip/7z 使用 (K_3) 加密并切成 3 个分卷(体积尽量接近,可填充对齐)。
  6. 对每个分卷计算 SHA-256
  7. 将分卷 分别上传 到三个不同中转站,得到 url1..3(失败则换站重试)。
  8. 组装元数据 JSON,用 B 的公钥加密,写入当日信令路径。
  9. 本地按策略删除中间态;仅保留任务日志(可无密钥)。

6.2 发送侧 UI 阶段(与算法一致)

阶段 显示文案
1 发送任务创建
2 一级加密(ChaCha20-Poly1305)
3 二级加密(SM4-GCM)
4 三级加密分卷(7z AES-256)
5–7 上传分卷 1 / 2 / 3
8 信令已发布,等待对方拉取
9 对方已取信令 / 分卷已被下载(若中转可探测)
10 任务完成或超时失败

「已被下载」依赖中转站是否提供次数/状态;没有则只能靠 B 回执信令(可选 ACK 通道)。


7. 接收流程(设备 B)

  1. 轮询信令路径,发现非空 → 先下载密文再清空页面(防他人二次读)。
  2. B 私钥解密元数据;校验 pair_id / 签名 / 时间窗。
  3. 并行下载三个分卷;逐个校验 SHA-256,失败则有限次重试或换镜像字段(若元数据带备用 URL)。
  4. 用 (K_3) 解 7z 合并 → secretdata2
  5. (K_2) 解 SM4 → secretdata1
  6. (K_1) 解 ChaCha20 → 明文,存设备保险区。
  7. 擦除分卷与中间文件;通知用户「可取回」。

7.1 接收侧 UI 阶段

阶段 显示文案
1 接收任务创建
2–4 下载分卷 1 / 2 / 3
5 分卷校验通过,合并解密(7z)
6 二级解密(SM4-GCM)
7 一级解密(ChaCha20-Poly1305)
8 清除过程文件
9 等待用户下载到可信终端
10 用户已取走 / 本地副本已按策略销毁

8. 失败恢复与边界情况

情况 处理
某一中转上传失败 自动换提供商;三站都失败则任务失败,不写信令
信令写入失败 载荷可先不删,指数退避重试;超时则删分卷防孤儿密文长期挂公网
跨日路径不一致 同时听「UTC 今日+昨日」
分卷哈希不符 重下;仍失败则信令标 failed,A 可重发新任务(新密钥)
中转提前删档 任务失败;可要求 A 在有效期内重传
元数据被串改 公钥加密下攻击者难精确定制;加签名后可直接拒收
大文件 单文件上限(如 2GB)由设备磁盘与中转限制决定;超时与断点续传按中转能力实现

重发:永远生成新的 (K_1..K_3) 与 task_id,禁止复用会话密钥。


9. 中转站与信令选型建议

9.1 载荷中转

  • 条件:匿名/免登录、直链下载、尽量支持 HTTPS、有过期时间。
  • 策略:三个不同运营主体;避免同一集团 CDN。
  • 上传出口可用不同网络路径(降低「同一 IP 传三站」的简单关联)。

9.2 信令

  • 草稿:note.ms 类「猜路径即可读写」——实现简单,但可用性与投毒是风险。
  • 增强选项:
    • 自建短 TTL 的 KV(Cloudflare Workers + 鉴权);
    • 双写两个信令后端,元数据相同;
    • 路径仍由日期+通道+盐派生,不把真实 pair 写进 URL。

10. 安全加固清单

  1. 私钥与 (K_i) 仅在设备安全元件/加密分区使用,UI 进程不落盘明文密钥。
  2. AEAD 必用(ChaCha20-Poly1305、SM4-GCM),避免「只加密不校验」。
  3. 明文与中间文件:任务结束 shred/安全擦除。
  4. 任务日志默认不含密钥与完整 URL,或单独加密审计库。
  5. 速率限制:防信令路径被扫(盐长度足够,如 128-bit)。
  6. 固件签名升级;调试口出厂关闭。
  7. 法律与合规:匿名中转与跨境传输需按使用地区自行评估。

11. 实现分期(从构思到原型)

阶段 交付
P0 Linux 上 CLI:本地三层加密 + 7z 分卷 + 手动上传 + RSA 封 JSON
P1 接入 2~3 个中转 API + note/自建信令轮询
P2 设备镜像(ARM 小主机)、Web UI 状态机、双日路径
P3 安全芯片存钥、ACK 回执通道、多通道 QoS、可观测指标

技术栈示例(无强制):Rust/Go 做加解密与状态机;7z 调 7zz;硬件用带 eMMC 的 ARM + 可选 TPM。


12. 流程总览(对照表)

步骤 发送方 A 接收方 B
1 选文件,生成会话密钥 轮询信令
2 ChaCha20 加密 取信令并清空
3 SM4 加密 RSA 解密元数据
4 7z 加密分卷 ×3 下载分卷并校验哈希
5 分上传三站 7z → SM4 → ChaCha20 解密
6 RSA 封元数据写信令 擦除中间文件,用户取回

13. 开放问题(后续可写专题)

  • 是否引入邮筒模式(A 离线后 B 才上线的持久邮箱,但仍无明文服务器)?
  • 三人以上群组如何做信封(多公钥封装同一 DEK)?
  • 中转站 API 频繁变更时的「驱动插件化」?
  • 与「家用存储 / Johnny.Decimal」归档流程如何衔接(收件后自动入库分类)?

修订说明

处理
原文 点对点收发步骤草稿,算法与 UI 表述不一致
补全 威胁模型、密钥语义、JSON 元数据、失败恢复、分期实现
修正 统一 ChaCha20 / SM4 / 7z-AES 与界面文案;MD5→SHA-256;RSA 方向改为「接收方公钥加密」
定位 设计构思文,非已上线产品说明书