EdwardAThomson/Private-Set-Intersection
GitHub: EdwardAThomson/Private-Set-Intersection
基于 ristetrotto255 和 Blake3 的隐私集合求交协议 C++ 实现,提供 CLI、HTTP 服务及 React 前端集成,支持两方在不泄露明文的前提下计算集合交集。
Stars: 1 | Forks: 0
# 隐私集合求交 (PSI) C++
PSI 协议参考实现的 C++ 移植版,基于 libsodium (ristretto255, XSalsa20-Poly1305) 和 Blake3 C 实现构建,包含确定性测试、CLI 工具以及用于 UI 集成的 HTTP endpoint。
该项目遵循 JavaScript 演示的四阶段工作流。两个实现最初都将元素哈希到曲线,形式为 `H(x)·G`(这是一个已知的离散对数,允许一方在离线状态下枚举另一方的集合),并将明文元素与盲化值一起发送。这两个缺陷在此处均已修复(参见 `docs/security_hardening.md`),并且相同的修复也已移植到 JS 仓库中([psi-demo PR #1](https://github.com/EdwardAThomson/psi-demo/pull/1)):现在两者都使用 ristretto255 的 hash-to-group、成员标签以及无明文的传输消息。`reference/` 下打包的旧版 JS 代码早于这些修复,仅保留作为可视化辅助工具。
之前版本的代码(JS 版)包含在此处,但也单独存在于 GitHub 上:https://github.com/EdwardAThomson/psi-demo。

## 功能
- 通过 ristretto255 `from_hash` 进行 hash-to-group(Elligator 2,未知离散对数),H2 密钥派生,以及基于 Blake3 的确定性随机派生。
- 默认使用 Tag 模式:Bob 发送单向 BLAKE3 成员标签,因此最终确定为 O(A) 次哈希查找;authenticated-secretbox 变体仍然可用(`runPSIProtocol`)。
- 传输消息仅包含盲化点和固定大小的标签(或在 secretbox 模式下的认证密文);没有任何明文元素会离开参与方。
- 面向阶段的 PSI API (`psi_protocol`),提供换行符和 JSON 序列化辅助工具。
- `psi_demo`:示例单元的 CLI 演示,打印明文值、序列化 payload 以及各阶段的耗时。
- `psi_server`:提供 `POST /psi` 的 HTTP 服务,返回可直接用于 React 集成的 JSON payload 和耗时指标。
- GoogleTest 套件涵盖辅助函数行为、序列化往返、PSI 流程和错误处理。
- 用于可见性单元格的多级网格编码,镜像原始的 JavaScript 前端。
- 对 Web Worker 友好的 HTTP 层,确保浏览器在运行 C++ PSI 后端时保持响应。
## 构建
```
cmake -S . -B build
cmake --build build
cd build && ctest # run tests
```
## 运行 CLI 演示
```
./build/psi_demo
```
## 运行 HTTP 服务器
```
./build/psi_server
```
# 监听 http://localhost:8080/psi (POST)
## 运行 React 前端
1. 从仓库根目录构建或启动 `psi_server`(见上文)。
2. 在第二个终端中,启动纯 C++ 的 React 演示:
cd reference_cpp_only
npm install # 仅第一次
npm start
应用将在 http://localhost:3000 打开,并将 PSI 请求代理到 `http://localhost:8080/psi`。要更改后端 URL,请在运行 `npm start` 之前设置 `REACT_APP_PSI_ENDPOINT`,或者在 `public/index.html` 中赋值 `window.__PSI_SERVER_ENDPOINT__`。
3. 如果您需要原始的基于 worker 的回退方案,旧版 JavaScript 演示仍保留在 `reference/` 中。
## HTTP API
### 请求
```
POST /psi
Content-Type: application/json
{
"bob_units": [{"id": "u1", "x": 100.0, "y": 100.0}, ...],
"alice_units": [{"id": "a1", "x": 150.0, "y": 150.0}, ...]
}
```
### 响应
```
{
"bob_message": {"items": [{"tag": ""}, ...]},
"alice_message": {"items": [{"blindedPoint": ""}, ...]},
"bob_response": {"items": [{"transformedPoint": ""}, ...]},
"intersection": ["450 450", ...],
"timings_ms": {
"bob_setup": ,
"alice_setup": ,
"bob_response": ,
"alice_finalize":
}
}
```
## React 集成草图
```
async function runPsi(bobUnits, aliceUnits) {
const res = await fetch('http://localhost:8080/psi', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ bob_units: bobUnits, alice_units: aliceUnits })
});
if (!res.ok) throw new Error('PSI request failed');
return res.json();
}
```
## 威胁模型
该协议针对诚实且好奇的参与方是隐私的。恶意参与方可以伪造其输入集,并将该协议用作成员资格预言机:它可以得知其选择探测的任何元素是否存在于诚实参与方的集合中,而诚实参与方无法区分探测行为与真实输入。集合的基数也会从消息数量中泄露。将输入绑定到先前的承诺(争议解决)以及将集合填充到固定大小的功能已在 `ROADMAP.md` 中追踪。
## 报告与文档
- `reports/psi_demo_report.md`:包含 payload 和耗时的 CLI 示例运行。
- `reports/progress_2025-10-16.md`:每日进度摘要。
- `docs/porting_plan.md`:路线图、里程碑和 API 参考。
## 前端变体
- `reference/`:旧版 React 演示,带有自动的 JavaScript worker 回退。
- `reference_cpp_only/`:纯 C++ 的 React 演示,通过轻量级 Web Worker 将 PSI 请求转发到后端,在 UI 中展示服务器耗时,并拒绝回退到原始的浏览器实现。
## 许可证
有关上游库各自许可证的信息,请参阅它们(libsodium、Blake3 C 实现)。
标签:Bash脚本, C++, Ristretto255, Web服务, 密码学, 手动系统调用, 数据可视化, 数据擦除, 私密集合求交, 隐私计算