安全说明¶
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)。
使用建议¶
- 使用高熵
--code:file_key直接由它派生,弱口令(如1234)可被离线暴力。 建议用长随机串,例如RelayDrop可后续支持口令生成器(当前请自行生成)。 - 中继口令
--password与--code不同且足够强:前者用于客户端 ↔ 中继鉴权。 优先用环境变量RELAYDROP_PASSWORD提供口令(见 usage.md 的「环境变量」小节), 不要写进命令行——命令行参数会出现在 shell 历史与/proc/<pid>/cmdline,同机其他用户可读到。 - 依赖 TLS 保护传输:
wss://路径的 TLS 由前端反向代理(如 nginx)/ 隧道(如 cloudflared)终结, 确保客户端 ↔ 前端之间的链路加密。 - 文件完整性:接收方会对 SHA-256 做校验,损坏或被篡改的文件会被拒绝。
自动生成命令的安全取舍¶
发送方在省略 --code 时会生成随机传输密钥,并打印一串可直接复制粘贴的接收命令:
需要注意的暴露面:
--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读到;最高安全场景用 systemdLoadCredential=注入(口令不落环境变量、不进 cmdline)。
已知限制¶
- 房间无「角色强制」:第一个连接者不一定是发送方;管道是双向的,谁先发
Manifest谁就是发送方。 使用时应约定「发送方先发 / 接收方先等」。 - 无前向保密(AES-GCM 固定密钥派生);若
room_code泄露,历史传输在密钥不变前提下可被解密。 - 单房间、单次传输;支持单个或多个文件/目录/混合源(见 README 与 usage.md),但不支持断点续传、压缩、多人(见 README 非目标说明)。