DreadpiratePickles/lockbox-lane

GitHub: DreadpiratePickles/lockbox-lane

一款端到端加密的文件分享工具,文件在客户端使用 AES-256-GCM 加密,服务器永远无法接触明文和密钥。

Stars: 0 | Forks: 0

# 🔒 Lockbox Lane ### 在你的机器上进行加密后再分享文件,确保在任何数据离开之前就已加密。 ![python](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white) ![license](https://img.shields.io/badge/license-MIT-blueviolet) ![tests](https://img.shields.io/badge/tests-18%20passing-brightgreen) ![interface](https://img.shields.io/badge/interface-CLI%20%2B%20Web-22c55e) ![crypto](https://img.shields.io/badge/crypto-AES--256--GCM-6f42c1) ![transmits](https://img.shields.io/badge/transmits-nothing%20by%20default-success) *如果服务器能够读取它,那它就不是私密的——只不过是读取起来有点麻烦而已。*
Lockbox Lane 是一个小型的防御性文件分享工具。文件在**客户端**进行加密 (在你的浏览器中使用 WebCrypto,或在本地使用 CLI),采用 AES-256-GCM 加密。服务器只 接收密文和公共 IV——**绝不接收密钥**。解密密钥通过分享链接的 URL *片段*(`#key=…`)进行传输,浏览器不会将该片段发送给服务器。服务器只是一个 姿态良好的储物柜;它无法读取自己存储的内容。 它附带了一个匹配的**本地加密 CLI**(`encrypt-file` / `decrypt-file` / `inspect` / `keygen`),因此你可以从终端或 脚本中生成和打开完全相同的 AES-256-GCM 信封——这对于备份、带外传输以及解释为什么*“服务器稍后对其进行了加密”* 不等同于*“服务器从未见过它”*非常有用。 ## 为什么会有这个项目 大多数“安全上传”工具都是*静态*加密的——但这发生在服务器已经接收到 你的明文**之后**。这可以防止磁盘被盗;但对于被攻破或好奇心强的 服务器毫无作用。Lockbox Lane 展示了用于简单分享的端到端加密:在传输前加密,加密存储,仅在接收者的浏览器中解密。 ## 它是如何工作的 ### 分享流程(浏览器) ``` Sender's browser Server (this app) Recipient's browser ──────────────── ───────────────── ─────────────────── pick file generate AES-256 key ──┐ generate 96-bit IV │ encrypt (AES-GCM) ──────┘ │ ciphertext + iv ▼ POST /api/files store blob on disk (uploads/.bin) store metadata in SQLite (id, size, iv, expiry, download cap, count) ◀──────────────── { id, share_path } build link: /share/#key=&name= │ │ key rides in the URL fragment — never sent in any HTTP request ▼ open /share/ GET /api/files/ ◀────────────────────────── (server checks expiry + download cap, then ──────────────────────────▶ returns ciphertext + iv header) decrypt in-browser with key from the fragment → download plaintext ``` 密钥在浏览器中生成、导出,并**仅**放置在分享 URL 的片段中。片段不会在 HTTP 请求中传输,因此服务器永远看不到密钥。任何拥有 *完整*分享 URL(包括片段)的人都可以解密——请将完整链接视为机密。 ### 信封(CLI 和浏览器共享同一格式) CLI 和浏览器都生成具有相同结构的 AES-256-GCM 输出,因此由其中一方生成的密钥可以 打开另一方生成的密文: ``` { "version": 1, "iv": "", "ciphertext": "" } ``` - **密钥:** 256 位,base64url(无填充)。 - **IV:** 每次加密生成全新的 96 位随机值(对于给定的密钥绝不重用)。 - **认证标签:** 128 位,由 GCM 附加到密文后。解密时会对其进行验证,因此错误的密钥 *或*被篡改的文件都会安全失败并返回相同的消息——根据设计,你无法分辨具体是哪种情况。 ### 数据模型 `files(id PRIMARY KEY, stored_name, size_bytes, iv, created_at, download_count, expires_at, max_downloads)` - `id` 是 128 位的 `secrets.token_urlsafe` 熵——这个不可猜测的 id **就是**访问控制。 - `expires_at` / `max_downloads` 为 `NULL` 时表示“无限制”(因此旧的 v1 行读取不变;数据库在首次使用时自动迁移)。 ### HTTP API | 方法 | 路径 | 用途 | | --- | --- | --- | | `GET` | `/` | 浏览器上传/加密界面。 | | `POST` | `/api/files` | 存储加密的 blob + IV(已验证)。可选过期时间/下载上限。 | | `GET` | `/api/files` | 列出 blob 元数据。除非 `LOCKBOX_LANE_ENABLE_LISTING=true`,否则**仅限本地回环**。 | | `GET` | `/api/files/` | 下载密文;IV 在 `X-Lockbox-IV` 头中返回。强制执行过期时间+上限(失效后返回 `410`)。 | | `GET` | `/share/` | 浏览器解密/下载界面。 | ## 安装 ``` cd lockbox-lane python -m venv .venv # Windows: .venv\Scripts\activate POSIX: source .venv/bin/activate pip install -r requirements.txt pip install -e . # optional; provides the `lockbox-lane` entry point cp .env.example .env # optional; tune limits and paths ``` 不想进行可编辑安装?可以使用 `PYTHONPATH=src python -m lockbox_lane.cli …` 运行所有内容。 **要求:** Python 3.11+,以及 `flask`、`cryptography`、`rich`(已在上方安装)。浏览器端 需要任何支持 WebCrypto 的浏览器(所有现代浏览器都支持)。 ## CLI 用法 全局选项位于子命令**之前**:`--db ` 和 `--storage `。 渲染选项位于子命令**之后**:`--json`(向标准输出输出纯 JSON,无装饰), `--plain` / `--no-color`(无样式文本;自动遵循 `NO_COLOR` 和非 TTY 输出)。 每次调用都会打印一个简洁的品牌标题,然后是结果。`--json` 输出始终是 无任何装饰的纯 JSON,因此可以安全地通过管道传输。 ### `keygen` — 生成新密钥 ``` lockbox-lane keygen ``` ``` ╭───────────── new 256-bit key ─────────────╮ │ ZPjf_BR9vBBZ2tmKCfWIV2fC4siabkiBKzHYJKcj7M0 │ ╰────────────────────────────────────────────╯ Pre-share this out-of-band, then: encrypt-file --key ``` ### `encrypt-file` — 将文件加密到信封中 ``` lockbox-lane encrypt-file --infile report.pdf --outfile report.lockbox --key-out report.key ``` ``` ╭──────────────── encrypted ────────────────╮ │ input report.pdf │ │ plaintext 48.2 KB │ │ envelope report.lockbox (64.3 KB) │ ╰────────────────────────────────────────────╯ key written report.key (mode 0600 where supported) ``` - 省略 `--key` 可生成新密钥;提供 `--key` 可重用预共享密钥。 - `--key-out FILE` 将密钥写入 `0600` 权限的文件,并**确保其不会出现在标准输出中**。如果没有此参数, 密钥将在高亮面板中打印一次,并带有“请勿将其泄露到聊天/工单/日志中”的提醒。 - 除非你传递 `--force`,否则拒绝覆盖 `--outfile` / `--key-out`。 ### `decrypt-file` — 打开信封 ``` lockbox-lane decrypt-file --infile report.lockbox --outfile report.pdf --key "$(cat report.key)" ``` ``` ╭─────────── decrypted & verified ───────────╮ │ report.pdf (48.2 KB recovered) │ ╰─────────────────────────────────────────────╯ ``` 密钥错误或文件被修改都会安全失败:`error decryption failed: wrong key or the file was modified`(退出代码 1)。 ### `inspect` — 无需密钥检查信封 ``` lockbox-lane inspect --infile report.lockbox ``` ``` ╭──────────────── envelope ─────────────────╮ │ version 1 │ │ iv 12 bytes │ │ ciphertext 64.3 KB │ │ plaintext (est.) 64.3 KB │ ╰────────────────────────────────────────────╯ ``` ### `list` — 显示已存储的 blob ``` lockbox-lane --db shares.sqlite3 --storage uploads list ``` ``` stored encrypted blobs ┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓ ┃ id ┃ size ┃ downloads ┃ status ┃ expires ┃ created ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩ │ H_6JPLrOrlFncmO-OIVCsQ │ 4 B │ 1/1 │ exhausted │ — │ 2026-07-05T07:56:12 │ │ 6D3tLVnKuJ2fJkVUkzTvmA │ 6 B │ 0 │ active │ — │ 2026-07-05T07:56:12 │ └────────────────────────┴──────┴───────────┴─────────┴─────────┴─────────────────────┘ ``` 状态采用颜色编码:`active`(绿色)、`expired`(红色)、`exhausted`(黄色)。 `list --json` 输出原始行以供脚本使用。 ### `purge` — 删除已存储的 blob ``` lockbox-lane purge --expired # safe GC: only expired/exhausted blobs lockbox-lane purge # ALL blobs; prompts for confirmation lockbox-lane purge --yes # ALL blobs, no prompt (for scripts) ``` 删除*所有* blob 需要交互式确认 `yes`,或使用 `--yes`。在 `--json`/非交互模式下,如果没有 `--yes` 将会拒绝执行,而不是进行猜测。 ### `serve` — 运行分享 Web 应用 ``` lockbox-lane serve --host 127.0.0.1 --port 5068 ``` ``` ╭──────────────────── serving ─────────────────────╮ │ http://127.0.0.1:5068 │ │ db lockbox_lane.sqlite3 │ │ storage uploads │ │ ciphertext is stored at rest; keys never reach the │ │ server. Ctrl+C to stop. │ ╰────────────────────────────────────────────────────╯ ``` 打开 URL,选择一个文件(可选择设置过期时间和/或下载上限),点击 **Encrypt and upload**(加密并上传),然后复制生成的分享链接。在任何标签页或浏览器中打开该链接,然后点击 **Decrypt and download**(解密并下载)。 ## 安全与授权 - **默认仅限本地回环。** `serve` 绑定到 `127.0.0.1`。除非你传递 `--allow-public` 并承认你已获授权在该 网络上暴露它,否则将拒绝绑定任何非本地回环地址(例如 `0.0.0.0`)。`--debug`(它会启用 Werkzeug 调试器——这对任何能访问它的人来说等同于远程代码执行)在本地回环之外将被完全拒绝。 - **在任何实际部署中使用 HTTPS。** 本地 HTTP 仅用于实验室测试。请在前面放置一个 TLS 终结 反向代理,否则密文和 IV 将明文传输(在没有 密钥的情况下依然无法读取,但完整性/元数据需要 TLS 保护)。 - **将输入视为敌意内容。** 上传的 IV 在 存储之前会被验证为纯净的 12 字节 base64url(稍后它们会被回显到响应头中)。信封文件会经过防御性解析。 数据库中的 `stored_name` 受到保护以防止路径遍历。上传受到大小限制 (`LOCKBOX_LANE_MAX_UPLOAD_MB`)并按 IP 进行速率限制。 - **响应加固。** 每个响应都设置了 `Content-Security-Policy`(包含每次请求的脚本 nonce——没有 `unsafe-inline` 脚本)、`Referrer-Policy: no-referrer`(这样分享 URL 就永远不会泄露)、 `X-Content-Type-Options: nosniff`、`X-Frame-Options: DENY`,以及针对 密文的 `Cache-Control: no-store`。 - **元数据列表默认仅限本地回环**——远程调用者会收到 `404`,因此他们无法 枚举每一个分享 id。仅在你了解 暴露风险的情况下才启用 `LOCKBOX_LANE_ENABLE_LISTING=true`。 - **机密信息不会进入日志。** 密钥最多只打印一次(或写入 `0600` 权限的文件)。没有任何内容 会记录密钥,并且当密钥被写入文件时,`--json` 会完全隐藏该密钥。 - **此工具*无法*防范的情况:** 被攻破的端点、由 恶意主机提供的恶意 JavaScript,或任何你手动将完整分享 URL 交给的人。端到端加密将信任从 服务器转移到了端点和持有链接的人身上——它并没有消除信任。 ### 配置(环境变量 / `.env`) | 变量 | 默认值 | 含义 | | --- | --- | --- | | `LOCKBOX_LANE_DB` | `lockbox_lane.sqlite3` | SQLite 元数据库路径。 | | `LOCKBOX_LANE_STORAGE` | `uploads` | 加密 blob 目录。 | | `LOCKBOX_LANE_HOST` / `LOCKBOX_LANE_PORT` | `127.0.0.1` / `5068` | `serve` 绑定地址。 | | `LOCKBOX_LANE_MAX_UPLOAD_MB` | `100` | 最大上传大小。 | | `LOCKBOX_LANE_MAX_EXPIRY_MIN` | `43200` (30 天) | 客户端可请求的过期时间上限。 | | `LOCKBOX_LANE_UPLOAD_RATE` / `LOCKBOX_LANE_DOWNLOAD_RATE` | `30` / `240` | 每个 IP 每分钟的请求数。 | | `LOCKBOX_LANE_ENABLE_LISTING` | `false` | 向远程调用者公开 `GET /api/files`。 | ## 开发与测试 ``` cd lockbox-lane PYTHONPATH=src python -m pytest -q ``` 测试快速且依赖极少——没有网络请求,没有 sleep。它们涵盖了加密往返和 故障模式、密钥/IV/信封验证、过期和阅后即焚语义、路径遍历 防护,以及 Flask 应用(通过 `test_client`):IV 验证、安全头、耗尽分享时的 `410` 错误, 以及仅限本地回环的列表门禁。 快速手动冒烟测试: ``` echo "the eagle lands at noon" > sample.txt lockbox-lane encrypt-file --infile sample.txt --outfile sample.lockbox --key-out sample.key lockbox-lane inspect --infile sample.lockbox lockbox-lane decrypt-file --infile sample.lockbox --outfile sample.out --key "$(cat sample.key)" lockbox-lane serve --host 127.0.0.1 --port 5068 ``` ## 🏷️ 为什么叫“Lockbox Lane”? 就像一排保险箱所在的街道,只有你掌握唯一的钥匙。加密在你的浏览器中进行,在任何数据离开你的机器之前就已经完成,因此服务器存储的是它确实无法打开的密文。这是“我们不会查看你的文件”唯一诚实的版本——它不是隐私政策中的承诺,而是一种在架构上根本无法进行查看的设计。 ## 🔬 这个工具是如何构建的 **目的。** 一个值得信赖的端到端加密文件投递处,密钥永远不会 触及服务器——现在支持阅后即焚 / 过期分享以及 纵深防御,因此服务器确实只是一个密文储物柜。 **工作原理。** `encrypt` 生成密文信封和密钥;服务器 只负责存储和提供信封。下载操作以原子方式强制执行每个分享的过期时间和 下载上限,一旦分享过期或耗尽,就会返回 HTTP 410。 `keygen` 通过带外方式预共享密钥;`inspect` 在没有 密钥的情况下读取信封结构;`purge --expired` 对过期的 blob 进行垃圾回收。 **出色的 CLI。** 采用颜色编码的 `list` 表格(active=绿色,expired=红色, exhausted=黄色),显示人类易读的大小和已用/上限下载量,每个 子命令的结果面板,没有 `--force` 拒绝覆盖,以及在执行破坏性 `purge` 时进行交互式确认(使用 `--yes` 用于自动化)。 **主要改进。** *功能性:* 每个分享的 `--minutes` 过期时间和下载 上限以原子方式执行,实现真正的阅后即焚;`keygen` 和 `inspect` 子命令;SQLite schema 可就地自行迁移旧的 v1 数据库。*安全性:* `serve`绑定到本地回环,如果没有 `--allow-public` 则拒绝非本地回环,并且 调试器在本地回环之外被完全禁用;默认情况下仅限本地回环的元数据列表(关闭了 分享 id 枚举 / 密文收集漏洞);严格的 12 字节 base64url IV 验证,然后再将其回显到响应头中(阻止 header 走私);基于数据库存储名称的 路径遍历防护;基于 nonce 的 CSP, 针对密文的 `Cache-Control: no-store`,按 IP 进行速率限制;密钥最多打印 一次或写入 `0600` 权限的文件。 **示例。** ``` PYTHONPATH=src python -m lockbox_lane.cli list ``` ## ⚖️ 授权使用与安全章程 **这些是用于你拥有或被明确授权评估的系统、文件、网络和人员的防御性工具。** 在运行任何东西之前请阅读本文: - **授权不是可选的。** 网络钓鱼模拟、网络扫描、IP 信誉查询和 Web 应用探测都会触及他人的系统或 数据。请先获得书面授权。在 你声明授权之前,一些工具*拒绝执行*(`--yes`、`--authorized-training`、`--i-have-authorization`、 `--i-am-authorized` 等)。 - **默认安全。** 每个 Web UI 都绑定到 `127.0.0.1`(本地回环)。对外请求、 实时发送和主动扫描都受到显式标志的控制——试运行、 被动模式,或者拒绝并发出警告始终是默认设置。 - **没有意外的“自毁”操作。** Flask `--debug`(Werkzeug 交互式 调试器在任何 traceback 上都具备远程代码执行能力)会受到强烈警告,并且 在本地回环之外被完全拒绝。不受信任的输入受到大小限制、验证并 进行无危害渲染,因此带有恶意的文件或日志行不会导致崩溃——或接管—— 你的终端。 - **输出中不含机密信息。** API 密钥保留在请求头中,密码来自 环境变量,任何敏感信息都不会被记录或打印。 这些不是攻击性工具。它们不包含任何漏洞利用、凭据 收集器或任何 payload。如果某个工具*可能*被滥用,那么在设计上它就具备了抵抗这种滥用的能力。 ## 🧪 开发 ``` python -m venv .venv && source .venv/bin/activate pip install -e . pytest -q # 18 tests, no network, no sleeps lockbox-lane --help ``` ## 📄 许可证 基于 **MIT License** 发布。详见 [LICENSE](LICENSE)。
防御性工具。没有漏洞利用,没有 payload,没有凭据收集器。
标签:Python, 客户端加密, 文件共享, 文档结构分析, 无后门, 端到端加密, 逆向工具