Skip to content

EdwardAThomson/Private-Set-Intersection

Repository files navigation

Private Set Intersection (PSI) C++

C++ port of the PSI protocol reference implementation. The project mirrors the JavaScript workflow (reference/psiCalculation.js) using OpenSSL, libsodium, and the Blake3 C implementation, while adding deterministic tests, CLI tooling, and an HTTP endpoint for UI integration.

The previous version of the code (in JS) is included here, but also separately on GitHub: https://github.com/EdwardAThomson/psi-demo.

Screenshot

Features

  • Hash-to-group, H2, ChaCha20-Poly1305, and Blake3-based random derivation aligned with the JS reference.
  • Phase-oriented PSI API (psi_protocol) with both newline and JSON serialization helpers.
  • psi_demo: CLI walkthrough of sample units, printing plaintext values, serialized payloads, and per-phase timings.
  • psi_server: HTTP service exposing POST /psi, returning JSON payloads and timing metrics ready for React integration.
  • GoogleTest suite covering helper behaviour, serialization round-trips, PSI flows, and error handling.
  • Multi-level grid encoding for visibility cells, mirroring the original JavaScript frontend.
  • Web Worker-friendly HTTP layer so browsers stay responsive while the PSI backend runs in C++.

Building

cmake -S . -B build
cmake --build build
cd build && ctest   # run tests

Running the CLI Demo

./build/psi_demo

Running the HTTP Server

./build/psi_server

listens on http://localhost:8080/psi (POST)

Sandbox note: opening sockets is blocked in some restricted environments; run the server on an unrestricted machine.

Running the React Frontend

  1. Build or start psi_server from the repo root (see above).
  2. In a second terminal, launch the C++-only React demo:
    cd reference_cpp_only
    npm install          # first time only
    npm start
    The app opens at http://localhost:3000 and proxies PSI requests to http://localhost:8080/psi. To change the backend URL, set REACT_APP_PSI_ENDPOINT before running npm start or assign window.__PSI_SERVER_ENDPOINT__ in public/index.html.
  3. The legacy JavaScript demo remains in reference/ if you need the original worker-based fallback.

HTTP API

Request

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}, ...]
}

Response

{
  "bob_message": {"items": [...]},
  "alice_message": {"items": [...]},
  "bob_response": {"items": [...]},
  "decrypted": ["450 450", ...],
  "timings_ms": {
    "bob_setup": <double>,
    "alice_setup": <double>,
    "bob_response": <double>,
    "alice_finalize": <double>
  }
}

React Integration Sketch

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();
}

Reports & Docs

  • reports/psi_demo_report.md: sample CLI run with payloads and timings.
  • reports/progress_2025-10-16.md: daily progress summary.
  • docs/porting_plan.md: roadmap, milestones, and API references.

Front-End Variants

  • reference/: legacy React demo with automatic JavaScript worker fallback.
  • reference_cpp_only/: C++-only React demo that forwards PSI requests through a lightweight Web Worker to the backend, exposes server timings in the UI, and refuses to fall back to the original browser implementation.

Licenses

Refer to upstream libraries for their respective licenses (OpenSSL, libsodium, Blake3 C implementation).