{"id":28458737,"url":"https://github.com/openmined/psi","last_synced_at":"2025-12-15T18:26:27.275Z","repository":{"id":37723506,"uuid":"257624745","full_name":"OpenMined/PSI","owner":"OpenMined","description":"Private Set Intersection Cardinality protocol based on ECDH and Bloom Filters","archived":false,"fork":false,"pushed_at":"2025-06-19T08:46:21.000Z","size":2231,"stargazers_count":142,"open_issues_count":3,"forks_count":39,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-06-19T09:42:28.321Z","etag":null,"topics":["c","cpp","golang","javascript","private-set-intersection"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenMined.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"openmined","open_collective":"openmined"}},"created_at":"2020-04-21T14:38:20.000Z","updated_at":"2025-06-17T20:10:38.000Z","dependencies_parsed_at":"2024-06-18T21:12:51.020Z","dependency_job_id":"225e153a-587d-41af-80f0-7638c6660f44","html_url":"https://github.com/OpenMined/PSI","commit_stats":{"total_commits":199,"total_committers":14,"mean_commits":"14.214285714285714","dds":0.6783919597989949,"last_synced_commit":"b6948f2124ef91e7808dfcfad6acdc050c0536e3"},"previous_names":["openmined/psi-cardinality"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/OpenMined/PSI","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenMined%2FPSI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenMined%2FPSI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenMined%2FPSI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenMined%2FPSI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenMined","download_url":"https://codeload.github.com/OpenMined/PSI/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenMined%2FPSI/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263111408,"owners_count":23415446,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["c","cpp","golang","javascript","private-set-intersection"],"created_at":"2025-06-07T00:39:40.819Z","updated_at":"2025-12-15T18:26:27.215Z","avatar_url":"https://github.com/OpenMined.png","language":"C++","readme":"![om-logo](https://github.com/OpenMined/design-assets/blob/master/logos/OM/horizontal-primary-trans.png)\n\n[![CD](https://github.com/OpenMined/PSI/actions/workflows/CD.yml/badge.svg?event=release)](https://github.com/OpenMined/PSI/actions/workflows/CD.yml)\n![License](https://img.shields.io/github/license/OpenMined/PSI)\n![OpenCollective](https://img.shields.io/opencollective/all/openmined)\n\n# PSI\n\nPrivate Set Intersection protocol based on ECDH and Golomb Compressed Sets or\nBloom Filters.\n\n## Protocol\n\nThe Private Set Intersection (PSI) protocol involves two parties, a client and a\nserver, each holding a dataset. The goal of the protocol is for the client to\ndetermine the intersection between their dataset and the server's dataset,\nwithout revealing any information about their respective datasets to each other.\n\nThe protocol proceeds as follows:\n\n1. Setup (server)\n\nThe server encrypts all its elements `x` under a commutative encryption scheme,\ncomputing `H(x)^s` where `s` is its secret key. The encrypted elements are then\ninserted into a container and sent to the client in the form of a serialized\nprotobuf and resembles* the following:\n\n```\n[ H(x_1)^(s), H(x_2)^(s), ... , H(x_n)^(s) ]\n```\n\n2. Request (client)\n\nThe client encrypts all their elements `x` using the commutative encryption\nscheme, computing `H(x)^c`, where `c` is its secret key. The client sends its\nencrypted elements to the server along with a boolean flag,\n`reveal_intersection`, indicating whether the client wants to learn the elements\nin the intersection or only its size (cardinality). The payload is sent as a\nserialized protobuf and resembles* the following:\n\n```\n[ H(x_1)^(c), H(x_2)^(c), ... , H(x_n)^(c) ]\n```\n\n3. Response (server)\n\nFor each encrypted element `H(x)^c` received from the client, the server\nencrypts it again under the commutative encryption scheme with its secret key\n`s`, computing `(H(x)^c)^s = H(x)^(cs)`. The result is sent back to the client\nin a serialized protobuf and resembles* the following:\n\n```\n[ H(x_1)^(cs), H(x_2)^(cs), ... , H(x_n)^(cs) ]\n```\n\n4. Compute intersection (client)\n\nThe client decrypts each element received from the server's response using its\nsecret key `c`, computing `(H(x)^(cs))^(1/c) = H(x)^s`. It then checks whether\neach decrypted element is present in the container received from the server, and\nreports the number of matches as the intersection size.\n\nIt's worth noting that the protocol has several variants, some of which\nintroduce a small false-positive rate, while others do not generate false\npositives. This behavior is selective, and the false-positive rate can be tuned.\nThe selection has implications on communication costs as well.\n\n__NOTE resembles*__: The protocol has configurable **containers**. Golomb\nCompressed Sets (`Gcs`) is the default container but it can be overridden to be\n`BloomFilter` or `Raw` encrypted strings. `Gcs` and `BloomFilter` will have\nfalse positives whereas `Raw` will not. Using `Raw` increases the communication\ncost as it is sending raw strings over the wire while the other two options\ndrastically reduce the cost at the price of having false positives.\n\n## Security\n\nSee [SECURITY.md](SECURITY.md).\n\n## Requirements\n\nThere are requirements for the entire project which each language shares. There\nalso could be requirements for each target language:\n\n### Global Requirements\n\nThese are the common requirements across all target languages of this project.\n\n- A compiler such as clang or gcc\n- [Bazel](https://bazel.build)\n\n## Installation\n\nThe repository uses a folder structure to isolate the supported targets from one\nanother:\n\n```\nprivate_set_intersection/\u003ctarget language\u003e/\u003csources\u003e\n```\n\n### C++\n\nSee the [C++ README.md](private_set_intersection/cpp/README.md)\n\n### JavaScript\n\nSee the [JavaScript README.md](private_set_intersection/javascript/README.md)\n\n### Go\n\nSee the [Go README.md](private_set_intersection/go/README.md)\n\n### Python\n\nSee the [Python README.md](private_set_intersection/python/README.md)\n\n### Rust\n\nSee the [Rust README.md](private_set_intersection/rust/README.md)\n\n## Usage\n\nA full description of the protocol can be found in the documentation of the\n[PsiClient](private_set_intersection/cpp/psi_client.h) class. The corresponding\nserver class is [PsiServer](private_set_intersection/cpp/psi_server.h). An\nexample of how to interleave the different phases of the protocol can be found\nin [psi_server_test.cpp](private_set_intersection/cpp/psi_server_test.cpp).\n\n## Changes\n\nSee [CHANGES.md](CHANGES.md).\n\n## Contributing\n\nPull requests are welcome. For major changes, please open an issue first to\ndiscuss what you would like to change.\n\nPlease make sure to update tests as appropriate.\n\n## Contributors\n\nSee [CONTRIBUTORS.md](CONTRIBUTORS.md).\n\n## License\n\n[Apache License 2.0](https://choosealicense.com/licenses/apache-2.0/)\n","funding_links":["https://github.com/sponsors/openmined","https://opencollective.com/openmined"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenmined%2Fpsi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenmined%2Fpsi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenmined%2Fpsi/lists"}