跳转至

安全说明

RelayDrop 是一个实现,目标是提供一套基于中继的加密文件转发。下面说明加密模型与安全取舍。

密钥模型

两把独立密钥(见 src/crypto.rs):

  • relay_key = HKDF-SHA256(relay_password)
  • 用途:保护客户端 ↔ 中继的控制通道(口令校验、房间名下发)。
  • 中继持有它,因此中继能读取房间名,但不能读取文件内容
  • file_key = HKDF-SHA256(room_code)
  • 用途:加密发送方 ↔ 接收方的文件分块(AES-256-GCM)。
  • 仅发送方与接收方知道(它们共享 --code),中继不知道,所以中继管道里是密文。

文件传输流程:发送方用 file_key 加密每个分块 → 中继仅做字节转发(看到的是密文)→ 接收方用 file_key 解密。

关于口令模型(重要)

本实现省略了 PAKE(口令认证密钥交换),直接由共享口令 room_code 派生 file_key。这意味着:

  • 若中继(你的 VPS)同时知道 room_code,它理论上能解密文件
  • 假设中继可信(它是你自己的 VPS)。在此前提下,简化是安全的,且实现更简单。

何时需要升级为完整 PAKE

如果你不信任中继(例如中继由第三方托管、或 VPS 可能被攻陷),则应升级为 PAKE, 使 file_key 不被任何单一方(包括知道 room_code 的中继)掌握。后续可引入 spake2 / opaque 等 crate 替代当前的 derive_key(code)

使用建议

  1. 使用高熵 --codefile_key 直接由它派生,弱口令(如 1234)可被离线暴力。 建议用长随机串,例如 RelayDrop 可后续支持口令生成器(当前请自行生成)。
  2. 中继口令 --password--code 不同且足够强:前者用于客户端 ↔ 中继鉴权。 优先用环境变量 RELAYDROP_PASSWORD 提供口令(见 usage.md 的「环境变量」小节), 不要写进命令行——命令行参数会出现在 shell 历史与 /proc/<pid>/cmdline,同机其他用户可读到。
  3. 依赖 TLS 保护传输wss:// 路径的 TLS 由前端反向代理(如 nginx)/ 隧道(如 cloudflared)终结, 确保客户端 ↔ 前端之间的链路加密。
  4. 文件完整性:接收方会对 SHA-256 做校验,损坏或被篡改的文件会被拒绝。

自动生成命令的安全取舍

发送方在省略 --code 时会生成随机传输密钥,并打印一串可直接复制粘贴的接收命令

relaydrop receive --relay <url> --code <随机> --password <pw> --out .

需要注意的暴露面:

  • --code(文件密钥来源)完整出现在发送方终端与接收方粘贴的 shell 中,并写入两端 shell 历史(~/.bash_history 等)、可能出现在 ps 进程列表(含命令行参数的短暂窗口)。 任何能读到该命令的人都能在有效期内解密并接收/偷取文件,因此命令不应通过不可信渠道明文转发。
  • --password(中继鉴权口令)按运维常量原样嵌入命令(本实现不会随机生成 --password,它由运维固定配置,见设计文档 D2)。 它的暴露同样意味着拿到命令的人能连上你的中继房间;务必与 --code 使用不同的强随机值。
  • 缓解:命令建议通过带外(已加密的 IM/密码管理器)发给受信任的接收方;用完即弃、不要长期留存命令文本;中继侧可对同一房间口令设置 TTL 或一次性。
  • 口令优先走环境变量:用 RELAYDROP_PASSWORD=SECRET relaydrop ... 代替 --password SECRET, 可避免口令进入 shell 历史与 ps/proc/<pid>/cmdline)。注意环境变量仍可能被同用户通过 /proc/<pid>/environ 读到;最高安全场景用 systemd LoadCredential= 注入(口令不落环境变量、不进 cmdline)。

已知限制

  • 房间无「角色强制」:第一个连接者不一定是发送方;管道是双向的,谁先发 Manifest 谁就是发送方。 使用时应约定「发送方先发 / 接收方先等」。
  • 无前向保密(AES-GCM 固定密钥派生);若 room_code 泄露,历史传输在密钥不变前提下可被解密。
  • 单房间、单次传输;支持单个或多个文件/目录/混合源(见 README 与 usage.md),但不支持断点续传、压缩、多人(见 README 非目标说明)。