{"id":50486959,"url":"https://github.com/systemslibrarian/crypto-lab-psi-gate","last_synced_at":"2026-06-01T23:03:00.985Z","repository":{"id":359836807,"uuid":"1215050618","full_name":"systemslibrarian/crypto-lab-psi-gate","owner":"systemslibrarian","description":"Browser-based Private Set Intersection demo implementing classic DH-PSI (Meadows 1986, Huberman-Franklin-Hogg 1999) over ristretto255 with RFC 9380 hash-to-curve. The primitive behind Signal contact discovery and Apple password monitoring.","archived":false,"fork":false,"pushed_at":"2026-05-23T16:58:55.000Z","size":23615,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T18:25:11.133Z","etag":null,"topics":["contact-discovery","crypto-lab","cryptography","ddh","dh-psi","diffie-hellman","hash-to-curve","noble-curves","privacy-preserving","private-set-intersection","psi","rfc-9380","ristretto255","secure-computation","secure-multi-party-computation","secure-two-party-computation","signal-protocol"],"latest_commit_sha":null,"homepage":"https://systemslibrarian.github.io/crypto-lab-psi-gate/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/systemslibrarian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T12:15:37.000Z","updated_at":"2026-05-23T16:59:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/systemslibrarian/crypto-lab-psi-gate","commit_stats":null,"previous_names":["systemslibrarian/crypto-lab-psi-gate"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/systemslibrarian/crypto-lab-psi-gate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-psi-gate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-psi-gate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-psi-gate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-psi-gate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/systemslibrarian","download_url":"https://codeload.github.com/systemslibrarian/crypto-lab-psi-gate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemslibrarian%2Fcrypto-lab-psi-gate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33797128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contact-discovery","crypto-lab","cryptography","ddh","dh-psi","diffie-hellman","hash-to-curve","noble-curves","privacy-preserving","private-set-intersection","psi","rfc-9380","ristretto255","secure-computation","secure-multi-party-computation","secure-two-party-computation","signal-protocol"],"created_at":"2026-06-01T23:02:58.773Z","updated_at":"2026-06-01T23:03:00.979Z","avatar_url":"https://github.com/systemslibrarian.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PSI Gate — Private Set Intersection\n\n[![CI](https://github.com/systemslibrarian/crypto-lab-psi-gate/actions/workflows/test.yml/badge.svg)](https://github.com/systemslibrarian/crypto-lab-psi-gate/actions/workflows/test.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![Node: 20 · 22](https://img.shields.io/badge/node-20%20%7C%2022-339933?logo=node.js\u0026logoColor=white)](./.github/workflows/test.yml)\n[![Test Vectors: PSI-GATE-v1](https://img.shields.io/badge/test_vectors-PSI--GATE--v1-blue)](./TEST_VECTORS.md)\n\n\u003e \"Whether therefore ye eat, or drink, or whatsoever ye do, do all to the glory of God.\"\n\u003e — 1 Corinthians 10:31\n\n## What It Is\n\nBrowser-based Private Set Intersection (PSI) demo implementing the classic\nDiffie-Hellman-based PSI protocol (Meadows 1986, Huberman-Franklin-Hogg 1999).\nTwo parties compute `A ∩ B` without revealing non-matching elements to each other.\n\nUses **ristretto255** via `@noble/curves` for DDH-hard group operations and\nRFC 9380-compliant hash-to-curve. Demonstrates the three-round interactive protocol,\nside-by-side comparison of what each party learns, and three realistic attack scenarios\n(set size inflation, dictionary attacks, scalar reuse) with honest discussion of PSI's\nlimitations. All cryptography runs in-browser — no backends, no servers.\n\n## When to Use It\n\n- Understanding the cryptographic primitive behind Signal contact discovery, Apple\n  password monitoring, and Google's Private Join and Compute\n- Teaching how two parties can compute a joint function without revealing inputs\n  (the essence of secure two-party computation)\n- Learning why the Decisional Diffie-Hellman (DDH) assumption matters for PSI\n  correctness and privacy\n- Evaluating PSI for contact discovery, password breach checking, ad attribution,\n  or healthcare data sharing applications\n\n**Not for:** production PSI implementations. This demo is semi-honest secure only and\ndoesn't include the rate limiting, proof-of-work, or set size hiding needed for\nreal deployment. Use Signal's OPRF-based PSI or Google's Private Join and Compute\nlibrary for production use.\n\n## Live Demo\n\nhttps://systemslibrarian.github.io/crypto-lab-psi-gate/\n\n## The DH-PSI Protocol\n\n```\nGroup G with generator g, prime order q (ristretto255).\nHash function H: {0,1}* → G  (hash-to-curve, RFC 9380)\n\nAlice has A = {a_1, ..., a_n}\nBob   has B = {b_1, ..., b_m}\n\nRound 1 (Alice):  Pick random α.  Send X_i = α·H(a_i) shuffled.\nRound 2 (Bob):    Pick random β.  Send Y_i = β·X_i and Z_j = β·H(b_j) shuffled.\nRound 3 (Alice):  Compute W_j = α·Z_j.  Intersection = {a_i : Y_i ∈ {W_j}}.\n```\n\n**Why it works:** Both α and β are applied to matched elements, giving the same\n`αβ·H(x)` regardless of order (DDH commutativity). Non-matched elements look random.\n\n## Six Exhibits\n\n| # | Exhibit | What you see |\n|---|---------|--------------|\n| 1 | Contact Discovery Problem | PrayerWarriors.Mobi scenario; naive vs PSI approach |\n| 2 | Protocol Walkthrough | Step-by-step with animated blinding/unblinding |\n| 3 | Live Simulator | Paste your own sets; run PSI instantly |\n| 4 | Attack Demos | Set size inflation, dictionary attack, scalar reuse, malformed-point injection, malicious OPRF publication |\n| 5 | Real-World Deployments | Signal, Apple, Google, DP3T, healthcare |\n| 6 | Cryptographer's Lab | Test vectors, wire transcript, benchmarks, security argument, PSI protocol comparison |\n\n### Cryptographer's Lab (Exhibit 6)\n\nFor reviewers and implementers who need byte-level rigor:\n\n- **Canonical test vectors** — fixed inputs (α seed = `…0007`, β seed = `…000b`,\n  A = `{alice,bob,mom}@example.com`, B = `{bob,mom,eve}@example.com`) produce a\n  deterministic trace. Any conforming DH-PSI/ristretto255 implementation must\n  reproduce every H(x), X_i, Y_i, Z_j, and W_j byte-for-byte.\n- **Wire-format transcript** — every ristretto point on the wire as a 32-byte\n  hex dump, color-coded by sender. Verifies linear O(n+m) communication.\n- **Benchmarks** — live measurement of `hashToPoint`, `scalarMul`,\n  `randomScalar`, and end-to-end PSI at multiple set sizes in your browser.\n- **Simulator-based security argument** — sketches of the simulators for\n  corrupt Alice and corrupt Bob under DDH; honest list of what this\n  implementation is NOT (constant-time, malicious-secure, side-channel hardened,\n  formally verified).\n- **Protocol comparison** — DH-PSI vs OPRF-PSI vs KKRT16 vs CM20 vs PaXoS/VOLE-PSI\n  vs FHE-PSI, with communication, computation, security model, and year.\n\n## What Can Go Wrong\n\n- **Set sizes are revealed.** Both parties learn how many elements the other has.\n  Hiding set sizes requires more sophisticated protocols (PaXoS, CM20).\n\n- **Dictionary attacks work against small domains.** If elements come from a small\n  domain (phone numbers, PINs), an attacker can enumerate the entire space and learn\n  your full set. Real deployments add rate limiting, proof-of-work, or OPRF.\n\n- **Scalar reuse is catastrophic.** If Alice reuses α across sessions with Bob, Bob\n  can link sessions and detect which elements changed. Fresh α per session is mandatory.\n\n- **Semi-honest security only.** The protocol assumes both parties follow it honestly.\n  An actively malicious party can deviate — submit malformed points, reuse scalars\n  intentionally, or lie about results. Malicious-security PSI requires additional ZK proofs.\n\n- **Inherent information leakage.** Even a perfect PSI tells Alice which of her elements\n  are in Bob's set. That fact alone may be sensitive depending on context.\n\n## Real-World Usage\n\nThe DH-PSI protocol dates to Meadows 1986 and was analyzed by Huberman, Franklin, and\nHogg (1999). Production deployments:\n\n- **Signal** — contact discovery via SGX enclave + OPRF-based PSI\n- **Apple iOS 14+** — Password Monitoring against breach databases\n- **Google Password Checkup** — 4B+ leaked credentials, blind hashing + k-anonymity\n- **Google Private Join and Compute** — ad conversion attribution (open-source)\n- **Meta Private Lift** — advertising measurement without user-level data sharing\n- **DP3T / Google-Apple Exposure Notification** — COVID contact tracing\n- **Healthcare** — cross-hospital duplicate billing detection\n\nModern high-performance PSI (KKRT16, PaXoS, VOLE-PSI) builds on oblivious PRF\nfrom oblivious transfer. The group used here (ristretto255) is the same prime-order\nabstraction behind Signal Double Ratchet and X25519.\n\n## Stack\n\n- **Vite + TypeScript strict** — `noUnusedLocals`, `noUnusedParameters`, full strict mode\n- **`@noble/curves`** — ristretto255 via `ristretto255_hasher` (RFC 9380 hash-to-curve, RFC 9496 ristretto encoding)\n- **Vitest + GitHub Actions** — golden test vectors, randomized property tests, CI on Node 20 + 22\n- **Web Worker offload** — `src/psi-worker.ts` keeps the UI responsive during 1k+ PSI runs and DDH sampling\n- **CSP-hardened** — hash-pinned inline script, no remote sources, `worker-src 'self' blob:`\n- **No backends, no server** — GitHub Pages static deployment\n- **No `Math.random()`** — all randomness via `crypto.getRandomValues`\n\n## Protocols\n\nTwo interoperating protocols are implemented and can be toggled in Exhibit 3:\n\n- **DH-PSI** (`src/psi.ts`) — the three-round Meadows/HFH protocol; pedagogical baseline.\n- **OPRF-PSI** (`src/oprf-psi.ts`) — Jarecki-Liu 2010; what Signal contact discovery uses\n  in spirit. Bob publishes PRF tags once, Alice queries with a per-query α, unblinds with α⁻¹.\n\n## Testing\n\n```\nnpm test          # Vitest run (26 tests: group ops, DH-PSI, OPRF-PSI, attacks, test vectors)\nnpm run test:watch\n```\n\nCI runs on every push/PR via `.github/workflows/test.yml`:\ntypecheck → tests → production build, on Node 20 and 22.\n\n## Related Crypto Labs\n\n```\ncrypto-lab-opaque-gate       — aPAKE (authentication, related primitive)\ncrypto-lab-silent-tally      — private aggregation\ncrypto-lab-blind-oracle      — TFHE (general-purpose PSI via FHE)\ncrypto-lab-oblivious-shelf   — PIR (private information retrieval)\ncrypto-lab-patron-shield     — privacy-preserving analytics\ncrypto-lab-paillier-gate     — Paillier (used in some PSI variants)\ncrypto-lab-ot-gate           — oblivious transfer (used in OPRF-PSI)\n```\n\n## GitHub Topics\n\n`cryptography` `private-set-intersection` `psi` `secure-computation`\n`contact-discovery` `ristretto255` `diffie-hellman` `ddh` `signal-protocol`\n`privacy-preserving` `browser-demo` `educational` `typescript` `vite`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-psi-gate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-psi-gate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemslibrarian%2Fcrypto-lab-psi-gate/lists"}