这一版做了什么
v1.3.0 的主题是把加密真正接到传输链路上。此前仓库里已经有 X25519 + AES-256-GCM + HKDF 的完整实现和单元测试,但它只用于生成设备指纹和握手标识,文件内容在局域网上仍然是明文。这一版把它接上了主线,并补上了配套的保护机制。
🔐 传输加密已生效
- 每个分块都做 AES-256-GCM 封装后才发送,服务端验签通过才落盘。tag 被改动、或分块被放到错误的序号上,都会被直接拒绝。
- 随机 96 位 nonce。修复了一个真实缺陷:之前的 nonce 是拿分块序号确定性推导的,同一个会话里发两个文件会复用同一个 GCM nonce,从而泄露密钥流。
- 以 task id + 分块序号作为 AAD,因此分块无法重排、无法跨文件拼接。
📱 手机 ↔ 手机端到端加密
发送方直接与目标手机协商独立的会话密钥,桌面 hub 只按目标地址转发已封装的密文——hub 不持有该会话的密钥,也无法解密文件内容。目标设备的会话 id 通过 X-Target-Session-Id 单独传递,避免把 hub 与发送方之间的会话 id 泄露给接收端。
🔑 配对凭据不再上网
6 位配对码 / 一次性 token 现在只作为 HKDF 的输入使用,双方用派生出的会话密钥做 HMAC 证明来互相验证,而不是像以前那样把 PIN 发给服务端做比较。PIN 本身从不经过网络。
🌐 自签名 HTTPS 门户
浏览器只在安全上下文里提供 WebCrypto,所以门户必须走 HTTPS。证书由纯 Node 生成(含 IP SAN),首次访问会有自签名证书警告。若你用 http:// 打开门户,页面会直接提示"当前地址不支持加密"并拒绝配对,而不是静默降级为明文。
🛡️ 其它安全修复
- 配对限流:同一来源 IP 连续 8 次失败后封禁(hub 与 Android 接收端都生效)。
- 会话强制校验:上传、下载、保管库列表、设备名接口都要求已验证的会话,只有回环调用豁免。
- 修复 PIN/token 泄露:
/api/v1/info此前会把 PIN 和 token 返回给任意局域网调用者,使配对形同虚设;现在只对回环披露。 - 修复
/health返回 HTML:它位于/api/v1前缀之外,落到了静态处理器上,用index.html返回 200,还骗过了 Tauri 的启动探测。 - 中继目标默认允许本机所在子网,这样不用 RFC1918 网段的网络(部分家用路由、VPN 覆盖网、实验室网段)无需配置即可中继。回环、链路本地(含云元数据
169.254.169.254)与公网地址仍然禁止。
📦 打包修复
- 安装包不再缺失后端模块。之前它只拷硬编码的文件列表(
server.js+public/),导致crypto_protocol.js、lan_guard.js、tls_selfsigned.js没被打进去,装完首次启动就是MODULE_NOT_FOUND。现在模块从目录自动发现,并在打包前做依赖校验——缺模块会让构建失败,而不是让用户的安装失败。 - 安装包不再携带维护者的个人路径,载荷里是空配置,默认保存到当前用户的
Downloads/SafeDrop。 - Android 支持真实签名:
signingConfigs.release从keystore.properties(已 gitignore)或SAFEDROP_KEYSTORE_*环境变量读取,仅在未配置时回退到调试密钥。 - 版本号统一到 1.3.0,由单一
APP_VERSION常量提供,此前 Tauri 停在 1.1.0、Android 停在 1.0.2。 - 修复设置面板样式:传输与安全配置区块此前引用了不存在的 CSS 类,文字没有正确落在设置栏里。
下载与安装
| 产物 | 适用平台 | 说明 |
|---|---|---|
SafeDrop-Setup.exe |
Windows 10 1809+ / 11(64 位) | 单文件自解压安装包,内置便携 Node 运行时,无需另外安装 Node.js |
app-release.apk |
Android 8.0(API 26)及以上 | 接收端,需允许"安装未知来源应用" |
⚠️ Android 包使用调试密钥签名(CN=Android Debug),足以自用与内部分发,但不是应用商店签名。同一台设备上后续版本需要同一密钥签名才能覆盖安装。macOS / Linux:Tauri 代码本身跨平台,但尚未实机验证,不保证可用。
验证情况
本次改动经过实测而非推断:
node test_encryption_e2e.js— 30 项全部通过,覆盖配对与 HMAC 证明、加解密往返、篡改与重排拒绝、限流、手机→手机中继(校验密文逐字节未被修改)、HTTPS 门户加密上传。- 从
SafeDrop-Setup.exe中实际提取嵌入载荷,确认 16 个条目齐全(含 4 个后端模块与node.exe),再用随包的node.exe启动,/health返回{"status":"ok","ready":true},并且从局域网 IP 请求/api/v1/info时已不再返回 PIN / token。 - APK 用
apksigner verify复核,签名者已变为稳定的调试密钥。
安装包版本标识修正
Windows 三个原生组件(SafeDrop.exe / installer.exe / uninstall.exe)的程序集版本此前仍停留在 1.0.1,与产品版本不一致,会体现在文件属性与「程序和功能」列表中。现已统一为 1.3.0,并在构建流程中加入版本一致性校验——组件版本与 APP_VERSION 不符时构建直接失败,避免再次漂移。
双端配对不同步(本次修复)
配对码在每次握手成功后都会轮换,但桌面界面只在启动时读取一次,因此首台设备配对后,屏幕上显示的 PIN 与二维码就失效了——第二台设备照着屏幕输入也会被拒绝(Pairing proof verification failed)。这解释了「双端不同步」的现象。现已修复:
- 桌面界面定时刷新配对信息,屏幕与 QR 始终跟随 hub 的当前值;
- 已轮换的旧凭据保留三代宽限,超出后才失效(窗口有界,不是无条件接受);
- 会话改为空闲超时,不再从创建时刻硬性到期,避免传输中被掐断后报 401。
Android 接收端存在完全相同的单槽位缺陷,已同步修复;其 PIN 生成也从 Math.random() 改为 SecureRandom。
已知边界
- 桌面端本机与 hub 之间走明文回环 HTTP,这是速度与复杂度的取舍。
- 自签名证书只提供传输加密,不提供身份认证;对端真实身份由配对 PIN 与握手 HMAC 保证,因此中间人即便替换证书,拿不到 PIN 也解不出会话密钥。
- 断点续传、批量下载、二维码分享链接仍在计划中。
校验值
65c365640d18e1c0a7fd30bf2d15d1a628c751f3c735d51adaa51fae97f755b2 *SafeDrop-Setup-1.3.0.exe
22f570a78dddf34c231a579e820efb791de124b65e8f807e28255b84eab40d1b *SafeDrop-Android-1.3.0.apk