In recent years, preserving privacy has became a fundamental requirement for any organization. Huge amounts of data are generated by social media, smart devices, or service providers (hospitals, banks, etc.), and analyzing them in a privacy preserving manner is not easy. Lately, privacy preserving techniques have emerged, including federated learning [29, 49] , secure multi-party computation [19] , or homomorphic encryption [18, 32] , which lead a much-needed privacy revolution.
Private Set Intersection (PSI) is a multi-party computation cryptographic protocol that allows two parties, each holding sets, to compute the intersection [6, 7, 16, 22, 33] or the cardinality of the intersection [8, 41] by comparing encrypted versions of these sets. Recently, several real-world applications of PSI and its variants have emerged. Ion et al. [24] applied a PSI-Sum protocol to advertising conversions aggregation, trying to solve the privacy problem between the ad supplier, which knows the users that have seen a particular ad, and the company, which knows who made a purchase and what they spent. Buddhavarapu et al. [4] improved these results with a new library and implementation, Private-ID, with applications in randomized controlled trials or machine learning training. Other applications include private contact discovery [9] or plagiarism detection [23] . Finally, there are several research implementations of PSI protocols [6, 26, 28, 33, 35] . However, all of these have in common that they focus on a single setting, and only provide bindings for a single programming language. In contrast, our goal is to enable the application of PSI in further use cases by providing an open-source library that is easy to use across language barriers and platforms.
We present a versatile open-source library for asymmetric private set intersection (PSI) and PSI-Cardinality (PSI-C). Our library combines the well-studied PSI protocol based on the decisional Diffie-Hellman (DDH) assumption with a Bloom filter compression to reduce the communication complexity. Our library supports bindings for C++, C, Go, JavaScript, Python, and Rust, as well as multiple platforms including browser targets. To the best of our knowledge, ours is the first PSI library to support such a wide set of languages. Our implementation is available under an open source license at https://github.com/OpenMined/PSI.
We describe the details of our architecture in Section 3. Then, in Section 4, the practicality of our library is exemplified with two use cases: privacy-preserving contact tracing (Section 4.1) based on PSI-Cardinality, and secure matching of vertically partitioned data (Section 4.2) based on PSI. Finally, in Section 5, we provide an experimental evaluation of our library.
Protocol 1 and Figure 2 in the appendix describe our variant of the DDH-based PSI and PSI-C protocols. The main difference to the presentation in Trieu et al. [41, Figure 4 ] is that our protocol uses a Bloom filter to compress the server's encrypted data set. As observed in previous work [28] , this can dramatically reduce communication in the asymmetric case. Thus, our protocol can be seen as a hybrid of the works of Trieu et al. [41] and Kiss et al. [28] . We note that Bloom filters were chosen here for simplicity, and can be replaced by smaller data structures such as cuckoo filters [14] or Golomb-compressed sets [34] . We also implement a more communication-efficient variant of our protocol using the latter. While we don't provide a full evaluation for that variant, we show the size differences between the data structures in Appendix B.
The security of our protocol follows directly from previous work. See for example De Cristofaro et al. [8] for a security proof for the PSI-C variant without Bloom filters. Since our main difference is computing a Bloom filter with public parameters, which can be trivially simulated, security of Protocol 1 follows.
Note that after the setup phase, communication only depends on n, the client's input size. Thus, our protocol is especially useful when the server set is static and can be reused across multiple queries. For the PSI case, this can be done in a straight-forward way, since the server's secret key k is never revealed. For PSI-C, we need to be a bit more careful, since repeated queries may make it easier for the client to learn the elements in the intersection in addition to the intersection size. For our contact tracing application (Section 4.1), we therefore suggest to employ rate limiting, and rotate the server key by re-running the setup phase repeatedly. Figure 4 ]. Parameters: A cyclic group G of order p, a hash function H that maps inputs to G, and a boolean flag RevealIntersection. Inputs: Server: a set X = {x 1 , . . . , x N }, false-positive rate p.
Client: a set Y = {y 1 , . . . , y n }. Server Setup:
1. Server chooses a random key k ← Z p . 2. For each i ∈ [N ], the server computes
} into a Bloom filter BF such that n queries give a false positive with probability at most p, and sends BF to the client.
Protocol:
1. Client randomly samples r ← Z p , and for each y i ∈ Y sends m i = H(y i ) r to the server. 
RevealIntersection is true, the client outputs S, otherwise |S|.
The main focus of the library is on performance and versatility. To achieve that, the core of the library is built using C++, and our other language bindings all use this C++ core. We use the elliptic curve P-256 to instantiate group G in Protocol 1, relying on the implementation of Ion et al. [24] . For message serialization, we use Protocol Buffers [2] , and our project is built using Bazel [1] to support builds across languages and platforms. Figure 1 in the appendix depicts our library's components and their interdependencies. We use our C bindings to interface with languages like Go and Rust that don't have a native C++ interface. For Python and JavaScript, we use the C++ core library directly.
Smartphone based contact tracing allows to notify people who may have been exposed to infections, thereby allowing them to self-isolate or seek treatment. However contact tracing data poses risks of discrimination based on health status, or location leakage [3] . Hence preserving the privacy of people's data is key for widespread adoption, especially considering that stopping a pandemic such as COVID-19 requires adoption of approximately 60 % of the whole population [42] .
Several approaches for contact tracing have been developed this year, with similar patterns: Data of infected people is collected on a central server (e.g. by national health authority). Meanwhile people's smartphones exchange IDs between them and collect which other IDs they have been in contact with lately (e.g. based on Bluetooth) in a local list, regularly download a list of infected people's IDs from the server, and compute the intersection of both server and local ID lists to find out whether they have been exposed. Notable protocols include TCN [39] and DP3T [11] ).
However, these protocols do not protect against linkage attacks, as essentially the server provides a list of infected IDs to the clients. This gives rise to the possibility of re-identifying infected persons, e.g. by recording IDs of people and using additional information (e.g., from cameras on the street).
Linkage attacks can be mitigated by using PSI-C for computing the intersection. So instead of the server providing a list of infected IDs, only the intersection size is computed by following Protocol 1. Hence no list of infected IDs is provided by the server, rather both server and client encrypt their sets and jointly compute the intersection. Using PSI-C for contact tracing has also been proposed in concurrent work [41] . To show the feasibility of our approach, and in particular its compatibility to existing protocols, we implement a privacy-preserving contact tracing library on top of the TCN protocol [5] .
Vertical Federated Learning (VFL) [15, 30, 49] applies federated learning [25] to vertically distributed data, i.e., datasets that share partial information about the same entity, differing in the features of each dataset. Different hospitals for example may have differing data about the same patient, but cannot simply merge this data across institutions due to privacy reasons. For such situations several approaches have been many suggested in the past [12, 13, 17, 27, 37, 43, 48] , including logistic regression [21, 31] .
One approach for such scenarios is Split Learning (SL) [20, 44, 45] using a Split Neural Network (SplitNN), where the Neural Network (NN) is split among participants, and each model segment acts as a self-contained NN. Each model segment trains and forwards its result to the next segment until completion. The security of SplitNN and its information leakage is being questioned [25] , but an enhanced privacy-preserving variant of SplitNN has been proposed in which the information leakage is reduced using distance correlation [38, 46, 47] . Still, additional privacy-preserving methods could be incorporated in SL when dealing with very sensitive datasets.
In our work, we have realized a privacy-preserving implementation of SplitNN trained on vertically distributed data, called PyVertical [40] . In our proof-of-concept (Appendix C), we first utilise PSI for identifying matching entries in two vertically distributed datasets in a privacy preserving manner, and then train a SplitNN on this data, thereby ensuring the privacy of the raw data. PyVertical is built upon the PySyft library [36] , which provides security features and mechanisms for training without sacrificing data privacy. Even though SplitNN does not provide formal security guarantees, PSI allows us to hide those data points that are not part of the intersection. Hence PSI is beneficial for just about any computation on vertically partitioned data (secure or not secure) if the parties want to hide elements that are not in the intersection.
We benchmark our PSI library on an Amazon EC2 T3a.xlarge instance with 4 vCPUs at 2.5 GHz and 16 GiB memory. Our results are presented in Table 1 . It can be seen that there is little difference between languages that bind directly to our C++ core. This is to be expected, as the running time is dominated by elliptic curve operations, compared to which the overhead of crossing language barriers (including protobuf serialization) is small. This changes when comparing WebAssembly and pure Javascript, which rely on cross-compilation of our library using Emscripten. Still, the overhead in modern browsers is less than 10x compared to the native version, and on the client side stays under 3 minutes for all sizes we tested.
The closest libraries to ours in previous work are the implementations of Kiss et al. [28] and Kales et al. [26] . Both focus on PSI for mobile applications, for example private contact discovery. We compare our results with the ECC-NR-PSI protocol from Kales et al. [26] for N = 1M, n = 1k.
As noted there, this protocol already outperforms Kiss et al. [28] . As can be seen in Table 1 , the size of the setup message is smaller for Kales et al. [26] . This is to be expected due to the fact that they use more efficient cuckoo filters [14] , and our library has an additional overhead due to our use of protocol buffers. However, in both the online phase and in terms of total communication, our implementation improves on the results of Kales et al. [26] . In Appendix B we also present experiments on a more communication-efficient variant of our protocol using Golomb-compressed sets. We stress that the online times from [26] are not comparable to ours, since their experiments were run on different hardware, in particular using a smartphone for the client.
In conclusion, our results show that our library is highly competitive in terms of running time and communication. At the same time, it is flexible enough to support multiple platforms and languages, including browsers. Possible improvements can be made by reducing the setup communication, for example using cuckoo filters [14, 26] . Finally, we see extensions like PrivateID [4] as promising future work. Table 1 : Benchmarks in seconds for n client elements and N = 1M server elements. The probability of a false positive over n lookups was set to p = 10 −9 . An asterisk ( * ) indicates experiments that were run on a smaller server set (N = 100k) and extrapolated from there. Numbers for previous work were taken from [26, Table 6 ]. Cells with dagger ( † ) were summed up in [26] , so we only report the sum. 
For many use cases of PSI, the server must send a large set of setup data to the client. Therefore, in addition to Bloom filters, we also implement Golomb coding [34] for better compression of the setup set. We will refer to this data structure as Golomb-compressed sets (GCS). We compare the sizes of Golomb-compressed sets and Bloom filters that needs to be sent to the client in Table 2 . Internally, the GCS implementation uses a one-pass encoding scheme on the server side, and an on-the-fly decoding scheme for bulk intersection on the client side, so it is similar in speed to Bloom filters for bulk insertion and intersection. However, Bloom filters are faster at random accesses and insertions of a small number elements. Therefore, it is important to weigh the costs of communication with the costs of random access lookups when deciding which underlying data structure to use. 
For our proof-of-concept of PyVertical we used the MNIST dataset of handwritten images and their labels [10] . The overall process is shown in Figure 3 . MNIST is a horizontally distributed dataset. As shown in Figure 3 , a) we have added a new IDs field to this data which assigns unique IDs to each data point. Furthermore, as shown in Figure 3 , b), we split the full dataset into two datasets; one with the handwritten images and their IDs, and one with the labels and their IDs. In the next step, we shuffle the datasets and randomly remove data points from both.
In the actual experiment, we utilise PSI to identify matching IDs in the two datasets, as shown in Figure 3 , c), hence link the data points with shared IDs, and order both datasets accordingly. Data points that are not elements of the intersection are being purged in this example. Finally, we create a SplitNN, as shown in Figure 3 , d), where one part of the network is trained on the images dataset and the other part of the network is trained on the labels dataset. This allows to train the model in a privacy-preserving manner by leveraging PySyft's pointers functionality [36] which keeps the raw training data hidden throughout the training process. 