MidnightLogic/PieceKeeper
GitHub: MidnightLogic/PieceKeeper
基于 Shamir 秘密共享算法的离线单文件 PWA,将敏感秘密拆分为多个份额以消除单点故障风险。
Stars: 0 | Forks: 0
Distribute secrets. Eliminate single points of failure.
An offline-first implementation of Shamir's Secret Sharing, split across a standalone NPM crypto module and a single-file PWA.
[](https://www.npmjs.com/package/@midnightlogic/piecekeeper-crypto)
[](https://github.com/MidnightLogic/PieceKeeper)
[](https://github.com/MidnightLogic/PieceKeeper/blob/main/LICENSE)



PieceKeeper 允许你获取一个敏感秘密——例如主密码、加密货币助记词或私钥——并在数学上将其拆分为多个独立的**份额 (shares)**。你可以定义一个阈值(例如,“5 个份额中的任意 3 个”),并且只有当凑齐最少数量的份额时才能重建该秘密。少于此数量将无法获取任何信息。
份额可以作为可打印的 **QR 码**分发,写入到 **NFC 标签**,或保存为纯**文本**。可选的双因素密码增加了第二层保护,因此仅物理持有份额不足以解码秘密。
## 📦 Monorepo 架构
本仓库结构化为包含两个包的 NPM workspace:
```
PieceKeeper/
├── packages/
│ ├── core/ → @midnightlogic/piecekeeper-crypto (standalone NPM module)
│ └── pwa/ → PieceKeeper PWA (Vite single-file application)
├── package.json (workspace root)
└── LICENSE
```
| 包 | 描述 |
|---|---|
| [`packages/core`](packages/core/) | 同构的 Shamir 秘密共享 + AES-256-GCM 加密。零 DOM 依赖。提供 ESM、CJS 和 TypeScript 声明。 |
| [`packages/pwa`](packages/pwa/) | 完整的 PieceKeeper 渐进式 Web 应用 — 摄像头扫描、NFC、QR 码生成、21 种语言和离线优先架构。 |
## 🌐 托管版本
通过 GitHub Pages 提供预编译的部署:
**[启动 PieceKeeper →](https://midnightlogic.github.io/PieceKeeper/)**
## 💡 常见用例
* **紧急访问账户:** 将特权管理员或 root 凭据拆分给多个团队负责人(例如,5 选 3)。只有当达到所需阈值的授权人员聚集在一起时,账户才能被激活——在执行双重控制的同时消除了单点泄密的风险。
* **遗产规划与继承:** 将加密钱包的助记词在家庭成员和律师之间进行拆分。只有当达到所需阈值的各方聚集在一起时,才能访问资金——任何单个人都无法单独采取行动。
* **地理分布:** 拆分一个主备份密码,并将份额存储在不同的物理位置:家用保险箱、银行保险库和安全的办公室。如果一个位置遭到破坏,秘密依然受到保护。
* **分布式团队访问:** 将关键的服务器密码或 API 密钥拆分给 5 名高管,要求至少 3 人同意才能解锁。任何单个人都不拥有单方面的访问权限。
## ✨ 特性
* **灵活的阈值(K of N):** 将秘密拆分为最多 64 个份额,并可以定义任意阈值(例如,5 选 3,8 选 4)。
* **双因素密码保护:** 可选择使用主密码对份额进行加密。重建时需要同时提供物理份额和密码。
* **QR 码生成与扫描:** 为每个份额生成可打印的 QR 码。使用内置的摄像头扫描器将其扫描回来——无需键盘输入。
* **NFC 标签支持:** 将份额直接写入 NFC 标签,并通过简单的触碰读回。非常适合硬件级别的分发。(注意:NFC 功能目前仅在 Android 版 Chrome 上受支持)。
* **打印就绪的 PDF 布局:** 一键打印,包含份额元数据、QR 码和格式清晰的说明。
* **21 种语言:** 完全国际化的界面,涵盖英语、西班牙语、法语、德语、意大利语、荷兰语、波兰语、葡萄牙语、俄语、土耳其语、阿拉伯语、印地语、孟加拉语、泰语、越南语、印度尼西亚语、日语、韩语、希伯来语和中文(简体 + 繁体)。
* **渐进式 Web 应用:** 可作为独立应用安装在 iOS 和 Android 上,具有完整的离线功能。
* **暗黑模式、音频反馈、触觉反馈、RTL 支持:** 可配置主题、可选的 UI 声音、触觉反馈,以及针对阿拉伯语和希伯来语的从右到左布局。
* **桌面宽度切换:** 可在紧凑的应用程序式布局和宽大的桌面布局之间切换,并保留偏好设置。
* **内置诊断套件:** 运行内部加密自检,以在生成份额之前验证设备的兼容性。
## 🔒 核心理念
* **单文件,零依赖:** 构建过程将所有应用程序逻辑、加密库、样式表、翻译和图标编译成一个便携的 HTML 文件。将其存储在 USB 驱动器上,打印在纸上,或保管在任何地方的保险库中。
* **天生离线:** PieceKeeper 发出零网络请求。你的数据永远不会离开你的设备。无论你连接到互联网还是完全处于气隙隔离环境,该应用程序的功能都完全相同。
* **无秘密持久化:** 秘密和份额从不写入磁盘、`IndexedDB` 或 cookies。只有用户偏好(主题、语言、布局)存储在 `localStorage` 中。当你关闭标签页时,所有加密材料都会消失。
## 📦 `@midnightlogic/piecekeeper-crypto`
加密核心作为独立的 NPM 包发布,供你自己的应用程序使用:
```
npm install @midnightlogic/piecekeeper-crypto
```
### 拆分秘密
```
import { splitSecret } from '@midnightlogic/piecekeeper-crypto';
const shares = await splitSecret('my-secret-password', 5, 3, '', 'backup-key');
// → 5 shares, any 3 can reconstruct
```
### 重建秘密
```
import { reconstructSecret } from '@midnightlogic/piecekeeper-crypto';
const result = await reconstructSecret(shares.slice(0, 3), '');
console.log(result.secret); // "my-secret-password"
```
### 检查份额
```
import { inspectShare } from '@midnightlogic/piecekeeper-crypto';
const meta = inspectShare(shares[0].Share);
console.log(meta.isEncrypted); // false
console.log(meta.familyId); // "a1b2c3d4"
```
## 🔐 密码学
* **Shamir 秘密共享 (SSS):** 在 5 层素数伽罗瓦域(128 位到 2048 位)上生成多项式份额,提供低于阈值的信息理论安全性。
- **动态素数选择(默认):** 自动选择适合秘密的最小素数,从而最小化份额大小和 QR 码密度。
- **隐身模式(高级):** 强制所有份额使用最大的 2048 位素数,并使用零填充有效载荷,产生统一长度的份额,不泄露关于秘密实际大小的任何信息。
* **密钥派生函数:** 该应用程序附带六个可配置的 KDF 配置文件:
- **Argon2id** — 内存密集型,OWASP 推荐。配置文件为 19MB(移动设备)和 64MB(默认)。
- **scrypt** — 内存密集型的传统替代方案,符合 OWASP 基线标准 (N=131072)。
- **PBKDF2** — CPU 密集型,符合 FIPS-140 标准。可配置 100k 到 2M 次迭代,使用 SHA-256/SHA-512。
* **加密:** 所有受密码保护的份额均采用 AES-256-GCM 认证加密。
* **防篡改份额:** 每个份额都是一个自描述的 Base64 信封,包含 schema 版本、集合标识符、时间戳和 N/K 参数。
* **内容安全策略:** 生产构建将 SHA-256 脚本哈希注入到 CSP 标头中,在不依赖 `unsafe-eval` 的情况下阻止任意代码执行。Frame-ancestors、form-action 和 base-uri 均被锁定。
* **XSS 防护:** 所有用户提供的数据(评论、份额字符串、元数据)在任何 HTML 渲染之前都会通过 `escapeHtml()` 进行转义。
点击展开:份额二进制格式、素数域、多项式算术和完整性校验和
#### 伽罗瓦域与素数表
所有 Shamir 算术均在 GF(p) 中以素数 `p` 为模执行。PieceKeeper 使用一个 **5 层素数解析表**,其中每个素数是严格大于 `2^(B×8)` 的最小验证素数:
| 层级 | 边界 (B) | 素数 | 位宽 | 典型用途 |
|------|:-------------|:---------------------|:----------|:-------------------------------|
| 0 | 16 字节 | 2¹²⁸ + 51 | 128 位 | 短密码(≤16 字节) |
| 1 | 32 字节 | 2²⁵⁶ + 297 | 256 位 | 标准密码(≤32 字节) |
| 2 | 64 字节 | 2⁵¹² + 75 | 512 位 | 助记词(≤64 字节) |
| 3 | 128 字节 | 2¹⁰²⁴ + 643 | 1024 位 | 扩展秘密(≤128 字节) |
| 4 | 256 字节 | 2²⁰⁴⁸ + 981 | 2048 位 | 最大 / 隐身模式 |
**动态素数选择(默认):** 引擎选择边界 `B` 能够容纳原始有效载荷长度(`1 + 1 + secretLen + 4` 字节)的最小层级,以最小化份额输出大小和 QR 码密度。
**隐身模式(高级):** 无论秘密长度如何,强制所有份额使用层级 4(2048 位)。有效载荷被零填充至完整的 256 字节边界,产生统一长度的份额,不会泄露有关秘密实际大小的任何信息。
#### 秘密有效载荷构造
在进行多项式求值之前,原始秘密会被封装在一个完整性信封中:
```
[0x01 marker] [1-byte secretLen] [secretBytes...] [4-byte SHA-256 checksum] [0x00 padding...]
```
- **标记(1 字节):** 固定的 `0x01` 哨兵值,用于重建后的验证。
- **长度前缀(1 字节):** 编码用户秘密的精确字节长度,以便在重建后进行精确提取。
- **秘密字节:** UTF-8 编码的用户秘密(最多 250 字节)。
- **校验和(4 字节):** 原始秘密字节的截断 SHA-256。在重建期间用于检测损坏或被篡改的份额。
- **填充(仅限隐身模式):** 用零字节填充至素数边界。
然后,此字节数组被转换为一个 BigInt `S` ——即多项式的秘密项(`a₀`)。
#### 多项式求值
对于阈值 `K`,引擎生成一个度为 `K-1` 的随机多项式:
```
f(x) = a₀ + a₁x + a₂x² + ... + aₖ₋₁xᵏ⁻¹ (mod p)
```
其中 `a₀ = S`(即秘密),而 `a₁...aₖ₋₁` 是通过 `crypto.getRandomValues()` 在 `[1, p-1]` 范围内生成的密码学随机系数。每个份额 `i` 即为点 `(i, f(i) mod p)`。
#### 拉格朗日插值(重建)
给定 `K` 个点 `(x₁, y₁) ... (xₖ, yₖ)`,秘密 `S = f(0)` 可通过以下方式恢复:
```
S = Σᵢ yᵢ · Lᵢ(0) (mod p)
Lᵢ(0) = Πⱼ≠ᵢ (0 - xⱼ) / (xᵢ - xⱼ) (mod p)
```
除法通过使用扩展欧几里得算法的模乘逆元进行计算。
#### 份额二进制信封 (Schema v2.0)
每个份额都是一个自描述的二进制数据包,编码为 Base64URL:
```
┌──────────────────── AAD (Authenticated Additional Data) ─────────────────────┐
│ [2B version] [1B flags] [1B kdfSchema] [4B timestamp] [4B familyId] [2B commentLen] [commentBytes...] │
└──────────────────────────────────────────────────────────────────────────────┘
┌──── Payload (encrypted if 2FA enabled, plaintext otherwise) ────┐
│ [1B N] [1B K] [1B X-coordinate] [variable: Y-coordinate bytes] │
└─────────────────────────────────────────────────────────────────┘
```
**标志位字节掩码:**
- 位 0:`isEncrypted`(已应用双因素密码)
- 位 1:`isStealth`(启用均匀填充)
- 位 2-4:`primeIndex`(0–4,选择所使用的素数层级)
AAD 元数据始终为明文(未加密),以便可以在没有密码的情况下检查份额。当启用双因素时,内部有效载荷(N, K, X, Y)将通过 AES-256-GCM 进行加密。
#### 双因素加密管道
当提供密码时:
1. **盐值生成:** 来自 `crypto.getRandomValues()` 的 16 个字节。
2. **密钥派生:** 密码在专用的 Web Worker 线程中通过用户选择的 KDF(Argon2id / scrypt / PBKDF2)进行拉伸。
3. **加密:** 内部有效载荷 + AAD 使用 AES-256-GCM 密封。12 字节的 IV 被前置到密文中。
4. **解密:** 在重建期间,会从密码 + 盐值重新派生相同的 KDF,并且 GCM 标签在释放内部坐标之前对密文和 AAD 进行认证。
#### 内存安全
在每次加密操作之后,所有中间字节数组(`passwordBytes`、`secretBytes`、`checksumBytes`、多项式系数)都会通过 `.fill(0)` 进行清零。这最大程度地减少了敏感材料存在于 JavaScript 堆内存中的时间窗口。
## 📖 工作流程
#### 拆分秘密
1. 导航到 **生成** 选项卡。
2. 输入你的秘密文本并设置评论(可选)。
3. 选择份额总数 (N) 和重建阈值 (K)。
. 可选择启用双因素密码保护。
5. 点击 **生成份额**。加密引擎在后台线程运行,以保持 UI 响应。
6. 分发生成的份额:复制为文本,打印为 QR 码,下载为 CSV,或写入 NFC 标签。
#### 重建秘密
1. 导航到 **重建** 选项卡。
2. 使用以下任意组合方式输入份额:手动粘贴、QR 码扫描、NFC 标签触碰或文件上传。
3. 一旦达到最小阈值 (K),如果使用了双因素密码,则提供该密码。
4. 点击 **重建** 以显示原始秘密。
## 📱 设备支持
* **桌面端:** Chrome、Firefox、Safari 和 Edge。可作为桌面 PWA 安装。
* **移动端:** iOS Safari 和 Android Chrome。摄像头和 NFC 功能需要 HTTPS 或 localhost 环境。
* **离线:** 一旦作为 PWA 安装,该应用程序即可在没有任何网络连接的情况下工作。
## 🛠️ 本地开发
PieceKeeper 使用 NPM workspaces。所有命令均从仓库根目录运行。
### 1. 克隆并安装
```
git clone https://github.com/MidnightLogic/PieceKeeper.git
cd PieceKeeper
npm install
```
### 2. 开发服务器
构建核心模块,然后启动带有热重载功能的 PWA 开发服务器:
```
npm run dev
```
### 3. 生产构建
构建两个包(Core → PWA)并将所有内容编译到 `packages/pwa/dist/index.html` 中:
```
npm run build
```
### 4. 运行核心测试
```
npm run test
```
## 🚦 本地 HTTPS 测试
要测试需要安全上下文的硬件功能(摄像头、NFC)而无需部署到服务器:
```
npm run build
npm run preview:tunnel
```
这将启动一个本地服务器并创建一个临时的 HTTPS 隧道,允许你通过本地网络在移动设备上进行测试。
注意:由于该应用程序为 GitHub Pages 路由进行了配置,因此你必须在终端中提供的临时隧道 URL 末尾附加 /PieceKeeper/(例如,`https://[your-tunnel-url]/PieceKeeper/`)。
## 🔐 安全性
有关我们的漏洞披露政策,请参阅 [SECURITY.md](SECURITY.md)。
## 📜 许可证
Apache 2.0 许可证。详见 [LICENSE](LICENSE)。
标签:2FA, Cilium, IPv6支持, NFC, NPM, PWA, Shamir秘密共享, StruQ, Vite, 二维码, 加密, 加密货币, 助记词备份, 单文件HTML, 双因素认证, 安全, 安全助手, 密码学, 密钥分片, 开源, 手动系统调用, 数字资产保护, 数据可视化, 消除单点故障, 渐进式Web应用, 漏洞扫描器, 离线应用, 私钥管理, 秘密共享, 自定义脚本, 超时处理, 门限密码学