diff --git a/.circleci/release.yml b/.circleci/release.yml index bbac8bcc..cdfc92ea 100644 --- a/.circleci/release.yml +++ b/.circleci/release.yml @@ -61,7 +61,7 @@ jobs: name: "Copy binary" command: | mkdir -p /tmp/binary/x86 - cp bazel-bin/psi/main /tmp/binary/x86 + cp bazel-bin/psi/apps/psi_launcher/main /tmp/binary/x86 - persist_to_workspace: root: "/tmp/binary" paths: @@ -95,7 +95,7 @@ jobs: name: "Copy binary" command: | mkdir -p /tmp/binary/arm - cp bazel-bin/psi/main /tmp/binary/arm + cp bazel-bin/psi/apps/psi_launcher/main /tmp/binary/arm - persist_to_workspace: root: "/tmp/binary" paths: diff --git a/LEGAL.md b/LEGAL.md index f9689208..9b98932a 100644 --- a/LEGAL.md +++ b/LEGAL.md @@ -1,7 +1,9 @@ -Legal Disclaimer +# Legal Disclaimer -Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail. +Within this source code, the comments in Chinese shall be the original, governing version. +Any comment in other languages are for reference only. +In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail. 法律免责声明 -关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。 \ No newline at end of file +关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。 diff --git a/MODULE.bazel b/MODULE.bazel index 8bb094dc..ef44cfea 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -35,7 +35,6 @@ bazel_dep(name = "abseil-cpp", version = "20240722.0") bazel_dep(name = "gflags", version = "2.2.2") bazel_dep(name = "rapidjson", version = "1.1.0.bcr.20241007") bazel_dep(name = "boost.math", version = "1.83.0") -bazel_dep(name = "boost.uuid", version = "1.83.0.bcr.1") bazel_dep(name = "boost.algorithm", version = "1.83.0.bcr.1") bazel_dep(name = "boost.multiprecision", version = "1.83.0") bazel_dep(name = "zlib", version = "1.3.1.bcr.3") diff --git a/README.md b/README.md index d09ca458..6e57c61c 100644 --- a/README.md +++ b/README.md @@ -22,97 +22,96 @@ In the following example, we are going to run PSI at a single host. 2. Prepare data and config. -receiver.config: - -```json -{ - "psi_config": { - "protocol_config": { - "protocol": "PROTOCOL_RR22", - "role": "ROLE_RECEIVER", - "broadcast_result": true - }, - "input_config": { - "type": "IO_TYPE_FILE_CSV", - "path": "/root/receiver/receiver_input.csv" - }, - "output_config": { - "type": "IO_TYPE_FILE_CSV", - "path": "/root/receiver/receiver_output.csv" - }, - "keys": [ - "id0", - "id1" - ], - "debug_options": { - "trace_path": "/root/receiver/receiver.trace" - } - }, - "self_link_party": "receiver", - "link_config": { - "parties": [ - { - "id": "receiver", - "host": "127.0.0.1:5300" + receiver.config: + + ```json + { + "psi_config": { + "protocol_config": { + "protocol": "PROTOCOL_RR22", + "role": "ROLE_RECEIVER", + "broadcast_result": true }, - { - "id": "sender", - "host": "127.0.0.1:5400" + "input_config": { + "type": "IO_TYPE_FILE_CSV", + "path": "/root/receiver/receiver_input.csv" + }, + "output_config": { + "type": "IO_TYPE_FILE_CSV", + "path": "/root/receiver/receiver_output.csv" + }, + "keys": [ + "id0", + "id1" + ], + "debug_options": { + "trace_path": "/root/receiver/receiver.trace" } - ] + }, + "self_link_party": "receiver", + "link_config": { + "parties": [ + { + "id": "receiver", + "host": "127.0.0.1:5300" + }, + { + "id": "sender", + "host": "127.0.0.1:5400" + } + ] + } } -} -``` + ``` -sender.config: + sender.config: -```json -{ - "psi_config": { - "protocol_config": { - "protocol": "PROTOCOL_RR22", - "role": "ROLE_SENDER", - "broadcast_result": true - }, - "input_config": { - "type": "IO_TYPE_FILE_CSV", - "path": "/root/sender/sender_input.csv" - }, - "output_config": { - "type": "IO_TYPE_FILE_CSV", - "path": "/root/sender/sender_output.csv" - }, - "keys": [ - "id0", - "id1" - ], - "debug_options": { - "trace_path": "/root/sender/sender.trace" - } - }, - "self_link_party": "sender", - "link_config": { - "parties": [ - { - "id": "receiver", - "host": "127.0.0.1:5300" + ```json + { + "psi_config": { + "protocol_config": { + "protocol": "PROTOCOL_RR22", + "role": "ROLE_SENDER", + "broadcast_result": true + }, + "input_config": { + "type": "IO_TYPE_FILE_CSV", + "path": "/root/sender/sender_input.csv" }, - { - "id": "sender", - "host": "127.0.0.1:5400" + "output_config": { + "type": "IO_TYPE_FILE_CSV", + "path": "/root/sender/sender_output.csv" + }, + "keys": [ + "id0", + "id1" + ], + "debug_options": { + "trace_path": "/root/sender/sender.trace" } - ] + }, + "self_link_party": "sender", + "link_config": { + "parties": [ + { + "id": "receiver", + "host": "127.0.0.1:5300" + }, + { + "id": "sender", + "host": "127.0.0.1:5400" + } + ] + } } -} -``` - -| File Name | Location | Description | -| :---------------- | :---------------------------------- | :------------------------------------------------------------------------- | -| receiver.config | /tmp/receiver/receiver.config | Config for receiver. | -| sender.config | /tmp/sender/sender.config | Config for sender. | -| receiver_input.csv | /tmp/receiver/receiver_input.csv | Input for receiver. Make sure the file contains two id keys - id0 and id1. | -| sender_input.csv | /tmp/sender/sender_input.csv | Input for sender. Make sure the file contains two id keys - id0 and id1. | + ``` + | File Name | Location | Description | + | :---------------- | :---------------------------------- | :------------------------------------------------------------------------- | + | receiver.config | /tmp/receiver/receiver.config | Config for receiver. | + | sender.config | /tmp/sender/sender.config | Config for sender. | + | receiver_input.csv | /tmp/receiver/receiver_input.csv | Input for receiver. Make sure the file contains two id keys - id0 and id1. | + | sender_input.csv | /tmp/sender/sender_input.csv | Input for sender. Make sure the file contains two id keys - id0 and id1. | 3. Run PSI @@ -122,7 +121,7 @@ In the first terminal, run the following command docker run -it --rm --network host --mount type=bind,source=/tmp/receiver,target=/root/receiver --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:latest --config receiver/receiver.config ``` -In the other terminal, run the following command simultaneously. +In the other terminal, run the following command simultaneously. ```bash docker run -it --rm --network host --mount type=bind,source=/tmp/sender,target=/root/sender --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:latest --config sender/sender.config @@ -131,7 +130,8 @@ docker run -it --rm --network host --mount type=bind,source=/tmp/sender,target You could also pass a minified JSON config directly. A minified JSON is a compact one without white space and line breaks. e.g. -``` + +```bash docker run -it --rm --network host --mount type=bind,source=/tmp/sender,target=/root/sender --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:latest --json '{"psi_config":{"protocol_config":{"protocol":"PROTOCOL_RR22","role":"ROLE_RECEIVER","broadcast_result":true},"input_config":{"type":"IO_TYPE_FILE_CSV","path":"/root/receiver/receiver_input.csv"},"output_config":{"type":"IO_TYPE_FILE_CSV","path":"/root/receiver/receiver_output.csv"},"keys":["id0","id1"],"debug_options":{"trace_path":"/root/receiver/receiver.trace"}},"self_link_party":"receiver","link_config":{"parties":[{"id":"receiver","host":"127.0.0.1:5300"},{"id":"sender","host":"127.0.0.1:5400"}]}}' ``` @@ -184,28 +184,33 @@ bazel build //... -c opt bazel test //... ``` - ### Trace We use [Perfetto](https://perfetto.dev/) from Google for tracing. Please use debug_options.trace_path field in PsiConfig to modify trace file path. The default path is /tmp/psi.trace. -After running psi binaries, please check trace by using [Trace Viewer](https://ui.perfetto.dev/). If this is not applicable, please check [this link](https://github.com/google/perfetto/issues/170) to deploy your own website. +After running psi binaries, please check trace by using [Trace Viewer](https://ui.perfetto.dev/). If this is not applicable, +please check [this link](https://github.com/google/perfetto/issues/170) to deploy your own website. The alternate way to visualize trace is to use **chrome://tracing**: -1. Download perfetto assets from https://github.com/google/perfetto/releases/tag/v37.0 + +1. Download perfetto assets from 2. You should find traceconv binary in assets folder. 3. Transfer trace file to JSON format: -```bash -chmod +x traceconv + ```bash + chmod +x traceconv + + ./traceconv json [trace file path] [json file path] + ``` -./traceconv json [trace file path] [json file path] -``` 4. Open chrome://tracing in your chrome and load JSON file. + + + ## PSI V2 Benchamrk Please refer to [PSI V2 Benchmark](docs/user_guide/psi_v2_benchmark.md) @@ -213,4 +218,3 @@ Please refer to [PSI V2 Benchmark](docs/user_guide/psi_v2_benchmark.md) ## APSI Benchmark Please refer to [APSI Benchmark](docs/user_guide/apsi_benchmark.md) - diff --git a/RELEASE.md b/RELEASE.md index c8327d18..8058ee3f 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,3 +1,5 @@ +# RELEASE + > NOTE: > > - `[Feature]` prefix for new features. @@ -6,46 +8,57 @@ > - `[Improvement]` prefix for implementation improvement. ## v0.5.0.dev241107 + - `[API]` delete legacy ub psi function. - `[API]` output csv null_rep can be specified. - `[Feature]` join can be done with one receiver. - `[Feature]` join can be done with ub psi protocol. ## v0.4.0.dev240801 + - [Bugfix] Fix MacOS and arm build. ## v0.4.0.dev240731 + - [Improvement] Port APSI again. - [Feature] Add Bucketized APSI. - [API] Remove SealPIR. ## v0.4.0.dev240521 + - [API] remove BC22 protocol ## v0.4.0.dev240517 + - [Improvement] upgrade yacl to 0.4.5b0. ## v0.4.0.dev240514 + - [API] add entrypoint for docker file. - [API] allow passing config JSON directly to main. - [Bugfix] fix ic mode. - [Bugfix] fix RR22, SealPIR and APSI. ## v0.4.0.dev240401 + - [Improvement] upgrade download uri of xz. ## v0.4.0.dev240329 + - [Improvement] upgrade yacl to 0.4.4b3. ## v0.3.0beta + - [Improvement] add uuid in system temp folder. - [Improvement] use arrow csv reader in pir. -- [Bugfix] fix typo in psi config check. +- [Bugfix] fix typo in psi config check. ## v0.3.0.dev240304 + - [API] expose ic_mode in RunLegacyPsi api ## v0.3.0.dev240222 + - [API] expose PIR API. ## v0.3.0.dev240219 @@ -63,13 +76,11 @@ - [Bugfix] Fix flakiness in psi_test. - [Bugfix] Fix race condition in rr22. - ## v0.2.0.dev231228 - [Bugfix] Fix RR22 race condition. - [Improvement] modify sort buffer size. - ## v0.2.0.dev231221 - [API] Rename check_duplicates to skip_duplicates_check. @@ -79,7 +90,6 @@ - [Bugfix] Fix duplicate key check. - [Bugfix] Fix SyncWait. - ## v0.1.0beta - [API] Add PSI v2 API. diff --git a/VERSIONING.md b/VERSIONING.md index f184f49d..cf32569b 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -1,73 +1,90 @@ # Versioning +## EN + SecretFlow artifacts belongs to one of the following categories: -- "Releases", i.e. artifact versions follow the **x.y.z** format, where **x** is called "major version", **y** is called "minor version", **z** is called "patch version". We follow [Semantic Versioning 2.0.0](https://semver.org/) to update versions. e.g. -``` -1.2.3 -``` +- "Releases", i.e. artifact versions follow the **x.y.z** format, where **x** is called "major version", **y** is called "minor version", +**z** is called "patch version". We follow [Semantic Versioning 2.0.0](https://semver.org/) to update versions. e.g. + + ```txt + 1.2.3 + ``` - "Pre-releases", i.e. artifact versions follow the **x.y.zb0** format. **Pre-release segment** is fixed to **b0**. e.g. -``` -0.8.7b0 # Pre-release of 0.8.7 -``` - -- "Developmental releases", i.e. artifact versions follow the **x.y.z.devYYMMDD** or **x.y.z.devYYMMDD** format, where **YY** is the last two digits of year(00-99), **MM** is the zero-padded digits of month(01-12) and **DD** is zero-padded digits of day of the month(01-31). **YY**, **MM** and **DD** indicates the date when a Developmental release is published. e.g. -``` -1.1.0.dev230820 # Developmental release of 1.1.0 published at 23/08/20 -1.3.0.dev231115 # Developmental release of 1.3.0 published at 23/11/15 -``` - -- "Post-releases", i.e. artifact versions follow the **x.y.zb0.postN** or **x.y.z.postN** format. **x.y.zb0.postN** is a Developmental release of a Pre-release while **x.y.z.postN** is a Developmental release of a Release. e.g. -``` -1.1.0.post0 # The 1st Post-release of 1.1.0 -1.3.0b0.post9 # The 10th Post-release of 1.3.0b0 -``` -## Releases + ```txt + 0.8.7b0 # Pre-release of 0.8.7 + ``` + +- "Developmental releases", i.e. artifact versions follow the **x.y.z.devYYMMDD** or **x.y.z.devYYMMDD** format, +where **YY** is the last two digits of year(00-99), +**MM** is the zero-padded digits of month(01-12) and **DD** is zero-padded digits of day of the month(01-31). +**YY**, **MM** and **DD** indicates the date when a Developmental release is published. e.g. + + ```txt + 1.1.0.dev230820 # Developmental release of 1.1.0 published at 23/08/20 + 1.3.0.dev231115 # Developmental release of 1.3.0 published at 23/11/15 + ``` + +- "Post-releases", i.e. artifact versions follow the **x.y.zb0.postN** or **x.y.z.postN** format. +**x.y.zb0.postN** is a Developmental release of a Pre-release while **x.y.z.postN** is a Developmental release of a Release. e.g. + + ```txt + 1.1.0.post0 # The 1st Post-release of 1.1.0 + 1.3.0b0.post9 # The 10th Post-release of 1.3.0b0 + ``` + +### Releases Release **x.y.z** meets the following conditions: + - Pre-release **x.y.zb0** has been published before, and - Pre-release **x.y.zb0** has passed through evaluation. -## Pre-releases +### Pre-releases Pre-release **x.y.zb0** is to support testing by external users prior to release **x.y.z**. -## Developmental releases +### Developmental releases Developmental releases are to provide the preview of new features. They are considered unstable. -## Post-releases +### Post-releases Post-releases are to address minor errors of Releases and Pre-releases. They are considered unstable. -# 版本控制 +## ZH SecretFlow 的 artifact 属于以下几种类别之一: - "Releases",即 artifact 版本遵循 **x.y.z** 格式,其中 **x** 称为 "主版本", **y** 称为 "次版本", **z** 称为 "修复版本"。我们遵循 [Semantic Versioning 2.0.0](https://semver.org/) 更新版本。例如: -``` -1.2.3 -``` + + ```txt + 1.2.3 + ``` - "Pre-releases",即 artifact 版本遵循 **x.y.zb0** 格式。预发布字段固定为 **b0**。例如: -``` -0.8.7b0 # 0.8.7的Pre-release -``` - -- "Developmental releases",即 artifact 版本遵循 **x.y.z.devYYMMDD** 或 **x.y.z.devYYMMDD** 格式,其中 **YY** 是年份的最后两位(00-99), **MM** 是月份的零填充数字(01-12), **DD** 是当月日期的零填充数字(01-31)。**YY**, **MM** 和 **DD** 用以表示发布开发版的日期。例如: -``` -1.1.0.dev230820 # 于23/08/20发布的1.1.0开发版 -1.3.0.dev231115 # 于23/11/15发布的1.3.0开发版 -``` - - -- "Post-releases",即 artifact 版本遵循 **x.y.zb0.postN** 或 **x.y.z.postN** 格式。 **x.y.zb0.postN** 是 Pre-releases 的 Post-releases,而 x.y.z.postN 是 Releases 的Post-releases 。例如: -``` -1.1.0.post0 # 1.1.0的第1个Post-release -1.3.0b0.post9 # 1.3.0b0的第10个Post-release -``` + + ```txt + 0.8.7b0 # 0.8.7的Pre-release + ``` + +- "Developmental releases",即 artifact 版本遵循 **x.y.z.devYYMMDD** 或 **x.y.z.devYYMMDD** 格式,其中 **YY** 是年份的最后两位(00-99), **MM** 是月份的零填充数字(01-12), +**DD** 是当月日期的零填充数字(01-31)。**YY**, **MM** 和 **DD** 用以表示发布开发版的日期。例如: + + ```txt + 1.1.0.dev230820 # 于23/08/20发布的1.1.0开发版 + 1.3.0.dev231115 # 于23/11/15发布的1.3.0开发版 + ``` + +- "Post-releases",即 artifact 版本遵循 **x.y.zb0.postN** 或 **x.y.z.postN** 格式。 +**x.y.zb0.postN** 是 Pre-releases 的 Post-releases,而 x.y.z.postN 是 Releases 的Post-releases 。例如: + + ```txt + 1.1.0.post0 # 1.1.0的第1个Post-release + 1.3.0b0.post9 # 1.3.0b0的第10个Post-release + ``` ## Releases diff --git a/bazel/psi.bzl b/bazel/psi.bzl index ae8a9574..2ebadb70 100644 --- a/bazel/psi.bzl +++ b/bazel/psi.bzl @@ -30,9 +30,9 @@ FAST_FLAGS = ["-O1"] def _psi_copts(): return select({ - "@psi//bazel:psi_build_as_release": RELEASE_FLAGS, - "@psi//bazel:psi_build_as_debug": DEBUG_FLAGS, - "@psi//bazel:psi_build_as_fast": FAST_FLAGS, + "//bazel:psi_build_as_release": RELEASE_FLAGS, + "//bazel:psi_build_as_debug": DEBUG_FLAGS, + "//bazel:psi_build_as_fast": FAST_FLAGS, "//conditions:default": FAST_FLAGS, }) + WARNING_FLAGS diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 9eb2270b..34a70d75 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -36,11 +36,11 @@ def _com_github_microsoft_apsi(): urls = [ "https://github.com/microsoft/APSI/archive/refs/tags/v0.11.0.tar.gz", ], - build_file = "@psi//bazel:microsoft_apsi.BUILD", + build_file = "//bazel:microsoft_apsi.BUILD", patch_args = ["-p1"], patches = [ - "@psi//bazel/patches:apsi.patch", - "@psi//bazel/patches:apsi-fourq.patch", + "//bazel/patches:apsi.patch", + "//bazel/patches:apsi-fourq.patch", ], patch_cmds = [ "rm -rf common/apsi/fourq", @@ -57,7 +57,7 @@ def _com_github_microsoft_kuku(): urls = [ "https://github.com/microsoft/Kuku/archive/refs/tags/v2.1.0.tar.gz", ], - build_file = "@psi//bazel:microsoft_kuku.BUILD", + build_file = "//bazel:microsoft_kuku.BUILD", ) def _com_google_flatbuffers(): @@ -75,7 +75,7 @@ def _com_google_flatbuffers(): "rm grpc/src/compiler/BUILD.bazel", "rm src/BUILD.bazel", ], - build_file = "@psi//bazel:flatbuffers.BUILD", + build_file = "//bazel:flatbuffers.BUILD", ) def _com_github_google_perfetto(): @@ -88,8 +88,8 @@ def _com_github_google_perfetto(): sha256 = "4c8fe8a609fcc77ca653ec85f387ab6c3a048fcd8df9275a1aa8087984b89db8", strip_prefix = "perfetto-41.0", patch_args = ["-p1"], - patches = ["@psi//bazel/patches:perfetto.patch"], - build_file = "@psi//bazel:perfetto.BUILD", + patches = ["//bazel/patches:perfetto.patch"], + build_file = "//bazel:perfetto.BUILD", ) def _com_github_floodyberry_curve25519_donna(): @@ -99,7 +99,7 @@ def _com_github_floodyberry_curve25519_donna(): strip_prefix = "curve25519-donna-2fe66b65ea1acb788024f40a3373b8b3e6f4bbb2", sha256 = "ba57d538c241ad30ff85f49102ab2c8dd996148456ed238a8c319f263b7b149a", type = "tar.gz", - build_file = "@psi//bazel:curve25519-donna.BUILD", + build_file = "//bazel:curve25519-donna.BUILD", urls = [ "https://github.com/floodyberry/curve25519-donna/archive/2fe66b65ea1acb788024f40a3373b8b3e6f4bbb2.tar.gz", ], @@ -109,7 +109,7 @@ def _com_github_zeromq_cppzmq(): maybe( http_archive, name = "com_github_zeromq_cppzmq", - build_file = "@psi//bazel:cppzmq.BUILD", + build_file = "//bazel:cppzmq.BUILD", strip_prefix = "cppzmq-4.10.0", sha256 = "c81c81bba8a7644c84932225f018b5088743a22999c6d82a2b5f5cd1e6942b74", type = ".tar.gz", @@ -122,7 +122,7 @@ def _com_github_zeromq_libzmq(): maybe( http_archive, name = "com_github_zeromq_libzmq", - build_file = "@psi//bazel:libzmq.BUILD", + build_file = "//bazel:libzmq.BUILD", strip_prefix = "libzmq-4.3.5", sha256 = "6c972d1e6a91a0ecd79c3236f04cf0126f2f4dfbbad407d72b4606a7ba93f9c6", type = ".tar.gz", @@ -135,7 +135,7 @@ def _com_github_open_source_parsers_jsoncpp(): maybe( http_archive, name = "com_github_open_source_parsers_jsoncpp", - build_file = "@psi//bazel:jsoncpp.BUILD", + build_file = "//bazel:jsoncpp.BUILD", strip_prefix = "jsoncpp-1.9.6", sha256 = "f93b6dd7ce796b13d02c108bc9f79812245a82e577581c4c9aabe57075c90ea2", type = ".tar.gz", diff --git a/benchmark/stats.py b/benchmark/stats.py index 0780167f..ba4e9810 100644 --- a/benchmark/stats.py +++ b/benchmark/stats.py @@ -12,14 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -import docker -import json import csv -import sys +import json import os +import sys import time from datetime import datetime +import docker + def stream_container_stats(container_name, output_file): client = docker.from_env() diff --git a/docker/.nsjail/README.md b/docker/.nsjail/README.md index 7b5620e2..a6344846 100644 --- a/docker/.nsjail/README.md +++ b/docker/.nsjail/README.md @@ -1 +1,3 @@ +# README + **NOTE: this folder is still experimental.** diff --git a/docker/README.md b/docker/README.md index a12c364e..c182c356 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,13 +1,16 @@ -# build psi binary with release-ci docker(for x86 only) +# Docker + +## build psi binary with release-ci docker(for x86 only) ```bash docker run -it --rm --mount type=bind,source="$(pwd)/../../psi",target=/home/admin/dev/src -w /home/admin/dev --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow/release-ci:1.2 /home/admin/dev/src/docker/entry.sh ``` -# build psi dev docker +## build psi dev docker ```bash bash build.sh -v -u -l ``` + - *-u* means upload docker to reg. - *-l* means tag docker as *latest* as well. diff --git a/docker/build.sh b/docker/build.sh index eb88fc64..a9d7bffd 100644 --- a/docker/build.sh +++ b/docker/build.sh @@ -72,7 +72,7 @@ echo -e "Build psi binary ${GREEN}PSI ${PSI_VERSION}${NO_COLOR}..." SCRIPT_DIR="$(realpath $(dirname $0))" if [[ SKIP -eq 0 ]]; then - docker run -it --rm --mount type=bind,source="${SCRIPT_DIR}/../",target=/home/admin/dev/src -w /home/admin/dev --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow/release-ci:latest /home/admin/dev/src/docker/entry.sh + docker run -it --rm --mount type=bind,source="${SCRIPT_DIR}/../",target=/home/admin/dev/src -w /home/admin/dev --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow/release-ci:1.7 /home/admin/dev/src/docker/entry.sh echo -e "Finish building psi binary ${GREEN}${IMAGE_LITE_TAG}${NO_COLOR}" fi diff --git a/docker/entry.sh b/docker/entry.sh index 115a42b6..6af249d3 100755 --- a/docker/entry.sh +++ b/docker/entry.sh @@ -7,7 +7,10 @@ cd src_copied conda install -y perl=5.20.3.1 -bazel build psi:main -c opt --config=linux-release --remote_timeout=300s --remote_retries=10 -chmod 777 bazel-bin/psi/main + + + +bazel build psi:main -c opt --config=linux-release --repository_cache=/tmp/bazel_repo_cache --remote_timeout=300s --remote_retries=10 +chmod 777 bazel-bin/psi/apps/psi_launcher/main mkdir -p ../src/docker/linux/amd64 -cp bazel-bin/psi/main ../src/docker/linux/amd64 +cp bazel-bin/psi/apps/psi_launcher/main ../src/docker/linux/amd64 diff --git a/docs/.gitignore b/docs/.gitignore index e35d8850..34a6e2b4 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1 +1,2 @@ _build +*.mo \ No newline at end of file diff --git a/docs/build.sh b/docs/build.sh new file mode 100644 index 00000000..37daa1cf --- /dev/null +++ b/docs/build.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -ex + +usage() { echo "Usage: $0 [-l ]" 1>&2; exit 1; } + + +while getopts ":l:" o; do + case "${o}" in + l) + l=${OPTARG} + ;; + *) + usage + ;; + esac +done +shift $((OPTIND-1)) + +if [ -z "${l}" ]; then + usage +fi + +echo "selected language is: ${l}" + +if [[ "$l" != "en" && "$l" != "zh_CN" ]]; then + usage +fi + +SPHINX_APIDOC_OPTIONS=members,autosummary + +make clean +env PYTHONPATH=$PYTHONPATH:$PWD/.. make SPHINXOPTS="-D language='${l}'" html diff --git a/docs/conf.py b/docs/conf.py index e132f2f7..a5ecd2ad 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,15 +7,28 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "SecretFlow PSI Library" -copyright = "2023, SecretFlow authors" +copyright = "2024, SecretFlow authors" author = "SecretFlow authors" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ - "myst_parser", + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", + "sphinx.ext.todo", + "sphinx.ext.viewcode", "sphinx.ext.extlinks", + "sphinx.ext.autosectionlabel", + "myst_parser", + "nbsphinx", + "sphinxcontrib.actdiag", + "sphinxcontrib.blockdiag", + "sphinxcontrib.nwdiag", + "sphinxcontrib.packetdiag", + "sphinxcontrib.rackdiag", + "sphinxcontrib.seqdiag", + "sphinx_design", ] templates_path = ["_templates"] @@ -80,3 +93,37 @@ "show_nav_level": 4, "language_switch_button": True, } + +myst_enable_extensions = [ + "amsmath", + "colon_fence", + "deflist", + "dollarmath", + "fieldlist", + "html_admonition", + "html_image", + "linkify", + "replacements", + "smartquotes", + "strikethrough", + "substitution", + "tasklist", +] + + +suppress_warnings = ["myst.header"] + +myst_gfm_only = True +myst_heading_anchors = 1 +myst_title_to_header = True + + +# app setup hook +def setup(app): + app.add_config_value( + "recommonmark_config", + { + "auto_toc_tree_section": "Contents", + }, + True, + ) \ No newline at end of file diff --git a/docs/getting_started.rst b/docs/getting_started.rst index d59331a4..12945fb6 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -3,7 +3,7 @@ Getting started Welcome to SecretFlow PSI Library. There are multiple methods to use PSI/PIR. -* C++ binaries, you could build the binary or with release docker image. +* C++ binaries, you could build the binary or with release docker image: `secretflow/release-ci:latest` (`secretflow/release-ci-aarch64:latest` for ARM). * Python packages * `SPU `_ warps the library as Python bindings. You could call PSI/PIR with spu. @@ -14,13 +14,12 @@ Welcome to SecretFlow PSI Library. There are multiple methods to use PSI/PIR. * `SCQL `_ integrates this library to do JOIN operations. * `SecretPad `_ provides PSI component. - * `Easy PSI `_ provides most functionality of this library with User Interface. -For PSI, we have a developing v2 PSI. +For `PSI`, we have a developing :doc:`v2 PSI `, and we recommend using it. +------------------------+------------------------------------------------+---------------------------------------------+ -| | PSI v1 APIs | PSI v2 APIs | +| | PSI v1 APIs(Deprecated) | PSI v2 APIs | +========================+================================================+=============================================+ | Supported Protocols | ECDH, KKRT, ECDH_OPRF_UB, DP_PSI, RR22 | ECDH, KKRT, RR22, ECDH_OPRF_UB | +------------------------+------------------------------------------------+---------------------------------------------+ @@ -45,7 +44,7 @@ C++ binaries Release Docker """""""""""""" -Please check official release docker image at `dockerhub `_. We also have mirrors at Alibaba Cloud: secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8. +Please check official release docker image at `dockerhub `_. We also have mirrors at Alibaba Cloud: `secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`. Building from Source @@ -72,18 +71,19 @@ Please check `SecretFlow Installation page ` - Component: https://www.secretflow.org.cn/docs/secretflow/latest/en-US/component/comp_list#psi @@ -104,8 +104,8 @@ SecretPad Please check `SecretPad handbook `_. -Easy PSI -"""""""" +(Deprecated) Easy PSI +"""""""""""""""""""""""" Please check `Easy PSI handbook `_. @@ -121,7 +121,7 @@ System Setup Dev Docker """""""""" -We use the same dev docker from secretflow/ubuntu-base-ci:: +You can use docker to compile:: ## start container docker run -d -it --name psi-dev-$(whoami) \ @@ -131,7 +131,7 @@ We use the same dev docker from secretflow/ubuntu-base-ci:: --cap-add=NET_ADMIN \ --privileged=true \ --entrypoint="bash" \ - secretflow/ubuntu-base-ci:latest + secretflow/release-ci:latest # attach to build container @@ -151,6 +151,7 @@ You need to install: * golang * xxd * lld +* perl>=5.20.3.1 For bazel, please check version in `.bazeliskrc `_ or use bazelisk instead. diff --git a/docs/index.rst b/docs/index.rst index c66f53d3..3c049627 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,12 +6,10 @@ Welcome to SecretFlow PSI Library's documentation! ================================================== -This is the repo of Private Set Intersection(PSI) and Private Information Retrieval(PIR) from SecretFlow team, which provides PSI and PIR functionality for `SecretFlow `_ , `SCQL `_ , `SecretPad `_ and `Easy PSI `_. +This is the repo of Private Set Intersection(PSI) and Private Information Retrieval(PIR) from SecretFlow team, which provides PSI and PIR functionality for `SecretFlow `_ , `SCQL `_ and `SecretPad `_. This repo is formerly psi/pir part from `secretflow/spu `_ repo. -We invite you to try `Easy PSI `_, a standalone PSI product powered by this library. - .. toctree:: :maxdepth: 2 :hidden: diff --git a/docs/locale/zh_CN/LC_MESSAGES/development/index.po b/docs/locale/zh_CN/LC_MESSAGES/development/index.po new file mode 100644 index 00000000..5023da26 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/development/index.po @@ -0,0 +1,27 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 15:24+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../development/index.rst:2 +msgid "Development" +msgstr "开发者指南" + +#: ../../development/index.rst:4 +msgid "Advanced topics related to principles, designs, benchmark and more." +msgstr "原理、设计和性能对比相关的高级主题" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/development/psi_protocol_intro.po b/docs/locale/zh_CN/LC_MESSAGES/development/psi_protocol_intro.po new file mode 100644 index 00000000..722acc73 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/development/psi_protocol_intro.po @@ -0,0 +1,1072 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 15:24+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../development/psi_protocol_intro.rst:2 +msgid "PSI Protocols Introduction" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:4 +msgid "SecretFlow SPU implements the following PSI protocols," +msgstr "" + +#: ../../development/psi_protocol_intro.rst:6 +msgid "Semi-honest ECDH-based two-party PSI protocol [HFH99]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:7 +msgid "Semi-honest ECDH-based three-party PSI protocol" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:8 +msgid "Semi-honest OT-based two-party PSI protocol [KKRT16]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:9 +msgid "Differentially Private (DP) PSI Protocol [DP-PSI]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:10 +msgid "Unbalanced PSI Protocol" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:11 +msgid "" +"Semi-honest and Malicious VOLE-based two-party PSI protocol [RS21]_ " +"[RR22]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:14 +msgid "ECDH-PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:16 +msgid "" +"The semi-honest DH-PSI protocol is due to Huberman, Franklin, and Hogg " +"[HFH99]_, but with roots as far back as Meadows [Mea86]_. It is a semi-" +"honest protocol that requires exponentiations in a Diffie-Hellman group " +"proportional to the number of items in the sets." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:20 +msgid "" +"As a general rule, OT-based PSI protocols are (significantly) faster but " +"require more communication than Diffie-Hellman-based PSI protocols. In " +"some scenarios, communication cost is overwhelmingly more important than " +"computation cost." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:24 +msgid "DH-PSI protocol based on the Decisional Diffie-Hellman assumption:" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:26 +msgid "Agree on a group G, with a generator g." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:27 +msgid "" +"The assumption: for random a,b,c cannot distinguish :math:`(g^a, g^b, " +"g^{ab})` from :math:`(g^a, g^b, g^c)`" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:29 +msgid "" +"Several candidate groups are widely used, such as subgroups of the " +"multiplication group of a finite field and elliptic curve groups. In " +"practice, carefully chosen elliptic curves like Curve25519 [Ber06]_ offer" +" a good balance between security and performance." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:35 +msgid "" +"For each element :math:`x_i` in its set, Alice applies the hash function " +"and then exponentiates it using its key :math:`\\alpha`, thus computing " +":math:`{H(x_i)}^\\alpha` . Alice sends " +":math:`\\{\\{H(x_i)\\}^\\alpha\\}_{i=1}^{n_1}` to Bob." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:39 +msgid "" +"For each element :math:`{H(x_i)}^\\alpha` received from Alice in the " +"previous step, Bob exponentiates it using its key :math:`\\beta`, " +"computing :math:`{H(x_i)}^{\\alpha\\beta}`. Bob sends " +":math:`{\\{\\{H(x_i)\\}^{\\alpha\\beta}\\}}_{i=1}^{n_1}` to Alice." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:43 +msgid "" +"For each element :math:`y_i` in its set, Bob applies the hash function " +"and then exponentiates it using its key :math:`\\beta`, thus computing " +":math:`{H(y_i)}^\\beta` . Bob sends the set " +":math:`\\{\\{H(y_i)\\}^\\beta\\}_{i=1}^{n_2}` to Alice." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:47 +msgid "" +"For each element :math:`{H(y_i)}^\\beta` received from Bob in the " +"previous step, Alice exponentiates it using its key :math:`\\alpha`, " +"computing :math:`{H(y_i)}^{\\beta\\alpha}` ." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:50 +msgid "" +"Alice compares two set " +":math:`{\\{\\{H(x_i)\\}^{\\alpha\\beta}\\}}_{i=1}^{n_1}` and " +":math:`{\\{\\{H(y_i)\\}^{\\beta\\alpha}\\}}_{i=1}^{n_2}` and gets " +"intersection." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:53 +msgid "The Elliptic Curve groups, supported in secretflow SPU PSI module." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:56 +msgid "EC group" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:56 +#: ../../development/psi_protocol_intro.rst:362 +msgid "Reference" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:56 +msgid "CryptoLib" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:58 +msgid "Curve25519" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:58 +msgid "[Ber06]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:58 +msgid "`LibSoidum `_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:60 +msgid "[ipp-crypto]_ (Intel® CPU support AVX-512 IFMA)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:62 +msgid "Secp256k1" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:62 +msgid "[SEC2-v2]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:62 +#: ../../development/psi_protocol_intro.rst:64 +msgid "`OpenSSL `_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:64 +msgid "SM2" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:64 +msgid "GBT.32918.1-2016" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:66 +msgid "ISO/IEC 14888-3:2018" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:68 +msgid "FourQ" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:68 +msgid "[FourQ]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:68 +msgid "`FourQlib `_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:72 +msgid "ECDH-PSI (3P)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:74 +msgid "" +"We implement our own three-party PSI protocol based on ECDH. Note that " +"our implementation has known leakage, please use at your own risk." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:77 +msgid "" +"Assume Alice, Bob, Charlie (receiver) want to perform 3P PSI, in addition" +" to the final output, our protocol leaks the intersection size of Alice's" +" data and Bob's data to Charlie." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:82 +msgid "" +"Note that at the beginning of ECDH-PSI protocol, we assume the input data" +" from both Alice and Charlie are shuffled (It's not necessary to shuffle " +"Bob's set)." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:85 +#: ../../development/psi_protocol_intro.rst:150 +msgid "Protocol:" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:87 +msgid "" +"For i-th element in its set, Alice calculates :math:`H(x_i)^\\alpha` and " +"sends to Bob." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:89 +msgid "" +"For i-th element, Bob calculates :math:`H(x_i)^{\\alpha\\beta}` and " +":math:`H(y_i)^\\beta`, then shuffles them randomly and sends them to " +"Alice." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:92 +msgid "" +"For i-th element, Alice calculates :math:`H(y_i)^{\\alpha\\beta}` and " +"gets the intersection of :math:`H(x_i)^{\\alpha\\beta} \\cap " +"H(y_i)^{\\alpha\\beta}` (we denote the intersection as " +":math:`I^{\\alpha\\beta}`), then sends :math:`I^{\\alpha\\beta}` to " +"Charlie." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:96 +msgid "" +"For i-th element, Charlie sends :math:`H(z_i)^{\\gamma}` to Bob, Bob " +"calculates and sends to Alice :math:`H(z_i)^{\\beta\\gamma}`, finally " +"Alice calculates and sends to Charlie " +":math:`H(z_i)^{\\alpha\\beta\\gamma}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:100 +msgid "" +"Charlie calculates :math:`I^{\\alpha\\beta\\gamma}` and compares " +":math:`I^{\\alpha\\beta\\gamma}` with " +":math:`H(z_i)^{\\alpha\\beta\\gamma}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:104 +msgid "KKRT16-PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:106 +msgid "" +"[KKRT16]_ is semi-honest OT-based PSI, based on OT Extension, BaRK-OPRF " +"and CuckooHash. [KKRT16]_ is the first PSI protocol requiring only one " +"minute for the case of larger sets ( :math:`2^{24}` items each) of long " +"strings (128 bits)." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:110 +msgid "We use 3-way stash-less CuckooHash proposed in [PSZ18]_." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:114 +msgid "" +"Sender and Receiver Agree on CuckooHash :math:`h_1,h_2,h_3: " +"{\\{0,1\\}}^{*} \\rightarrow [m]`" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:115 +msgid "" +"Receiver inserts each x into bin :math:`h_1(x)`, :math:`h_2(x)` or " +":math:`h_3(x)`" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:116 +msgid "" +"Sender inserts each y into bin :math:`h_1(y)`, :math:`h_2(y)` and " +":math:`h_3(y)`" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:117 +msgid "" +"Run BaRK-OPRF, Receiver gets :math:`F_{s,k_i}(x)`,Sender gets " +":math:`F_{s,k_i}(y)`, for :math:`bin_i`" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:118 +msgid "Sender sends all :math:`\\{F_{s,k_i}(y)\\}` values to Receiver" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:119 +msgid "Receiver compares two BaRK-OPRFs set and obtains the intersection." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:123 +msgid "Differentially Private PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:125 +msgid "" +"We also implement a Differentially Private (DP) Private Set Intersection " +"(PSI) Protocol. Our implementation bases on ECDH-PSI, and provides:" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:128 +msgid "Differentially private PSI results." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:130 +msgid "This feature is currently under test, please use at your own risk!" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:132 +msgid "" +"Why PSI with differentially private results? If we want a scheme that " +"protects both the private inputs and output privacy, an ideal way is to " +"use `circuit PSI`, which is a typical PSI variant that allows secure " +"computation (e.g. MPC or HE) on the PSI result without revealing it. " +"`PSTY19 `_ However those protocols " +"are expensive in terms of efficiency." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:139 +msgid "" +"DP-PSI is a way of utilizing the up-sampling and sub-sampling mechanism " +"to add calibrated noises to the PSI results, without revealing its " +"concise value." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:142 +msgid "" +"The protocol is listed below, assume Alice has a (hashed and shuffled) " +"set :math:`X` and Bob has a (hashed and shuffled) :math:`Y`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:147 +msgid "" +"Note that we use \"encrypt\" to denote the process of calculating " +":math:`y\\gets x^a`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:152 +msgid "" +"Alice and Bob first encrypts their own dataset, and gets :math:`X^a` and " +":math:`Y^b` separately." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:155 +msgid "Alice sends :math:`X^a` to Bob." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:157 +msgid "" +"Bob performs random subsampling on :math:`Y^b`, gets :math:`Y_*^b` and " +"sends it to Alice. In the meantime, on receiving :math:`X^a` from Alice, " +"Bob re-encrypts it with :math:`b`, gets :math:`X^{ab}`. Then it samples a" +" random permutation :math:`\\pi` to permute Alice's set, and sends " +"permuted :math:`\\pi(X^{ab})` back to Alice." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:163 +msgid "" +"On receiving :math:`Y_*^b` and :math:`\\pi(X^{ab})` from Bob, Alice re-" +"encrypts :math:`Y_*^b` and gets :math:`Y_*^{ab}`, then calculates the " +"intersection :math:`I_*^{ab}\\gets\\pi(X^{ab})\\cap Y_*^{ab}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:167 +msgid "" +"Alice randomly subsamples the intersection, gets :math:`I_{**}^{ab}`, and" +" then finds their corresponding index in :math:`Y_*^b`. Then randomly " +"adds non-intersection index to this set." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:171 +msgid "Alice sends the index set to Bob, then Bob reveals the final results." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:173 +msgid "" +"In the end, this scheme ensures that the receiver (Bob) only learns the " +"noised intersection, without the ability of pointing out whether an " +"element is in the actual set intersection or not." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:177 +msgid "" +"Note that multiple invocations of DP-PSI inevitably weaken the privacy " +"protection, therefore, we strongly suggest that user should implement a " +"protection mechanism to prevent multiple DP-PSI executions on the same " +"input value." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:183 +msgid "Intel(R) Xeon(R) Platinum" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:183 +msgid "2^20" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:183 +msgid "2^21" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:183 +msgid "2^22" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:183 +msgid "2^23" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:183 +msgid "2^24" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:185 +msgid "DP-PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:185 +msgid "9.806s" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:185 +msgid "20.134s" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:185 +msgid "42.067s" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:185 +msgid "86.580s" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:185 +msgid "170.359s" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:188 +msgid "" +"For DP, our default privacy protection strength is :math:`\\epsilon=3`. " +"For more details, please refer to the original paper: [DP-PSI]_" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:192 +#: ../../development/psi_protocol_intro.rst:243 +msgid "Unbalanced PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:195 +msgid "Ecdh-OPRF based PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:197 +msgid "" +"[RA18]_ section 3 introduces Basic Unbalanced PSI(Ecdh-OPRF based) " +"protocol proposed in [BBCD+11]_ that relaxes the security of the [JL10]_ " +"to be secure against semi-honest adversaries. The protocol has two " +"phases, the preprocessing phase and the online phase. The authors " +"introduced many optimizations to push as much computation and " +"communication cost to the preprocessing phase as possible." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:202 +msgid "" +"An Oblivious Pseudorandom Function (OPRF) is a two-party protocol between" +" client and server for computing the output of a Pseudorandom Function " +"(PRF). [draft-irtf-cfrg-voprf-10]_ specifies OPRF, VOPRF, and POPRF " +"protocols built upon prime-order groups." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:208 +msgid "Offline Phase" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:210 +msgid "" +"For each element :math:`y_i` in its set, Bob applies PRF using private " +"key :math:`\\beta`, i.e. computing :math:`H_2(y_i,{H_1(y_i)}^\\beta)` ." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:213 +msgid "" +"Bob sends :math:`\\{\\{H_2(y_i,{H_1(y_i)}^\\beta)\\}\\}_{i=1}^{n_2}` to " +"Alice in shuffled order." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:215 +msgid "Online Phase" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:217 +msgid "" +"For each element :math:`x_i` in its set, Alice applies the hash function " +"and then exponentiates it using its blind key :math:`r_i`, thus computing" +" :math:`{H_1(x_i)}^{r_i}`. Alice sends " +":math:`\\{\\{H_1(x_i)\\}^{r_i}\\}_{i=1}^{n_1}` to Bob." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:220 +msgid "" +"For each element :math:`H_1(x_i)^{r_i}` received from Alice in the " +"previous step, Bob exponentiates it using its key :math:`\\beta`, " +"computing :math:`{H_1(x_i)}^{r_i\\beta}`. Bob sends " +":math:`{\\{\\{H_1(x_i)\\}^{\\{r_i\\}\\beta}\\}}_{i=1}^{n_1}` to Alice." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:223 +msgid "" +"Alice receives :math:`{\\{\\{H_1(x_i)\\}^{r_i\\beta}\\}}_{i=1}^{n_1}` " +"from Bob, and unblinds it using :math:`r_i`, gets " +":math:`\\{\\{\\{H_1(x_i)\\}^\\beta\\}\\}_{i=1}^{n_1}`, computes OPRF " +":math:`\\{\\{H_2(x_i,{H_1(x_i)}^\\beta)\\}\\}_{i=1}^{n_1}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:225 +msgid "" +"Alice compares two sets " +":math:`\\{\\{H_2(x_i,{H_1(x_i)}^\\beta)\\}\\}_{i=1}^{n_1}` and " +":math:`\\{\\{H_2(y_i,{H_1(y_i)}^\\beta)\\}\\}_{i=1}^{n_2}` and gets " +"intersection." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:229 +#: ../../development/psi_protocol_intro.rst:245 +msgid "Labeled PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:231 +msgid "" +"Somewhat homomorphic encryption (SHE) can be used to build efficient " +"(labeled) Private Set Intersection protocols in the unbalanced setting, " +"where one of the sets is much larger than the other. [CMGD+21]_ " +"introduces several optimizations and improvements to the protocols of " +"[CLR17]_, [CHLR18]_, resulting in improved running time and improved " +"communication complexity in the sender's set size." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:237 +msgid "" +"Microsoft `APSI (Asymmetric PSI) `_ " +"library provides a PSI functionality for asymmetric set sizes based on " +"the latest [CMGD+21]_. APSI uses the BFV([FV12]_) encryption scheme " +"implemented in the Microsoft [SEAL]_ library." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:241 +msgid "" +"SecretFlow SPU wraps `APSI `_ library," +" can be used for" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:244 +msgid "Malicious PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:246 +msgid "Keyword PIR" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:250 +msgid "Setup Phase" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:252 +msgid "**Choose ItemParams**, TableParams, QueryParams, SEALParams." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:253 +msgid "" +"**Sender's OPRF**: The sender samples a key :math:`\\beta` for the OPRF, " +"updates its items set to " +":math:`\\{\\{H_2(s_i,{H_1(s_i)}^\\beta)\\}\\}_{s_i\\in S}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:255 +msgid "" +"**Sender's Hashing**: Sender inserts all :math:`s_i\\in S` into the sets " +":math:`\\mathcal{B}[h_0(s_i)]`, :math:`\\mathcal{B}[h_1(s_i)]` and " +":math:`\\mathcal{B}[h_2(s_i)]`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:257 +msgid "" +"**Splitting**: For each set :math:`\\mathcal{B}[i]`, the sender splits it" +" into bin bundles, denoted as :math:`\\mathcal{B}[i,1]`, ..., " +":math:`\\mathcal{B}[i,k]`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:259 +msgid "**Computing Coeffcients**:" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:261 +msgid "" +"**Matching Polynomial**: For each bin bundle :math:`\\mathcal{B}[i,j]`, " +"the sender computes the matching polynomial over :math:`\\mathbb{F}_t`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:263 +msgid "" +"**Label Polynomial**: If the sender has labels associated with its set, " +"then for each bin bundle :math:`\\mathcal{B}[i,j]`, the sender " +"interpolates the label polynomial over :math:`\\mathbb{F}_t`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:266 +msgid "Intersection Phase" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:268 +msgid "Receiver Encrypt :math:`r_i \\in R`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:270 +msgid "" +"**Receiver's OPRF**: Receiver and Sender run ecdh-OPRF protocol, get " +":math:`\\{\\{H_2(r_i,{H_1(r_i)}^\\beta)\\}\\}_{r_i\\in R}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:272 +msgid "" +"**Receiver's CuckooHash**: Receiver performs cuckoo hashing on the set " +":math:`R` into CuckooTable C with m bins using h1; h2; h3 has the hash " +"functions." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:274 +msgid "" +"**Packing**: Receiver packs items in CuckooTable C into a FHE plaintext " +"polynomial." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:275 +msgid "**Windowsing**: the receiver computes the component-wise query powers." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:276 +msgid "" +"**Encrypt**: The receiver uses *FHE.Encrypt* to encrypt query powers and " +"sends the ciphertexts to the sender." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:278 +msgid "" +"**Sender Homomorphically evaluate Matching Polynomial**: The sender " +"receives the collection of ciphertexts and homomorphically evaluates " +"Matching Polynomial. If Labeled PSI is desired, Sender homomorphically " +"evaluates Label Polynomial. The sender sends evaluated ciphertexts to " +"Receiver." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:281 +msgid "" +"**Receiver Decrypt and Get result**: receiver receives and decrypts the " +"matching ciphertexts, and labels ciphertexts if needed, outputs the " +"matching set and labels." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:284 +msgid "Labeled PSI Parameters" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:287 +msgid "Params" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:287 +msgid "function" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:289 +msgid "1" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:289 +msgid "ItemParams" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:291 +msgid "felts_per_item" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:291 +msgid "" +"how many Microsoft SEAL batching slots should represent each item = " +"item_bit_size / plain_modulus_bits item_bit_size = stats_params + " +"log(ns)+log(nr)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:295 +msgid "2" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:295 +msgid "TableParams" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:297 +msgid "hash_func_count" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:297 +msgid "" +"cuckoo hash count. if nr>1,hash_func_count = 3 nr=1-> hash_func_count=1 " +"means essentially disabling cuckoo hashing" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:300 +msgid "table_size" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:300 +msgid "positive multiple of floor(poly_modulus_degree/felts_per_item)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:302 +msgid "max_items_per_bin" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:302 +msgid "how many items fit into each row of the sender's bin bundles" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:304 +msgid "3" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:304 +msgid "QueryParams" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:306 +msgid "ps_low_degree" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:306 +msgid "" +"any number between 0 and max_items_per_bin If set to zero, the Paterson-" +"Stockmeyer algorithm is not used ps_low_degree > 1, use Paterson-" +"Stockmeyer algorithm" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:310 +msgid "query_powers" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:310 +msgid "" +"how many items fit into each row of the sender's bin bundles ref Challis " +"and Robinson (2010) to determine good source powers" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:313 +msgid "4" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:313 +msgid "SEALParams" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:315 +msgid "poly_modulus_degree" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:315 +msgid "2048 / 4096 / 8192" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:317 +msgid "plain_modulus(_bits)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:317 +msgid "16(65535) / 22(bits)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:319 +msgid "coeff_modulus_bits" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:319 +msgid "{48} / {48, 30, 30} / {56, 56, 56, 50}" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:323 +msgid "RR22 Blazing Fast PSI" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:325 +msgid "" +"[RS21]_ introduced an efficient PSI protocol based on OKVS and VOLE. " +"[RR22]_ present significant improvements to the OKVS data structure along" +" with new techniquesfor further reducing the communication overhead of " +"[RS]21." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:328 +msgid "" +"Oblivous Key-Value Stores(OKVS) consists of algorithms Encode and Decode." +" Encode takes a list of key-value (k,v) pairs as input and returns an " +"abstract data structure S. Decode takes such a data structure S and a key" +" k' as input, and gives some output v'." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:332 +msgid "" +"Pseudorandom correlation generators(PCGs) allow for the efficient " +"generation of oblivious transfer (OT) and vector oblivious linear " +"evaluations (VOLE) with sublinear communication and concretely good " +"computational overhead. PCG makes use of a so-called LPN-friendly " +"errorcorrecting code. `secretflow/YACL " +"`_ provides VOLE code " +"implementation. LPN-friendly coeds now support [CRR21]_ silver " +"codes(LDPC) and [BCGI+22]_ Expand-Accumulate Codes. Silver is Most " +"efficient, but not recommended to use due to its security flaw." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:340 +msgid "Semi-honest Protocol:" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:344 +msgid "" +"The Receiver samples :math:`r \\leftarrow \\{0,1\\}^\\kappa` and computes" +" :math:`\\vec{P} := \\mathrm{Encode} (L,r)` where :math:`L := " +"\\{(H^{n*m}(x,r),H(x))|x \\in X\\}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:348 +msgid "" +"Sender and Receiver Run (sub)VOLE protocol, Sender gets :math:`\\Delta` " +"and :math:`\\vec{B}`, Receiver gets :math:`\\vec{A}` and " +":math:`\\vec{C}`, such that: :math:`\\vec{C}=\\Delta " +"*\\vec{A'}+\\vec{B}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:352 +msgid "" +"Receiver sends :math:`r, \\vec{A}=\\vec{A'}+\\vec{P}` to Sender. Sender " +"defines :math:`\\vec{K}=\\vec{B}+\\Delta \\cdot \\vec{A}`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:355 +msgid "" +"Sender sends :math:`Y'=H^{n*m}(\\vec{Y},r)\\cdot \\vec{K}-\\Delta \\cdot " +"H(\\vec{Y})` to the Receiver." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:358 +msgid "" +"Receiver compares :math:`X'=H^{n*m}(\\vec{X},r)\\cdot \\vec{C}` and " +":math:`Y'`, outputs intersection result :math:`X \\cap Y`." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:364 +msgid "" +"E. Boyle, G. Couteau, N. Gilboa, and Y. Ishai. Compressing vector OLE. In" +" ACM CCS 2018, pages 896–912. ACM Press, October 2018." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:367 +#: ../../development/psi_protocol_intro.rst:371 +msgid "" +"E. Boyle, G. Couteau, N. Gilboa, Y. Ishai, L. Kohl, P. Rindal, and P. " +"Scholl. Efficient two-round OT extension and silent non-interactive " +"secure computation. In ACM CCS 2019, pages 291–308. ACM Press, November " +"2019." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:375 +msgid "" +"Daniel J. Bernstein. Curve25519: new diffie-hellman speed records. In In " +"Public Key Cryptography (PKC), Springer-Verlag LNCS 3958, page 2006, " +"2006. (Cited on page 4.)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:378 +msgid "" +"Elette Boyle, Geoffroy Couteau, Niv Gilboa, Yuval Ishai, Lisa Kohl, " +"Nicolas Resch, Peter Scholl. Correlated Pseudorandomness from Expand-" +"Accumulate Codes. Crypto2022." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:381 +msgid "" +"Baldi, P., Baronio, R., Cristofaro, E.D., Gasti, P., Tsudik, G.: " +"Countering GATTACA: Efficient and Secure Testing of Fully-sequenced Human" +" Genomes. In: ACM Conference on Computer and Communications Security. pp." +" 691–702. ACM (2011)." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:385 +msgid "" +"G. Couteau, Y. Ishai, L. Kohl, E. Boyle, P. Scholl, and N. Gilboa. " +"Efficient pseudorandom correlation generators from ring-lpn. Springer-" +"Verlag, 2020." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:388 +msgid "" +"Chen, H., Huang, Z., Laine, K., Rindal, P.: Labeled PSI from fully " +"homomorphic encryption with malicious security. In: Lie, D., Mannan, M., " +"Backes, M., Wang, X. (eds.) ACM CCS 2018. pp. 1223{1237. ACM Press (Oct " +"2018). https://doi.org/10.1145/3243734.3243836" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:392 +msgid "" +"Chen, H., Laine, K., Rindal, P.: Fast private set intersection from " +"homomorphic encryption. In: Thuraisingham, B.M., Evans, D., Malkin, T., " +"Xu, D. (eds.) ACM CCS 2017. pp. 1243{1255. ACM Press (Oct / Nov 2017). " +"https://doi.org/10.1145/3133956.3134061" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:396 +msgid "" +"Kelong Cong, Radames Cruz Moreno, Mariana Botelho da Gama, Wei Dai, Ilia " +"Iliashenko, Kim Laine, Michael Rosenberg. Labeled PSI from Homomorphic " +"Encryption with Reduced Computation and Communication CCS'21: Proceedings" +" of the 2021 ACM SIGSAC Conference on Computer and Communications " +"SecurityNovember 2021" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:400 +msgid "" +"Geoffroy Couteau, Peter Rindal, and Srinivasan Raghuraman. Silver: Silent" +" VOLE and Oblivious Transfer from Hardness of Decoding Structured LDPC " +"Codes. Crypto2021." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:403 +msgid "Differentially-Private PSI https://arxiv.org/pdf/2208.13249.pdf" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:405 +msgid "" +"Costello, C., Longa, P.: Fourq: four-dimensional decompositions on a " +"q-curve over the mersenne prime. Cryptology ePrint Archive, Report " +"2015/565 (2015), https://eprint.iacr.org/2015/565" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:408 +msgid "" +"Fan, J., Vercauteren, F.: Somewhat practical fully homomorphic " +"encryption. Cryptology ePrint Archive, Report 2012/144 (2012), " +"http://eprint.iacr.org/2012/144.pdf" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:411 +msgid "" +"Bernardo A. Huberman, Matt Franklin, and Tad Hogg. Enhancing privacy and " +"trust in electronic communities. In ACM CONFERENCE ON ELECTRONIC " +"COMMERCE. ACM, 1999." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:414 +msgid "https://github.com/intel/ipp-crypto/" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:416 +msgid "" +"Jarecki, S., Liu, X.: Fast Secure Computation of Set Intersection. In: " +"SCN. LNCS, vol. 6280, pp. 418–435. Springer (2010)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:419 +msgid "" +"V. Kolesnikov, R. Kumaresan, M. Rosulek, and N. Trieu. Efficient batched " +"oblivious PRF with applications to private set intersection. In ACM CCS " +"2016, pages 818–829. ACM Press, October 2016." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:422 +msgid "" +"C. Meadows. A more efficient cryptographic matchmaking protocol for use " +"in the absence of a continuously available third party. In 1986 IEEE " +"Symposium on Security and Privacy, pages 134–134, April 1986." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:425 +msgid "" +"B. Pinkas, T. Schneider, and M. Zohner. Scalable private set intersection" +" based on ot extension. ACM Transactions on Privacy and Security (TOPS), " +"21(2):1–35, 2018." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:428 +msgid "" +"Resende, A.C.D., Aranha, D.F.: Faster unbalanced private set " +"intersection. In: Meiklejohn, S., Sako, K. (eds.) FC2018. LNCS, vol. " +"10957, pp. 203{221. Springer, Heidelberg (Feb / Mar 2018)" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:431 +msgid "" +"Srinivasan Raghuraman and Peter Rindal. Blazing Fast PSI from Improved " +"OKVS and Subfield VOLE. CCS'22." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:433 +msgid "" +"Srinivasan Raghuraman, Peter Rindal, Titouan Tanguy. Expand-Convolute " +"Codes for Pseudorandom Correlation Generators from LPN. Crypto2023." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:436 +msgid "" +"Peter Rindal and Phillipp Schoppmann. VOLE-PSI: fast OPRF and circuit-psi" +" from vector-ole. EUROCRYPT2021." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:438 +msgid "" +"Microsoft SEAL (release 4.0). https://github.com/Microsoft/SEAL (Sep " +"2022), microsoft Research, Redmond, WA." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:441 +msgid "" +"Standards for Efficient Cryptography (SEC) " +"" +msgstr "" + +#: ../../development/psi_protocol_intro.rst:443 +msgid "" +"P. Schoppmann, A. Gascón, L. Reichert, and M. Raykova. Distributed " +"vector-OLE: Improved constructions and implementation. In ACM CCS 2019, " +"pages 1055–1072. ACM Press, November 2019." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:446 +msgid "" +"C. Weng, K. Yang, J. Katz, and X. Wang. Wolverine: fast, scalable, and " +"communication-efficient zero-knowledge proofs for boolean and arithmetic " +"circuits. In 2021 IEEE Symposium on Security and Privacy (SP), pages " +"1074–1091. IEEE, 2021." +msgstr "" + +#: ../../development/psi_protocol_intro.rst:450 +msgid "" +"Oblivious Pseudorandom Functions (OPRFs) using Prime-Order Groups. " +"https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-10.html" +msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/getting_started.po b/docs/locale/zh_CN/LC_MESSAGES/getting_started.po new file mode 100644 index 00000000..21f5d193 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/getting_started.po @@ -0,0 +1,425 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-26 20:09+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../getting_started.rst:2 +msgid "Getting started" +msgstr "开始教程" + +#: ../../getting_started.rst:4 +msgid "" +"Welcome to SecretFlow PSI Library. There are multiple methods to use " +"PSI/PIR." +msgstr "欢迎使用SecretFlow PSI Library。有多种方式调用PSI、PIR功能。" + +#: ../../getting_started.rst:6 +msgid "" +"C++ binaries, you could build the binary or with release docker image: " +"`secretflow/release-ci:latest` (`secretflow/release-ci-aarch64:latest` " +"for ARM)." +msgstr "" +"可以直接编译或者使用镜像 `secretflow/release-ci:latest` (`secretflow/release-ci-" +"aarch64:latest` for ARM) 编译二进制。" + +#: ../../getting_started.rst:7 ../../getting_started.rst:57 +msgid "Python packages" +msgstr "Python 包" + +#: ../../getting_started.rst:9 +msgid "" +"`SPU `_ warps the library as Python " +"bindings. You could call PSI/PIR with spu." +msgstr "`SPU `_ 包含了PSI和PIR功能的python接口。" + +#: ../../getting_started.rst:10 +msgid "" +"`SecretFlow `_ warps SPU further " +"with user-friendly APIs." +msgstr "`SecretFlow `_ 使用SPU的Python接口又包了一层。" + +#: ../../getting_started.rst:13 ../../getting_started.rst:91 +msgid "Applications" +msgstr "应用" + +#: ../../getting_started.rst:15 +msgid "" +"`SCQL `_ " +"integrates this library to do JOIN operations." +msgstr "" +"`SCQL `_ " +"集成了PSI来实现Join操作。" + +#: ../../getting_started.rst:16 +msgid "" +"`SecretPad `_" +" provides PSI component." +msgstr "" +"`SecretPad `_" +" 提供了PSI相关的组件." + +#: ../../getting_started.rst:19 +msgid "" +"For `PSI`, we have a developing :doc:`v2 PSI `, " +"and we recommend using it." +msgstr "对于 `PSI` 功能,我们新开发了 :doc:`v2 PSI ` 配置,建议使用它。" + +#: ../../getting_started.rst:22 +msgid "PSI v1 APIs(Deprecated)" +msgstr "" + +#: ../../getting_started.rst:22 +msgid "PSI v2 APIs" +msgstr "" + +#: ../../getting_started.rst:24 +msgid "Supported Protocols" +msgstr "" + +#: ../../getting_started.rst:24 +msgid "ECDH, KKRT, ECDH_OPRF_UB, DP_PSI, RR22" +msgstr "" + +#: ../../getting_started.rst:24 +msgid "ECDH, KKRT, RR22, ECDH_OPRF_UB" +msgstr "" + +#: ../../getting_started.rst:26 +msgid "CSV parser" +msgstr "" + +#: ../../getting_started.rst:26 +msgid "Support a subset of csv files." +msgstr "" + +#: ../../getting_started.rst:26 +msgid "Apache Arrow, support all legal csv files." +msgstr "" + +#: ../../getting_started.rst:28 +msgid "Recovery after failure" +msgstr "" + +#: ../../getting_started.rst:28 ../../getting_started.rst:30 +msgid "Unsupported" +msgstr "" + +#: ../../getting_started.rst:28 ../../getting_started.rst:30 +msgid "Supported" +msgstr "" + +#: ../../getting_started.rst:30 +msgid "Support duplicated keys" +msgstr "" + +#: ../../getting_started.rst:32 ../../getting_started.rst:45 +msgid "Release Docker" +msgstr "" + +#: ../../getting_started.rst:32 +msgid "Not provided" +msgstr "" + +#: ../../getting_started.rst:32 +msgid "Provided" +msgstr "" + +#: ../../getting_started.rst:34 +msgid "Python Binding" +msgstr "" + +#: ../../getting_started.rst:34 +msgid "with SPU" +msgstr "" + +#: ../../getting_started.rst:39 +msgid "Installation" +msgstr "" + +#: ../../getting_started.rst:42 +msgid "C++ binaries" +msgstr "" + +#: ../../getting_started.rst:47 +msgid "" +"Please check official release docker image at `dockerhub " +"`_. We also have mirrors" +" at Alibaba Cloud: `secretflow-registry.cn-" +"hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`." +msgstr "" +"请查看官方发布镜像 `dockerhub `_." +" 我们也提供了阿里云 镜像: `secretflow-registry.cn-" +"hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`." + +#: ../../getting_started.rst:51 +msgid "Building from Source" +msgstr "源码构建" + +#: ../../getting_started.rst:53 +msgid "Please see :ref:`building`." +msgstr "参考 :ref:`building`." + +#: ../../getting_started.rst:60 +msgid "SPU" +msgstr "" + +#: ../../getting_started.rst:62 +msgid "" +"Please check `SPU Installation Guidelines " +"`_." +msgstr "" +"请查看 `SPU Installation Guidelines " +"`_." + +#: ../../getting_started.rst:64 +msgid "APIs: https://www.secretflow.org.cn/docs/spu/latest/en-US/reference/py_api" +msgstr "" + +#: ../../getting_started.rst:67 +msgid "SecretFlow" +msgstr "" + +#: ../../getting_started.rst:69 +msgid "" +"Please check `SecretFlow Installation page " +"`_." +msgstr "" +"请查看 `SecretFlow Installation page " +"`_." + +#: ../../getting_started.rst:71 +msgid "APIs:" +msgstr "" + +#: ../../getting_started.rst:73 +msgid "PSI v1:" +msgstr "" + +#: ../../getting_started.rst:74 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.psi_df" +msgstr "" + +#: ../../getting_started.rst:75 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.psi_csv" +msgstr "" + +#: ../../getting_started.rst:76 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.psi_join_df" +msgstr "" + +#: ../../getting_started.rst:77 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.psi_join_csv" +msgstr "" + +#: ../../getting_started.rst:79 +msgid "PSI v2:" +msgstr "" + +#: ../../getting_started.rst:80 +msgid "" +"https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.psi_v2" +msgstr "" + +#: ../../getting_started.rst:82 +msgid "PIR:" +msgstr "" + +#: ../../getting_started.rst:83 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.pir_setup" +msgstr "" + +#: ../../getting_started.rst:84 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.pir_query" +msgstr "" + +#: ../../getting_started.rst:85 +msgid "" +"(Deprecated) https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/source/secretflow#secretflow.SPU.pir_memory_query" +msgstr "" + +#: ../../getting_started.rst:86 +msgid ":doc:`pir config `" +msgstr "" + +#: ../../getting_started.rst:88 +msgid "" +"Component: https://www.secretflow.org.cn/docs/secretflow/latest/en-" +"US/component/comp_list#psi" +msgstr "" + +#: ../../getting_started.rst:94 +msgid "SCQL" +msgstr "" + +#: ../../getting_started.rst:96 +msgid "" +"Please check `SCQL Quickstart tutorial " +"`_." +msgstr "" + +#: ../../getting_started.rst:98 +msgid "Featured operators using PSI:" +msgstr "" + +#: ../../getting_started.rst:99 +msgid "" +"https://www.secretflow.org.cn/docs/scql/latest/en-" +"US/reference/operators#in" +msgstr "" + +#: ../../getting_started.rst:100 +msgid "" +"https://www.secretflow.org.cn/docs/scql/latest/en-" +"US/reference/operators#join" +msgstr "" + +#: ../../getting_started.rst:103 +msgid "SecretPad" +msgstr "" + +#: ../../getting_started.rst:105 +msgid "" +"Please check `SecretPad handbook " +"`_." +msgstr "" + +#: ../../getting_started.rst:108 +msgid "(Deprecated) Easy PSI" +msgstr "" + +#: ../../getting_started.rst:110 +msgid "" +"Please check `Easy PSI handbook " +"`_." +msgstr "" +"请查看 `Easy PSI handbook `_." + +#: ../../getting_started.rst:116 +msgid "Building" +msgstr "编译" + +#: ../../getting_started.rst:119 +msgid "System Setup" +msgstr "系统设置" + +#: ../../getting_started.rst:122 +msgid "Dev Docker" +msgstr "开发Docker镜像" + +#: ../../getting_started.rst:124 +msgid "You can use docker to compile::" +msgstr "可以使用Docker来编译 ::" + +#: ../../getting_started.rst:141 +msgid "Linux" +msgstr "" + +#: ../../getting_started.rst:143 +msgid "You need to install:" +msgstr "需要安装:" + +#: ../../getting_started.rst:145 +msgid "gcc>=11.2" +msgstr "" + +#: ../../getting_started.rst:146 +msgid "cmake>=3.26" +msgstr "" + +#: ../../getting_started.rst:147 +msgid "ninja" +msgstr "" + +#: ../../getting_started.rst:148 +msgid "nasm>=2.15" +msgstr "" + +#: ../../getting_started.rst:149 +msgid "python>=3.8" +msgstr "" + +#: ../../getting_started.rst:150 +msgid "bazel" +msgstr "" + +#: ../../getting_started.rst:151 +msgid "golang" +msgstr "" + +#: ../../getting_started.rst:152 +msgid "xxd" +msgstr "" + +#: ../../getting_started.rst:153 +msgid "lld" +msgstr "" + +#: ../../getting_started.rst:154 +msgid "perl>=5.20.3.1" +msgstr "" + +#: ../../getting_started.rst:156 +msgid "" +"For bazel, please check version in `.bazeliskrc " +"`_ or use " +"bazelisk instead." +msgstr "" +"对于bazel,请查看 `.bazeliskrc " +"`_ 中的版本,或者使用 " +"bazelisk。" + +#: ../../getting_started.rst:159 +msgid "Build & UnitTest" +msgstr "构建和单元测试" + +#: ../../getting_started.rst:161 +msgid "We use bazel for building and testing::" +msgstr "我们使用bazel来构建和测试 ::" + +#: ../../getting_started.rst:173 +msgid "Reporting an Issue" +msgstr "报告Issue" + +#: ../../getting_started.rst:175 +msgid "" +"Please create an issue at `Github Issues " +"`_." +msgstr "请提交Issue到 `Github Issues `_ 。" + +#: ../../getting_started.rst:177 +msgid "We will look into issues and get back to you soon." +msgstr "我们会尽快回复issues问题。" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/index.po b/docs/locale/zh_CN/LC_MESSAGES/index.po new file mode 100644 index 00000000..c625fb3b --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/index.po @@ -0,0 +1,48 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 20:55+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../index.rst:7 +msgid "Welcome to SecretFlow PSI Library's documentation!" +msgstr "欢迎查看SecretFlow PSI的相关文档" + +#: ../../index.rst:9 +msgid "" +"This is the repo of Private Set Intersection(PSI) and Private Information" +" Retrieval(PIR) from SecretFlow team, which provides PSI and PIR " +"functionality for `SecretFlow " +"`_ , `SCQL " +"`_ and " +"`SecretPad `_." +msgstr "" +"该仓包含SecretFlow项目中隐私求交(PSI)和隐匿查询(PIR)相关的代码, " +"`SecretFlow " +"`_ , `SCQL " +"`_ 和 " +"`SecretPad `_ 的PSI功能都是通过本仓实现的。" + +#: ../../index.rst:11 +msgid "" +"This repo is formerly psi/pir part from `secretflow/spu " +"`_ repo." +msgstr "" +"本仓之前是 `secretflow/spu " +"`_ 的一部分。" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/reference/index.po b/docs/locale/zh_CN/LC_MESSAGES/reference/index.po new file mode 100644 index 00000000..ad94914b --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/reference/index.po @@ -0,0 +1,27 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 15:24+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../reference/index.rst:2 +msgid "API reference" +msgstr "" + +#: ../../reference/index.rst:4 +msgid "This page covers all Protocol Buffers message as APIs." +msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/reference/launch_config.po b/docs/locale/zh_CN/LC_MESSAGES/reference/launch_config.po new file mode 100644 index 00000000..44554d15 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/reference/launch_config.po @@ -0,0 +1,836 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-26 20:09+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../reference/launch_config.md:1 +msgid "Launch Configuration" +msgstr "" + +#: ../../reference/launch_config.md:3 +msgid "" +"Please check psi.BucketPsiConfig at **PSI v1 Configuration**. Please " +"check psi.v2.PsiConfig and psi.v2.UbPsiConfig at **PSI v2 " +"Configuration**." +msgstr "" + +#: ../../reference/launch_config.md:6 +msgid "Table of Contents" +msgstr "" + +#: ../../reference/launch_config.md:10 ../../reference/launch_config.md:18 +#: ../../reference/launch_config.md:32 ../../reference/launch_config.md:47 +#: ../../reference/launch_config.md:73 ../../reference/launch_config.md:168 +msgid "Messages" +msgstr "" + +#: ../../reference/launch_config.md:11 +msgid "[LaunchConfig](#launchconfig)" +msgstr "" + +#: ../../reference/launch_config.md:19 +msgid "[AllocatedPorts](#allocatedports)" +msgstr "" + +#: ../../reference/launch_config.md:20 +msgid "[ClusterDefine](#clusterdefine)" +msgstr "" + +#: ../../reference/launch_config.md:21 +msgid "[Party](#party)" +msgstr "" + +#: ../../reference/launch_config.md:22 +msgid "[Port](#port)" +msgstr "" + +#: ../../reference/launch_config.md:23 +msgid "[Service](#service)" +msgstr "" + +#: ../../reference/launch_config.md:24 +msgid "[TaskInputConfig](#taskinputconfig)" +msgstr "" + +#: ../../reference/launch_config.md:25 +msgid "[TaskInputConfig.SfPsiConfigMapEntry](#taskinputconfigsfpsiconfigmapentry)" +msgstr "" + +#: ../../reference/launch_config.md:33 +msgid "[ContextDescProto](#contextdescproto)" +msgstr "" + +#: ../../reference/launch_config.md:34 +msgid "[PartyProto](#partyproto)" +msgstr "" + +#: ../../reference/launch_config.md:35 +msgid "[RetryOptionsProto](#retryoptionsproto)" +msgstr "" + +#: ../../reference/launch_config.md:36 +msgid "[SSLOptionsProto](#ssloptionsproto)" +msgstr "" + +#: ../../reference/launch_config.md:41 +msgid "[Scalar Value Types](#scalar-value-types)" +msgstr "" + +#: ../../reference/launch_config.md:50 +msgid "LaunchConfig" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Field" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Type" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Description" +msgstr "" + +#: ../../reference/launch_config.md +msgid "link_config" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ yacl.link.ContextDescProto](#yacllinkcontextdescproto)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Configs for network." +msgstr "" + +#: ../../reference/launch_config.md +msgid "self_link_party" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ string](#string)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "With link_config." +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"[**oneof**](https://developers.google.com/protocol-" +"buffers/docs/proto3#oneof) runtime_config.legacy_psi_config" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ BucketPsiConfig](#bucketpsiconfig)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Please check at psi.proto." +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"[**oneof**](https://developers.google.com/protocol-" +"buffers/docs/proto3#oneof) runtime_config.psi_config" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ v2.PsiConfig](#v2psiconfig)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Please check at psi_v2.proto." +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"[**oneof**](https://developers.google.com/protocol-" +"buffers/docs/proto3#oneof) runtime_config.ub_psi_config" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ v2.UbPsiConfig](#v2ubpsiconfig)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"[**oneof**](https://developers.google.com/protocol-" +"buffers/docs/proto3#oneof) runtime_config.apsi_sender_config" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ ApsiSenderConfig](#apsisenderconfig)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Please check at pir.proto." +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"[**oneof**](https://developers.google.com/protocol-" +"buffers/docs/proto3#oneof) runtime_config.apsi_receiver_config" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ ApsiReceiverConfig](#apsireceiverconfig)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "none" +msgstr "" + +#: ../../reference/launch_config.md:67 ../../reference/launch_config.md:162 +#: ../../reference/launch_config.md:251 +msgid "Enums" +msgstr "" + +#: ../../reference/launch_config.md:76 +msgid "AllocatedPorts" +msgstr "" + +#: ../../reference/launch_config.md:77 +msgid "AllocatedPorts represents allocated ports for pod." +msgstr "" + +#: ../../reference/launch_config.md +msgid "ports" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[repeated Port](#port)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Allocated ports." +msgstr "" + +#: ../../reference/launch_config.md:87 +msgid "ClusterDefine" +msgstr "" + +#: ../../reference/launch_config.md:88 +msgid "ClusterDefine represents the information of all parties." +msgstr "" + +#: ../../reference/launch_config.md +msgid "parties" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[repeated Party](#party)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Basic information of all parties." +msgstr "" + +#: ../../reference/launch_config.md +msgid "self_party_idx" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ int32](#int32)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "index of self party." +msgstr "" + +#: ../../reference/launch_config.md +msgid "self_endpoint_idx" +msgstr "" + +#: ../../reference/launch_config.md +msgid "index of self endpoint." +msgstr "" + +#: ../../reference/launch_config.md:100 +msgid "Party" +msgstr "" + +#: ../../reference/launch_config.md:101 +msgid "Party represents the basic information of the party." +msgstr "" + +#: ../../reference/launch_config.md +msgid "name" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Name of party." +msgstr "" + +#: ../../reference/launch_config.md +msgid "role" +msgstr "" + +#: ../../reference/launch_config.md +msgid "role carried by party. Examples: client, server..." +msgstr "" + +#: ../../reference/launch_config.md +msgid "services" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[repeated Service](#service)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "List of services exposed by pod." +msgstr "" + +#: ../../reference/launch_config.md:113 +msgid "Port" +msgstr "" + +#: ../../reference/launch_config.md:114 +msgid "Port represents an allocated port for pod." +msgstr "" + +#: ../../reference/launch_config.md +msgid "Each named port in a pod must have a unique name." +msgstr "" + +#: ../../reference/launch_config.md +msgid "port" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Number of port allocated for pod." +msgstr "" + +#: ../../reference/launch_config.md +msgid "scope" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Scope of port. Must be Cluster,Domain,Local. Defaults to \"Local\". " +"+optional" +msgstr "" + +#: ../../reference/launch_config.md +msgid "protocol" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Protocol for port. Must be HTTP,GRPC. Defaults to \"HTTP\". +optional" +msgstr "" + +#: ../../reference/launch_config.md:127 +msgid "Service" +msgstr "" + +#: ../../reference/launch_config.md:128 +msgid "Service represents the service address corresponding to the port." +msgstr "" + +#: ../../reference/launch_config.md +msgid "port_name" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Name of port." +msgstr "" + +#: ../../reference/launch_config.md +msgid "endpoints" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[repeated string](#string)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Endpoint list corresponding to the port." +msgstr "" + +#: ../../reference/launch_config.md:139 +msgid "TaskInputConfig" +msgstr "" + +#: ../../reference/launch_config.md +msgid "sf_psi_config_map" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"[map " +"TaskInputConfig.SfPsiConfigMapEntry](#taskinputconfigsfpsiconfigmapentry)" +msgstr "" + +#: ../../reference/launch_config.md:150 +msgid "TaskInputConfig.SfPsiConfigMapEntry" +msgstr "" + +#: ../../reference/launch_config.md +msgid "key" +msgstr "" + +#: ../../reference/launch_config.md +msgid "value" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ psi.LaunchConfig](#psilaunchconfig)" +msgstr "" + +#: ../../reference/launch_config.md:171 +msgid "ContextDescProto" +msgstr "" + +#: ../../reference/launch_config.md:172 +msgid "Configuration for link config." +msgstr "" + +#: ../../reference/launch_config.md +msgid "id" +msgstr "" + +#: ../../reference/launch_config.md +msgid "the UUID of this communication. optional" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[repeated PartyProto](#partyproto)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "party description, describes the world." +msgstr "" + +#: ../../reference/launch_config.md +msgid "connect_retry_times" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ uint32](#uint32)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "connect to mesh retry time." +msgstr "" + +#: ../../reference/launch_config.md +msgid "connect_retry_interval_ms" +msgstr "" + +#: ../../reference/launch_config.md +msgid "connect to mesh retry interval." +msgstr "" + +#: ../../reference/launch_config.md +msgid "recv_timeout_ms" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ uint64](#uint64)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "recv timeout in milliseconds." +msgstr "" + +#: ../../reference/launch_config.md:183 +msgid "" +"'recv time' is the max time that a party will wait for a given event. for" +" example:" +msgstr "" + +#: ../../reference/launch_config.md:185 +msgid "" +"begin recv end recv |--------|-------recv-" +"time----------|------------------| alice's timeline" +msgstr "" + +#: ../../reference/launch_config.md:187 +msgid "" +"begin send end send |-----busy-" +"work-------------|-------------|------------| bob's timeline" +msgstr "" + +#: ../../reference/launch_config.md:189 +msgid "" +"in above case, when alice begins recv for a specific event, bob is still " +"busy doing its job, when alice's wait time exceed wait_timeout_ms, it " +"raise exception, although bob now is starting to send data." +msgstr "" + +#: ../../reference/launch_config.md:191 +msgid "" +"so for long time work(that one party may wait for the others for very " +"long time), this value should be changed accordingly. | | " +"http_max_payload_size | [ uint32](#uint32) | http max payload size, if a " +"single http request size is greater than this limit, it will be unpacked " +"into small chunks then reassembled." +msgstr "" + +#: ../../reference/launch_config.md:194 +msgid "" +"This field does affect performance. Please choose wisely. | | " +"http_timeout_ms | [ uint32](#uint32) | a single http request timetout. | " +"| throttle_window_size | [ uint32](#uint32) | throttle window size for " +"channel. if there are more than limited size messages are flying, " +"`SendAsync` will block until messages are processed or throw exception " +"after wait for `recv_timeout_ms` | | brpc_channel_protocol | [ " +"string](#string) | BRPC client channel protocol. | | " +"brpc_channel_connection_type | [ string](#string) | BRPC client channel " +"connection type. | | enable_ssl | [ bool](#bool) | ssl options for link " +"channel. | | client_ssl_opts | [ SSLOptionsProto](#ssloptionsproto) | ssl" +" configs for channel this config is ignored if enable_ssl == false; | | " +"server_ssl_opts | [ SSLOptionsProto](#ssloptionsproto) | ssl configs for " +"service this config is ignored if enable_ssl == false; | | " +"chunk_parallel_send_size | [ uint32](#uint32) | chunk parallel send size " +"for channel. if need chunked send when send message, the max paralleled " +"send size is chunk_parallel_send_size | | retry_opts | [ " +"RetryOptionsProto](#retryoptionsproto) | retry options |" +msgstr "" + +#: ../../reference/launch_config.md:208 +msgid "PartyProto" +msgstr "" + +#: ../../reference/launch_config.md +msgid "host" +msgstr "" + +#: ../../reference/launch_config.md:220 +msgid "RetryOptionsProto" +msgstr "" + +#: ../../reference/launch_config.md:221 +msgid "Retry options." +msgstr "" + +#: ../../reference/launch_config.md +msgid "max_retry" +msgstr "" + +#: ../../reference/launch_config.md +msgid "max retry count default 3" +msgstr "" + +#: ../../reference/launch_config.md +msgid "retry_interval_ms" +msgstr "" + +#: ../../reference/launch_config.md +msgid "time between retries at first retry default 1 second" +msgstr "" + +#: ../../reference/launch_config.md +msgid "retry_interval_incr_ms" +msgstr "" + +#: ../../reference/launch_config.md +msgid "The amount of time to increase the interval between retries default 2s" +msgstr "" + +#: ../../reference/launch_config.md +msgid "max_retry_interval_ms" +msgstr "" + +#: ../../reference/launch_config.md +msgid "The maximum interval between retries default 10s" +msgstr "" + +#: ../../reference/launch_config.md +msgid "error_codes" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[repeated uint32](#uint32)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "retry on these brpc error codes, if empty, retry on all codes" +msgstr "" + +#: ../../reference/launch_config.md +msgid "http_codes" +msgstr "" + +#: ../../reference/launch_config.md +msgid "retry on these http codes, if empty, retry on all http codes" +msgstr "" + +#: ../../reference/launch_config.md +msgid "aggressive_retry" +msgstr "" + +#: ../../reference/launch_config.md +msgid "[ bool](#bool)" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"do aggressive retry, this means that retries will be made on additional " +"error codes" +msgstr "" + +#: ../../reference/launch_config.md:237 +msgid "SSLOptionsProto" +msgstr "" + +#: ../../reference/launch_config.md:238 +msgid "SSL options." +msgstr "" + +#: ../../reference/launch_config.md +msgid "certificate_path" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Certificate file path" +msgstr "" + +#: ../../reference/launch_config.md +msgid "private_key_path" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Private key file path" +msgstr "" + +#: ../../reference/launch_config.md +msgid "verify_depth" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Set the maximum depth of the certificate chain for verification If 0, " +"turn off the verification" +msgstr "" + +#: ../../reference/launch_config.md +msgid "ca_file_path" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Set the trusted CA file to verify the peer's certificate If empty, use " +"the system default CA files" +msgstr "" + +#: ../../reference/launch_config.md:255 +msgid "Scalar Value Types" +msgstr "" + +#: ../../reference/launch_config.md +msgid ".proto Type" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Notes" +msgstr "" + +#: ../../reference/launch_config.md +msgid "C++ Type" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Java Type" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Python Type" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

double" +msgstr "" + +#: ../../reference/launch_config.md +msgid "double" +msgstr "" + +#: ../../reference/launch_config.md +msgid "float" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

float" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

int32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint32 instead." +msgstr "" + +#: ../../reference/launch_config.md +msgid "int32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "int" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

int64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint64 instead." +msgstr "" + +#: ../../reference/launch_config.md +msgid "int64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "long" +msgstr "" + +#: ../../reference/launch_config.md +msgid "int/long" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

uint32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Uses variable-length encoding." +msgstr "" + +#: ../../reference/launch_config.md +msgid "uint32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

uint64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "uint64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

sint32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int32s." +msgstr "" + +#: ../../reference/launch_config.md +msgid "

sint64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int64s." +msgstr "" + +#: ../../reference/launch_config.md +msgid "

fixed32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Always four bytes. More efficient than uint32 if values are often greater" +" than 2^28." +msgstr "" + +#: ../../reference/launch_config.md +msgid "

fixed64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "" +"Always eight bytes. More efficient than uint64 if values are often " +"greater than 2^56." +msgstr "" + +#: ../../reference/launch_config.md +msgid "

sfixed32" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Always four bytes." +msgstr "" + +#: ../../reference/launch_config.md +msgid "

sfixed64" +msgstr "" + +#: ../../reference/launch_config.md +msgid "Always eight bytes." +msgstr "" + +#: ../../reference/launch_config.md +msgid "

bool" +msgstr "" + +#: ../../reference/launch_config.md +msgid "bool" +msgstr "" + +#: ../../reference/launch_config.md +msgid "boolean" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

string" +msgstr "" + +#: ../../reference/launch_config.md +msgid "A string must always contain UTF-8 encoded or 7-bit ASCII text." +msgstr "" + +#: ../../reference/launch_config.md +msgid "string" +msgstr "" + +#: ../../reference/launch_config.md +msgid "String" +msgstr "" + +#: ../../reference/launch_config.md +msgid "str/unicode" +msgstr "" + +#: ../../reference/launch_config.md +msgid "

bytes" +msgstr "" + +#: ../../reference/launch_config.md +msgid "May contain any arbitrary sequence of bytes." +msgstr "" + +#: ../../reference/launch_config.md +msgid "ByteString" +msgstr "" + +#: ../../reference/launch_config.md +msgid "str" +msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/reference/pir_config.po b/docs/locale/zh_CN/LC_MESSAGES/reference/pir_config.po new file mode 100644 index 00000000..4af38acb --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/reference/pir_config.po @@ -0,0 +1,503 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-30 15:39+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../reference/pir_config.md:1 +msgid "PIR Configuration" +msgstr "" + +#: ../../reference/pir_config.md:3 +msgid "Table of Contents" +msgstr "" + +#: ../../reference/pir_config.md:7 ../../reference/pir_config.md:21 +msgid "Messages" +msgstr "" + +#: ../../reference/pir_config.md:8 +msgid "[ApsiReceiverConfig](#apsireceiverconfig)" +msgstr "" + +#: ../../reference/pir_config.md:9 +msgid "[ApsiSenderConfig](#apsisenderconfig)" +msgstr "" + +#: ../../reference/pir_config.md:10 +msgid "[PirResultReport](#pirresultreport)" +msgstr "" + +#: ../../reference/pir_config.md:15 +msgid "[Scalar Value Types](#scalar-value-types)" +msgstr "" + +#: ../../reference/pir_config.md:24 +msgid "ApsiReceiverConfig" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Field" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Type" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Description" +msgstr "" + +#: ../../reference/pir_config.md +msgid "threads" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[ uint32](#uint32)" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Number of threads to use" +msgstr "" + +#: ../../reference/pir_config.md +msgid "log_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[ string](#string)" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Log file path. For APSI only." +msgstr "" + +#: ../../reference/pir_config.md +msgid "silent" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[ bool](#bool)" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Do not write output to console. For APSI only." +msgstr "" + +#: ../../reference/pir_config.md +msgid "log_level" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"One of 'all', 'debug', 'info' (default), 'warning', 'error', 'off'. For " +"APSI only." +msgstr "" + +#: ../../reference/pir_config.md +msgid "query_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Path to a text file containing query data (one per line). Header is not " +"needed." +msgstr "" + +#: ../../reference/pir_config.md +msgid "output_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Path to a file where intersection result will be written." +msgstr "" + +#: ../../reference/pir_config.md +msgid "params_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Path to a JSON file describing the parameters to be used by the sender. " +"If not set, receiver will ask sender, which results in additional " +"communication." +msgstr "" + +#: ../../reference/pir_config.md +msgid "experimental_enable_bucketize" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Must be same as sender config." +msgstr "" + +#: ../../reference/pir_config.md +msgid "experimental_bucket_cnt" +msgstr "" + +#: ../../reference/pir_config.md +msgid "query_batch_size" +msgstr "" + +#: ../../reference/pir_config.md +msgid "The number of query in a batch. default 1." +msgstr "" + +#: ../../reference/pir_config.md:44 +msgid "ApsiSenderConfig" +msgstr "" + +#: ../../reference/pir_config.md:45 +msgid "" +"NOTE(junfeng): We provide a config identical to original APSI CLI. Please" +" check https://github.com/microsoft/APSI?tab=readme-ov-file#command-line-" +"interface-cli for details." +msgstr "" + +#: ../../reference/pir_config.md +msgid "db_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Path to a CSV file describing the sender's dataset (an item-label pair on" +" each row) or a file containing a serialized SenderDB; the CLI will first" +" attempt to load the data as a serialized SenderDB, and – upon failure – " +"will proceed to attempt to read it as a CSV file For CSV File: 1. the " +"first col is processed as item while the second col as label. OTHER COLS " +"ARE IGNORED. 2. NO HEADERS ARE ALLOWED." +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Path to a JSON file describing the parameters to be used by the sender. " +"Not required if db_file points to a serialized SenderDB." +msgstr "" + +#: ../../reference/pir_config.md +msgid "sdb_out_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Save the SenderDB in the given file. Required if gen_db_only is set true." +" Use experimental_bucket_folder instead if you turn " +"experimental_enable_bucketize on." +msgstr "" + +#: ../../reference/pir_config.md +msgid "nonce_byte_count" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Number of bytes used for the nonce in labeled mode (default is 16)" +msgstr "" + +#: ../../reference/pir_config.md +msgid "compress" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Whether to compress the SenderDB in memory; this will make the memory " +"footprint smaller at the cost of increased computation." +msgstr "" + +#: ../../reference/pir_config.md +msgid "save_db_only" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Whether to save sender db only." +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"[experimental] Whether to split data in buckets and Each bucket would be " +"a seperate SenderDB. If set, experimental_bucket_folder must be a valid " +"folder." +msgstr "" + +#: ../../reference/pir_config.md +msgid "[experimental] The number of bucket to fit data." +msgstr "" + +#: ../../reference/pir_config.md +msgid "experimental_bucket_folder" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[experimental] Folder to save bucketized small csv files and db files." +msgstr "" + +#: ../../reference/pir_config.md +msgid "experimental_db_generating_process_num" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[ int32](#int32)" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[experimental] The number of processes to use for generating db." +msgstr "" + +#: ../../reference/pir_config.md +msgid "source_file" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Source file used to genenerate sender db. Currently only support csv file." +msgstr "" + +#: ../../reference/pir_config.md +msgid "experimental_bucket_group_cnt" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"[experimental] The number of group of bucket, each group has a db_file, " +"default 1024." +msgstr "" + +#: ../../reference/pir_config.md:73 +msgid "PirResultReport" +msgstr "" + +#: ../../reference/pir_config.md:74 +msgid "The report of pir task." +msgstr "" + +#: ../../reference/pir_config.md +msgid "match_cnt" +msgstr "" + +#: ../../reference/pir_config.md +msgid "[ int64](#int64)" +msgstr "" + +#: ../../reference/pir_config.md +msgid "none" +msgstr "" + +#: ../../reference/pir_config.md:84 +msgid "Enums" +msgstr "" + +#: ../../reference/pir_config.md:88 +msgid "Scalar Value Types" +msgstr "" + +#: ../../reference/pir_config.md +msgid ".proto Type" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Notes" +msgstr "" + +#: ../../reference/pir_config.md +msgid "C++ Type" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Java Type" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Python Type" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

double" +msgstr "" + +#: ../../reference/pir_config.md +msgid "double" +msgstr "" + +#: ../../reference/pir_config.md +msgid "float" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

float" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

int32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint32 instead." +msgstr "" + +#: ../../reference/pir_config.md +msgid "int32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "int" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

int64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint64 instead." +msgstr "" + +#: ../../reference/pir_config.md +msgid "int64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "long" +msgstr "" + +#: ../../reference/pir_config.md +msgid "int/long" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

uint32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Uses variable-length encoding." +msgstr "" + +#: ../../reference/pir_config.md +msgid "uint32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

uint64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "uint64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

sint32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int32s." +msgstr "" + +#: ../../reference/pir_config.md +msgid "

sint64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int64s." +msgstr "" + +#: ../../reference/pir_config.md +msgid "

fixed32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Always four bytes. More efficient than uint32 if values are often greater" +" than 2^28." +msgstr "" + +#: ../../reference/pir_config.md +msgid "

fixed64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "" +"Always eight bytes. More efficient than uint64 if values are often " +"greater than 2^56." +msgstr "" + +#: ../../reference/pir_config.md +msgid "

sfixed32" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Always four bytes." +msgstr "" + +#: ../../reference/pir_config.md +msgid "

sfixed64" +msgstr "" + +#: ../../reference/pir_config.md +msgid "Always eight bytes." +msgstr "" + +#: ../../reference/pir_config.md +msgid "

bool" +msgstr "" + +#: ../../reference/pir_config.md +msgid "bool" +msgstr "" + +#: ../../reference/pir_config.md +msgid "boolean" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

string" +msgstr "" + +#: ../../reference/pir_config.md +msgid "A string must always contain UTF-8 encoded or 7-bit ASCII text." +msgstr "" + +#: ../../reference/pir_config.md +msgid "string" +msgstr "" + +#: ../../reference/pir_config.md +msgid "String" +msgstr "" + +#: ../../reference/pir_config.md +msgid "str/unicode" +msgstr "" + +#: ../../reference/pir_config.md +msgid "

bytes" +msgstr "" + +#: ../../reference/pir_config.md +msgid "May contain any arbitrary sequence of bytes." +msgstr "" + +#: ../../reference/pir_config.md +msgid "ByteString" +msgstr "" + +#: ../../reference/pir_config.md +msgid "str" +msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/reference/psi_config.po b/docs/locale/zh_CN/LC_MESSAGES/reference/psi_config.po new file mode 100644 index 00000000..7465dd79 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/reference/psi_config.po @@ -0,0 +1,1808 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-30 15:59+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../reference/psi_config.md:1 +msgid "PSI v1 Configuration" +msgstr "" + +#: ../../reference/psi_config.md:3 +msgid "Table of Contents" +msgstr "" + +#: ../../reference/psi_config.md:7 ../../reference/psi_config.md:29 +msgid "Messages" +msgstr "" + +#: ../../reference/psi_config.md:8 +msgid "[BucketPsiConfig](#bucketpsiconfig)" +msgstr "" + +#: ../../reference/psi_config.md:9 +msgid "[DpPsiParams](#dppsiparams)" +msgstr "" + +#: ../../reference/psi_config.md:10 +msgid "[InputParams](#inputparams)" +msgstr "" + +#: ../../reference/psi_config.md:11 +msgid "[MemoryPsiConfig](#memorypsiconfig)" +msgstr "" + +#: ../../reference/psi_config.md:12 +msgid "[OutputParams](#outputparams)" +msgstr "" + +#: ../../reference/psi_config.md:13 +msgid "[PsiResultReport](#psiresultreport)" +msgstr "" + +#: ../../reference/psi_config.md:17 ../../reference/psi_config.md:160 +msgid "Enums" +msgstr "" + +#: ../../reference/psi_config.md:18 +msgid "[CurveType](#curvetype)" +msgstr "" + +#: ../../reference/psi_config.md:19 +msgid "[PsiType](#psitype)" +msgstr "" + +#: ../../reference/psi_config.md:23 +msgid "[Scalar Value Types](#scalar-value-types)" +msgstr "" + +#: ../../reference/psi_config.md:32 +msgid "BucketPsiConfig" +msgstr "" + +#: ../../reference/psi_config.md:39 +msgid "The Bucket-psi configuration." +msgstr "" + +#: ../../reference/psi_config.md +msgid "Field" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Description" +msgstr "" + +#: ../../reference/psi_config.md +msgid "psi_type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ PsiType](#psitype)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "The psi type." +msgstr "" + +#: ../../reference/psi_config.md +msgid "receiver_rank" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ uint32](#uint32)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Specified the receiver rank. Receiver can get psi result." +msgstr "" + +#: ../../reference/psi_config.md +msgid "broadcast_result" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ bool](#bool)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Whether to broadcast psi result to all parties." +msgstr "" + +#: ../../reference/psi_config.md +msgid "input_params" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ InputParams](#inputparams)" +msgstr "" + +#: ../../reference/psi_config.md ../../reference/psi_config.md:87 +msgid "The input parameters of psi." +msgstr "" + +#: ../../reference/psi_config.md +msgid "output_params" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ OutputParams](#outputparams)" +msgstr "" + +#: ../../reference/psi_config.md ../../reference/psi_config.md:135 +msgid "The output parameters of psi." +msgstr "" + +#: ../../reference/psi_config.md +msgid "curve_type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ CurveType](#curvetype)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Optional, specified elliptic curve cryptography used in psi when needed." +msgstr "" + +#: ../../reference/psi_config.md +msgid "bucket_size" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Optional, specified the hash bucket size used in psi." +msgstr "" + +#: ../../reference/psi_config.md +msgid "preprocess_path" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ string](#string)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Optional,the path of offline preprocess file." +msgstr "" + +#: ../../reference/psi_config.md +msgid "ecdh_secret_key_path" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Optional,secret key path of ecdh_oprf, 256bit/32bytes binary file." +msgstr "" + +#: ../../reference/psi_config.md +msgid "dppsi_params" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ DpPsiParams](#dppsiparams)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Optional,params for dp-psi" +msgstr "" + +#: ../../reference/psi_config.md:70 +msgid "DpPsiParams" +msgstr "" + +#: ../../reference/psi_config.md:71 +msgid "The input parameters of dp-psi." +msgstr "" + +#: ../../reference/psi_config.md +msgid "bob_sub_sampling" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ double](#double)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "bob sub-sampling bernoulli_distribution probability." +msgstr "" + +#: ../../reference/psi_config.md +msgid "epsilon" +msgstr "" + +#: ../../reference/psi_config.md +msgid "dp epsilon" +msgstr "" + +#: ../../reference/psi_config.md:82 +msgid "InputParams" +msgstr "" + +#: ../../reference/psi_config.md +msgid "path" +msgstr "" + +#: ../../reference/psi_config.md +msgid "The path of input csv file." +msgstr "" + +#: ../../reference/psi_config.md +msgid "select_fields" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[repeated string](#string)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "The select fields of input data." +msgstr "" + +#: ../../reference/psi_config.md +msgid "precheck" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Whether to check select fields duplicate." +msgstr "" + +#: ../../reference/psi_config.md:99 +msgid "MemoryPsiConfig" +msgstr "" + +#: ../../reference/psi_config.md:105 +msgid "The In-memory psi configuration." +msgstr "" + +#: ../../reference/psi_config.md +msgid "Optional,Params for dp-psi" +msgstr "" + +#: ../../reference/psi_config.md:130 +msgid "OutputParams" +msgstr "" + +#: ../../reference/psi_config.md +msgid "The path of output csv file." +msgstr "" + +#: ../../reference/psi_config.md +msgid "need_sort" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Whether to sort output file by select fields." +msgstr "" + +#: ../../reference/psi_config.md:146 +msgid "PsiResultReport" +msgstr "" + +#: ../../reference/psi_config.md:147 +msgid "The report of psi result." +msgstr "" + +#: ../../reference/psi_config.md +msgid "original_count" +msgstr "" + +#: ../../reference/psi_config.md +msgid "[ int64](#int64)" +msgstr "" + +#: ../../reference/psi_config.md +msgid "The data count of input." +msgstr "" + +#: ../../reference/psi_config.md +msgid "intersection_count" +msgstr "" + +#: ../../reference/psi_config.md +msgid "The count of intersection. Get `-1` when self party can not get result." +msgstr "" + +#: ../../reference/psi_config.md +msgid "original_key_count" +msgstr "" + +#: ../../reference/psi_config.md +msgid "none" +msgstr "" + +#: ../../reference/psi_config.md +msgid "intersection_key_count" +msgstr "" + +#: ../../reference/psi_config.md:163 +msgid "CurveType" +msgstr "" + +#: ../../reference/psi_config.md:164 +msgid "The specified elliptic curve cryptography used in psi." +msgstr "" + +#: ../../reference/psi_config.md +msgid "Name" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Number" +msgstr "" + +#: ../../reference/psi_config.md +msgid "CURVE_INVALID_TYPE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "0" +msgstr "" + +#: ../../reference/psi_config.md +msgid "CURVE_25519" +msgstr "" + +#: ../../reference/psi_config.md +msgid "1" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Daniel J. Bernstein. Curve25519: new diffie-hellman speed records" +msgstr "" + +#: ../../reference/psi_config.md +msgid "CURVE_FOURQ" +msgstr "" + +#: ../../reference/psi_config.md +msgid "2" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"FourQ: four-dimensional decompositions on a Q-curve over the Mersenne " +"prime" +msgstr "" + +#: ../../reference/psi_config.md +msgid "CURVE_SM2" +msgstr "" + +#: ../../reference/psi_config.md +msgid "3" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"SM2 is an elliptic curve based cryptosystem (ECC) published as a Chinese " +"National Standard as GBT.32918.1-2016 and published in ISO/IEC " +"14888-3:2018" +msgstr "" + +#: ../../reference/psi_config.md +msgid "CURVE_SECP256K1" +msgstr "" + +#: ../../reference/psi_config.md +msgid "4" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"parameters of the elliptic curve defined in Standards for Efficient " +"Cryptography (SEC) http://www.secg.org/sec2-v2.pdf" +msgstr "" + +#: ../../reference/psi_config.md +msgid "CURVE_25519_ELLIGATOR2" +msgstr "" + +#: ../../reference/psi_config.md +msgid "5" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Curve25519 with rfc9380 elligator2 hash_to_curve" +msgstr "" + +#: ../../reference/psi_config.md:178 +msgid "PsiType" +msgstr "" + +#: ../../reference/psi_config.md:185 +msgid "The algorithm type of psi." +msgstr "" + +#: ../../reference/psi_config.md +msgid "INVALID_PSI_TYPE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_PSI_2PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "``` NOTICED: No longer supported ``` DDH based PSI" +msgstr "" + +#: ../../reference/psi_config.md +msgid "KKRT_PSI_2PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` Efficient Batched Oblivious PRF with" +" Applications to Private Set Intersection " +"https://eprint.iacr.org/2016/799.pdf" +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_PSI_3PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Multi-party PSI based on ECDH (Say A, B, C (receiver)) notice: two-party " +"intersection cardinarlity leak (" +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_PSI_NPC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Iterative running 2-party ecdh psi to get n-party PSI. Notice: two-party " +"intersection leak" +msgstr "" + +#: ../../reference/psi_config.md +msgid "KKRT_PSI_NPC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "6" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Iterative running 2-party kkrt psi to get n-party PSI. Notice: two-party " +"intersection leak" +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_OPRF_UB_PSI_2PC_GEN_CACHE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "7" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI " +"Generate CACHE." +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_OPRF_UB_PSI_2PC_TRANSFER_CACHE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "8" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI " +"transfer CACHE." +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_OPRF_UB_PSI_2PC_OFFLINE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "9" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI " +"offline phase." +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_OPRF_UB_PSI_2PC_ONLINE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "10" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI " +"online phase." +msgstr "" + +#: ../../reference/psi_config.md +msgid "ECDH_OPRF_UB_PSI_2PC_SHUFFLE_ONLINE" +msgstr "" + +#: ../../reference/psi_config.md +msgid "11" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI " +"with shuffling online phase. large set party get intersection result" +msgstr "" + +#: ../../reference/psi_config.md +msgid "DP_PSI_2PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "12" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Differentially-Private PSI https://arxiv.org/pdf/2208.13249.pdf bases on " +"ECDH-PSI, and provides: Differentially private PSI results." +msgstr "" + +#: ../../reference/psi_config.md +msgid "RR22_FAST_PSI_2PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "13" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"``` NOTICED: No longer supported ``` Blazing Fast PSI " +"https://eprint.iacr.org/2022/320.pdf two mode: fast mode or low " +"communication mode" +msgstr "" + +#: ../../reference/psi_config.md +msgid "RR22_LOWCOMM_PSI_2PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "14" +msgstr "" + +#: ../../reference/psi_config.md +msgid "RR22_MALICIOUS_PSI_2PC" +msgstr "" + +#: ../../reference/psi_config.md +msgid "15" +msgstr "" + +#: ../../reference/psi_config.md:209 +msgid "Scalar Value Types" +msgstr "" + +#: ../../reference/psi_config.md +msgid ".proto Type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Notes" +msgstr "" + +#: ../../reference/psi_config.md +msgid "C++ Type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Java Type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Python Type" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

double" +msgstr "" + +#: ../../reference/psi_config.md +msgid "double" +msgstr "" + +#: ../../reference/psi_config.md +msgid "float" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

float" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

int32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint32 instead." +msgstr "" + +#: ../../reference/psi_config.md +msgid "int32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "int" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

int64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint64 instead." +msgstr "" + +#: ../../reference/psi_config.md +msgid "int64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "long" +msgstr "" + +#: ../../reference/psi_config.md +msgid "int/long" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

uint32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Uses variable-length encoding." +msgstr "" + +#: ../../reference/psi_config.md +msgid "uint32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

uint64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "uint64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

sint32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int32s." +msgstr "" + +#: ../../reference/psi_config.md +msgid "

sint64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int64s." +msgstr "" + +#: ../../reference/psi_config.md +msgid "

fixed32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Always four bytes. More efficient than uint32 if values are often greater" +" than 2^28." +msgstr "" + +#: ../../reference/psi_config.md +msgid "

fixed64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "" +"Always eight bytes. More efficient than uint64 if values are often " +"greater than 2^56." +msgstr "" + +#: ../../reference/psi_config.md +msgid "

sfixed32" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Always four bytes." +msgstr "" + +#: ../../reference/psi_config.md +msgid "

sfixed64" +msgstr "" + +#: ../../reference/psi_config.md +msgid "Always eight bytes." +msgstr "" + +#: ../../reference/psi_config.md +msgid "

bool" +msgstr "" + +#: ../../reference/psi_config.md +msgid "bool" +msgstr "" + +#: ../../reference/psi_config.md +msgid "boolean" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

string" +msgstr "" + +#: ../../reference/psi_config.md +msgid "A string must always contain UTF-8 encoded or 7-bit ASCII text." +msgstr "" + +#: ../../reference/psi_config.md +msgid "string" +msgstr "" + +#: ../../reference/psi_config.md +msgid "String" +msgstr "" + +#: ../../reference/psi_config.md +msgid "str/unicode" +msgstr "" + +#: ../../reference/psi_config.md +msgid "

bytes" +msgstr "" + +#: ../../reference/psi_config.md +msgid "May contain any arbitrary sequence of bytes." +msgstr "" + +#: ../../reference/psi_config.md +msgid "ByteString" +msgstr "" + +#: ../../reference/psi_config.md +msgid "str" +msgstr "" + +#~ msgid "DDH based PSI" +#~ msgstr "" + +#~ msgid "ecdh-oprf 2-party Unbalanced-PSI Generate CACHE." +#~ msgstr "" + +#~ msgid "ecdh-oprf 2-party Unbalanced-PSI transfer CACHE." +#~ msgstr "" + +#~ msgid "ecdh-oprf 2-party Unbalanced-PSI offline phase." +#~ msgstr "" + +#~ msgid "ecdh-oprf 2-party Unbalanced-PSI online phase." +#~ msgstr "" + +#~ msgid "" +#~ "ecdh-oprf 2-party Unbalanced-PSI with" +#~ " shuffling online phase. large set " +#~ "party get intersection result" +#~ msgstr "" + +#~ msgid "" +#~ "Blazing Fast PSI " +#~ "https://eprint.iacr.org/2022/320.pdf two mode: fast" +#~ " mode or low communication mode" +#~ msgstr "" + +#~ msgid "[ApsiReceiverConfig](#apsireceiverconfig)" +#~ msgstr "" + +#~ msgid "[ApsiSenderConfig](#apsisenderconfig)" +#~ msgstr "" + +#~ msgid "[PirResultReport](#pirresultreport)" +#~ msgstr "" + +#~ msgid "[DebugOptions](#debugoptions)" +#~ msgstr "" + +#~ msgid "[EcdhConfig](#ecdhconfig)" +#~ msgstr "" + +#~ msgid "[InputAttr](#inputattr)" +#~ msgstr "" + +#~ msgid "[InternalRecoveryRecord](#internalrecoveryrecord)" +#~ msgstr "" + +#~ msgid "[IoConfig](#ioconfig)" +#~ msgstr "" + +#~ msgid "[KkrtConfig](#kkrtconfig)" +#~ msgstr "" + +#~ msgid "[OutputAttr](#outputattr)" +#~ msgstr "" + +#~ msgid "[ProtocolConfig](#protocolconfig)" +#~ msgstr "" + +#~ msgid "[PsiConfig](#psiconfig)" +#~ msgstr "" + +#~ msgid "[RecoveryCheckpoint](#recoverycheckpoint)" +#~ msgstr "" + +#~ msgid "[RecoveryConfig](#recoveryconfig)" +#~ msgstr "" + +#~ msgid "[Rr22Config](#rr22config)" +#~ msgstr "" + +#~ msgid "[UbPsiConfig](#ubpsiconfig)" +#~ msgstr "" + +#~ msgid "[IoType](#iotype)" +#~ msgstr "" + +#~ msgid "[Protocol](#protocol)" +#~ msgstr "" + +#~ msgid "[PsiConfig.AdvancedJoinType](#psiconfigadvancedjointype)" +#~ msgstr "" + +#~ msgid "[RecoveryCheckpoint.Stage](#recoverycheckpointstage)" +#~ msgstr "" + +#~ msgid "[Role](#role)" +#~ msgstr "" + +#~ msgid "[UbPsiConfig.Mode](#ubpsiconfigmode)" +#~ msgstr "" + +#~ msgid "ApsiReceiverConfig" +#~ msgstr "" + +#~ msgid "threads" +#~ msgstr "" + +#~ msgid "Number of threads to use" +#~ msgstr "" + +#~ msgid "log_file" +#~ msgstr "" + +#~ msgid "Log file path. For APSI only." +#~ msgstr "" + +#~ msgid "silent" +#~ msgstr "" + +#~ msgid "Do not write output to console. For APSI only." +#~ msgstr "" + +#~ msgid "log_level" +#~ msgstr "" + +#~ msgid "" +#~ "One of 'all', 'debug', 'info' (default)," +#~ " 'warning', 'error', 'off'. For APSI " +#~ "only." +#~ msgstr "" + +#~ msgid "query_file" +#~ msgstr "" + +#~ msgid "" +#~ "Path to a text file containing " +#~ "query data (one per line). Header " +#~ "is not needed." +#~ msgstr "" + +#~ msgid "output_file" +#~ msgstr "" + +#~ msgid "Path to a file where intersection result will be written." +#~ msgstr "" + +#~ msgid "params_file" +#~ msgstr "" + +#~ msgid "" +#~ "Path to a JSON file describing the" +#~ " parameters to be used by the " +#~ "sender. If not set, receiver will " +#~ "ask sender, which results in additional" +#~ " communication." +#~ msgstr "" + +#~ msgid "experimental_enable_bucketize" +#~ msgstr "" + +#~ msgid "Must be same as sender config." +#~ msgstr "" + +#~ msgid "experimental_bucket_cnt" +#~ msgstr "" + +#~ msgid "query_batch_size" +#~ msgstr "" + +#~ msgid "The number of query in a batch. default 1." +#~ msgstr "" + +#~ msgid "ApsiSenderConfig" +#~ msgstr "" + +#~ msgid "" +#~ "NOTE(junfeng): We provide a config " +#~ "identical to original APSI CLI. Please" +#~ " check https://github.com/microsoft/APSI?tab=readme-" +#~ "ov-file#command-line-interface-cli for " +#~ "details." +#~ msgstr "" + +#~ msgid "db_file" +#~ msgstr "" + +#~ msgid "" +#~ "Path to a CSV file describing the" +#~ " sender's dataset (an item-label pair" +#~ " on each row) or a file " +#~ "containing a serialized SenderDB; the " +#~ "CLI will first attempt to load the" +#~ " data as a serialized SenderDB, and" +#~ " – upon failure – will proceed " +#~ "to attempt to read it as a " +#~ "CSV file For CSV File: 1. the " +#~ "first col is processed as item " +#~ "while the second col as label. " +#~ "OTHER COLS ARE IGNORED. 2. NO " +#~ "HEADERS ARE ALLOWED." +#~ msgstr "" + +#~ msgid "" +#~ "Path to a JSON file describing the" +#~ " parameters to be used by the " +#~ "sender. Not required if db_file points" +#~ " to a serialized SenderDB." +#~ msgstr "" + +#~ msgid "sdb_out_file" +#~ msgstr "" + +#~ msgid "" +#~ "Save the SenderDB in the given " +#~ "file. Required if gen_db_only is set " +#~ "true. Use experimental_bucket_folder instead " +#~ "if you turn experimental_enable_bucketize on." +#~ msgstr "" + +#~ msgid "nonce_byte_count" +#~ msgstr "" + +#~ msgid "Number of bytes used for the nonce in labeled mode (default is 16)" +#~ msgstr "" + +#~ msgid "compress" +#~ msgstr "" + +#~ msgid "" +#~ "Whether to compress the SenderDB in " +#~ "memory; this will make the memory " +#~ "footprint smaller at the cost of " +#~ "increased computation." +#~ msgstr "" + +#~ msgid "save_db_only" +#~ msgstr "" + +#~ msgid "Whether to save sender db only." +#~ msgstr "" + +#~ msgid "" +#~ "[experimental] Whether to split data in" +#~ " buckets and Each bucket would be " +#~ "a seperate SenderDB. If set, " +#~ "experimental_bucket_folder must be a valid " +#~ "folder." +#~ msgstr "" + +#~ msgid "[experimental] The number of bucket to fit data." +#~ msgstr "" + +#~ msgid "experimental_bucket_folder" +#~ msgstr "" + +#~ msgid "[experimental] Folder to save bucketized small csv files and db files." +#~ msgstr "" + +#~ msgid "experimental_db_generating_process_num" +#~ msgstr "" + +#~ msgid "[ int32](#int32)" +#~ msgstr "" + +#~ msgid "[experimental] The number of processes to use for generating db." +#~ msgstr "" + +#~ msgid "source_file" +#~ msgstr "" + +#~ msgid "" +#~ "Source file used to genenerate sender" +#~ " db. Currently only support csv file." +#~ msgstr "" + +#~ msgid "experimental_bucket_group_cnt" +#~ msgstr "" + +#~ msgid "" +#~ "[experimental] The number of group of" +#~ " bucket, each group has a db_file," +#~ " default 1024." +#~ msgstr "" + +#~ msgid "PirResultReport" +#~ msgstr "" + +#~ msgid "The report of pir task." +#~ msgstr "" + +#~ msgid "match_cnt" +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice** This enum is " +#~ "scheduled for removal in a future " +#~ "release. Use psi.v2.ProtocolConfig instead." +#~ msgstr "" + +#~ msgid "DebugOptions" +#~ msgstr "" + +#~ msgid "Logging level for default logger. Default to info. Supports:" +#~ msgstr "" + +#~ msgid "trace: SPDLOG_LEVEL_TRACE" +#~ msgstr "" + +#~ msgid "debug: SPDLOG_LEVEL_DEBUG" +#~ msgstr "" + +#~ msgid "info: SPDLOG_LEVEL_INFO" +#~ msgstr "" + +#~ msgid "warn: SPDLOG_LEVEL_WARN" +#~ msgstr "" + +#~ msgid "err: SPDLOG_LEVEL_ERROR" +#~ msgstr "" + +#~ msgid "critical: SPDLOG_LEVEL_CRITICAL" +#~ msgstr "" + +#~ msgid "off: SPDLOG_LEVEL_OFF" +#~ msgstr "" + +#~ msgid "logging_level" +#~ msgstr "" + +#~ msgid "trace_path" +#~ msgstr "" + +#~ msgid "The path of trace. Deafult to /tmp/psi.trace" +#~ msgstr "" + +#~ msgid "EcdhConfig" +#~ msgstr "" + +#~ msgid "Configs for ECDH protocol." +#~ msgstr "" + +#~ msgid "curve" +#~ msgstr "" + +#~ msgid "[ psi.CurveType](#psicurvetype)" +#~ msgstr "" + +#~ msgid "batch_size" +#~ msgstr "" + +#~ msgid "[ uint64](#uint64)" +#~ msgstr "" + +#~ msgid "If not set, use default value: 4096." +#~ msgstr "" + +#~ msgid "InputAttr" +#~ msgstr "" + +#~ msgid "keys_unique" +#~ msgstr "" + +#~ msgid "Keys in input file are unique. If not set, use default value: false." +#~ msgstr "" + +#~ msgid "InternalRecoveryRecord" +#~ msgstr "" + +#~ msgid "stage" +#~ msgstr "" + +#~ msgid "[ RecoveryCheckpoint.Stage](#recoverycheckpointstage)" +#~ msgstr "" + +#~ msgid "ecdh_dual_masked_item_peer_count" +#~ msgstr "" + +#~ msgid "parsed_bucket_count" +#~ msgstr "" + +#~ msgid "IoConfig" +#~ msgstr "" + +#~ msgid "IO configuration." +#~ msgstr "" + +#~ msgid "type" +#~ msgstr "" + +#~ msgid "[ IoType](#iotype)" +#~ msgstr "" + +#~ msgid "Required for FILE." +#~ msgstr "" + +#~ msgid "KkrtConfig" +#~ msgstr "" + +#~ msgid "Configs for KKRT protocol" +#~ msgstr "" + +#~ msgid "" +#~ "Since the total input may not fit" +#~ " in memory, the input may be " +#~ "splitted into buckets. bucket_size indicate" +#~ " the number of items in each " +#~ "bucket. If the memory of host is" +#~ " limited, you should set a smaller" +#~ " bucket size. Otherwise, you should " +#~ "use a larger one. If not set, " +#~ "use default value: 1 << 20." +#~ msgstr "" + +#~ msgid "OutputAttr" +#~ msgstr "" + +#~ msgid "csv_null_rep" +#~ msgstr "" + +#~ msgid "" +#~ "Null representation in output csv file." +#~ " If not set, use default value: " +#~ "\"NULL\"." +#~ msgstr "" + +#~ msgid "ProtocolConfig" +#~ msgstr "" + +#~ msgid "Any items related to PSI protocols." +#~ msgstr "" + +#~ msgid "protocol" +#~ msgstr "" + +#~ msgid "[ Protocol](#protocol)" +#~ msgstr "" + +#~ msgid "role" +#~ msgstr "" + +#~ msgid "[ Role](#role)" +#~ msgstr "" + +#~ msgid "Reveal result to sender." +#~ msgstr "" + +#~ msgid "ecdh_config" +#~ msgstr "" + +#~ msgid "[ EcdhConfig](#ecdhconfig)" +#~ msgstr "" + +#~ msgid "For ECDH protocol." +#~ msgstr "" + +#~ msgid "kkrt_config" +#~ msgstr "" + +#~ msgid "[ KkrtConfig](#kkrtconfig)" +#~ msgstr "" + +#~ msgid "For KKRT protocol." +#~ msgstr "" + +#~ msgid "rr22_config" +#~ msgstr "" + +#~ msgid "[ Rr22Config](#rr22config)" +#~ msgstr "" + +#~ msgid "For RR22 protocol." +#~ msgstr "" + +#~ msgid "PsiConfig" +#~ msgstr "" + +#~ msgid "The top level of Configs. run(PsiConfig)->PsiReport" +#~ msgstr "" + +#~ msgid "Advanced Joins Type: Inner Join e.g. If input of receiver is" +#~ msgstr "" + +#~ msgid "and input of sender is" +#~ msgstr "" + +#~ msgid "After inner join. The output of receiver is:" +#~ msgstr "" + +#~ msgid "The output of sender is" +#~ msgstr "" + +#~ msgid "Type: Left Join After left join. The output of left side is:" +#~ msgstr "" + +#~ msgid "The output of right side is" +#~ msgstr "" + +#~ msgid "Type: Right Join After right join. The output of left side is:" +#~ msgstr "" + +#~ msgid "Type: Full Join After full join. The output of left side is:" +#~ msgstr "" + +#~ msgid "Type: Difference After difference. The output of left side is:" +#~ msgstr "" + +#~ msgid "protocol_config" +#~ msgstr "" + +#~ msgid "[ ProtocolConfig](#protocolconfig)" +#~ msgstr "" + +#~ msgid "Configs for protocols." +#~ msgstr "" + +#~ msgid "input_config" +#~ msgstr "" + +#~ msgid "[ IoConfig](#ioconfig)" +#~ msgstr "" + +#~ msgid "Configs for input." +#~ msgstr "" + +#~ msgid "output_config" +#~ msgstr "" + +#~ msgid "Configs for output." +#~ msgstr "" + +#~ msgid "keys" +#~ msgstr "" + +#~ msgid "keys for intersection." +#~ msgstr "" + +#~ msgid "debug_options" +#~ msgstr "" + +#~ msgid "[ DebugOptions](#debugoptions)" +#~ msgstr "" + +#~ msgid "Logging level." +#~ msgstr "" + +#~ msgid "skip_duplicates_check" +#~ msgstr "" + +#~ msgid "If true, the check of duplicated items will be skiped." +#~ msgstr "" + +#~ msgid "disable_alignment" +#~ msgstr "" + +#~ msgid "It true, output is not promised to be aligned." +#~ msgstr "" + +#~ msgid "recovery_config" +#~ msgstr "" + +#~ msgid "[ RecoveryConfig](#recoveryconfig)" +#~ msgstr "" + +#~ msgid "Configs for recovery." +#~ msgstr "" + +#~ msgid "advanced_join_type" +#~ msgstr "" + +#~ msgid "[ PsiConfig.AdvancedJoinType](#psiconfigadvancedjointype)" +#~ msgstr "" + +#~ msgid "left_side" +#~ msgstr "" + +#~ msgid "" +#~ "Required if advanced_join_type is " +#~ "ADVANCED_JOIN_TYPE_LEFT_JOIN or " +#~ "ADVANCED_JOIN_TYPE_RIGHT_JOIN." +#~ msgstr "" + +#~ msgid "check_hash_digest" +#~ msgstr "" + +#~ msgid "" +#~ "Check if hash digest of keys from" +#~ " parties are equal to determine " +#~ "whether to early-stop." +#~ msgstr "" + +#~ msgid "input_attr" +#~ msgstr "" + +#~ msgid "[ InputAttr](#inputattr)" +#~ msgstr "" + +#~ msgid "Input attributes." +#~ msgstr "" + +#~ msgid "output_attr" +#~ msgstr "" + +#~ msgid "[ OutputAttr](#outputattr)" +#~ msgstr "" + +#~ msgid "Output attributes." +#~ msgstr "" + +#~ msgid "RecoveryCheckpoint" +#~ msgstr "" + +#~ msgid "Save some critical information for future recovery." +#~ msgstr "" + +#~ msgid "Stage of PSI." +#~ msgstr "" + +#~ msgid "config" +#~ msgstr "" + +#~ msgid "[ PsiConfig](#psiconfig)" +#~ msgstr "" + +#~ msgid "A copy of origin PSI config." +#~ msgstr "" + +#~ msgid "input_hash_digest" +#~ msgstr "" + +#~ msgid "[ bytes](#bytes)" +#~ msgstr "" + +#~ msgid "Hash digest of input keys." +#~ msgstr "" + +#~ msgid "ecdh_dual_masked_item_self_count" +#~ msgstr "" + +#~ msgid "Saved dual masked item count from self originally. PROTOCOL_ECDH only." +#~ msgstr "" + +#~ msgid "Saved dual masked item count from peer originally. PROTOCOL_ECDH only." +#~ msgstr "" + +#~ msgid "Saved parsed bucket count. PROTOCOL_KKRT and PROTOCOL_RR22 only." +#~ msgstr "" + +#~ msgid "RecoveryConfig" +#~ msgstr "" + +#~ msgid "" +#~ "Configuration for recovery. If a PSI " +#~ "task failed unexpectedly, e.g. network " +#~ "failures and restart, the task can " +#~ "resume to the latest checkpoint to " +#~ "save time. However, enabling recovery " +#~ "would due in extra disk IOs and" +#~ " disk space occupation." +#~ msgstr "" + +#~ msgid "enabled" +#~ msgstr "" + +#~ msgid "folder" +#~ msgstr "" + +#~ msgid "Stores status and checkpoint files." +#~ msgstr "" + +#~ msgid "Rr22Config" +#~ msgstr "" + +#~ msgid "Configs for RR22 protocol." +#~ msgstr "" + +#~ msgid "low_comm_mode" +#~ msgstr "" + +#~ msgid "UbPsiConfig" +#~ msgstr "" + +#~ msgid "config for unbalanced psi." +#~ msgstr "" + +#~ msgid "mode" +#~ msgstr "" + +#~ msgid "[ UbPsiConfig.Mode](#ubpsiconfigmode)" +#~ msgstr "" + +#~ msgid "Required." +#~ msgstr "" + +#~ msgid "Required for all modes except MODE_OFFLINE_GEN_CACHE." +#~ msgstr "" + +#~ msgid "" +#~ "Config for origin input. Servers: " +#~ "Required for MODE_OFFLINE_GEN_CACHE, MODE_OFFLINE," +#~ " MODE_FULL. Clients: Required for " +#~ "MODE_ONLINE and MODE_FULL." +#~ msgstr "" + +#~ msgid "" +#~ "Join keys. Servers: Required for " +#~ "MODE_OFFLINE_GEN_CACHE, MODE_OFFLINE, MODE_FULL. " +#~ "Clients: Required for MODE_ONLINE and " +#~ "MODE_FULL." +#~ msgstr "" + +#~ msgid "server_secret_key_path" +#~ msgstr "" + +#~ msgid "" +#~ "Servers: Required for MODE_OFFLINE_GEN_CACHE, " +#~ "MODE_OFFLINE, MODE_ONLINE and MODE_FULL." +#~ msgstr "" + +#~ msgid "cache_path" +#~ msgstr "" + +#~ msgid "server_get_result" +#~ msgstr "" + +#~ msgid "client_get_result" +#~ msgstr "" + +#~ msgid "" +#~ "It true, output is not promised to" +#~ " be aligned. Valid if both " +#~ "server_get_result and client_get_result are " +#~ "true." +#~ msgstr "" + +#~ msgid "Required for MODE_ONLINE and MODE_FULL." +#~ msgstr "" + +#~ msgid "IoType" +#~ msgstr "" + +#~ msgid "TODO(junfeng): support more io types including oss, sql, etc." +#~ msgstr "" + +#~ msgid "IO_TYPE_UNSPECIFIED" +#~ msgstr "" + +#~ msgid "IO_TYPE_FILE_CSV" +#~ msgstr "" + +#~ msgid "Local csv file." +#~ msgstr "" + +#~ msgid "Protocol" +#~ msgstr "" + +#~ msgid "PSI protocols." +#~ msgstr "" + +#~ msgid "PROTOCOL_UNSPECIFIED" +#~ msgstr "" + +#~ msgid "PROTOCOL_ECDH" +#~ msgstr "" + +#~ msgid "" +#~ "[Mea86]C. Meadows, \"A More Efficient " +#~ "Cryptographic Matchmaking Protocol for Use " +#~ "in the Absence of a Continuously " +#~ "Available Third Party,\" 1986 IEEE " +#~ "Symposium on Security and Privacy, " +#~ "Oakland, CA, USA, 1986, pp. 134-134, " +#~ "doi: 10.1109/SP.1986.10022." +#~ msgstr "" + +#~ msgid "PROTOCOL_KKRT" +#~ msgstr "" + +#~ msgid "" +#~ "Efficient Batched Oblivious PRF with " +#~ "Applications to Private Set Intersection " +#~ "https://eprint.iacr.org/2016/799.pdf" +#~ msgstr "" + +#~ msgid "PROTOCOL_RR22" +#~ msgstr "" + +#~ msgid "Blazing Fast PSI https://eprint.iacr.org/2022/320.pdf" +#~ msgstr "" + +#~ msgid "PsiConfig.AdvancedJoinType" +#~ msgstr "" + +#~ msgid "Advanced Join allow duplicate keys." +#~ msgstr "" + +#~ msgid "If selected, duplicates_check is skipped." +#~ msgstr "" + +#~ msgid "If selected, both parties are allowed to contain duplicate keys." +#~ msgstr "" + +#~ msgid "" +#~ "If use left join, full join or " +#~ "difference, the size of difference set" +#~ " of left party is revealed to " +#~ "right party." +#~ msgstr "" + +#~ msgid "" +#~ "If use right join, full join or" +#~ " difference, the size of difference " +#~ "set of right party is revealed to" +#~ " left party." +#~ msgstr "" + +#~ msgid "ADVANCED_JOIN_TYPE_UNSPECIFIED" +#~ msgstr "" + +#~ msgid "ADVANCED_JOIN_TYPE_INNER_JOIN" +#~ msgstr "" + +#~ msgid "ADVANCED_JOIN_TYPE_LEFT_JOIN" +#~ msgstr "" + +#~ msgid "ADVANCED_JOIN_TYPE_RIGHT_JOIN" +#~ msgstr "" + +#~ msgid "ADVANCED_JOIN_TYPE_FULL_JOIN" +#~ msgstr "" + +#~ msgid "ADVANCED_JOIN_TYPE_DIFFERENCE" +#~ msgstr "" + +#~ msgid "RecoveryCheckpoint.Stage" +#~ msgstr "" + +#~ msgid "STAGE_UNSPECIFIED" +#~ msgstr "" + +#~ msgid "STAGE_INIT_END" +#~ msgstr "" + +#~ msgid "STAGE_PRE_PROCESS_END" +#~ msgstr "" + +#~ msgid "STAGE_ONLINE_START" +#~ msgstr "" + +#~ msgid "STAGE_ONLINE_END" +#~ msgstr "" + +#~ msgid "STAGE_POST_PROCESS_END" +#~ msgstr "" + +#~ msgid "Role" +#~ msgstr "" + +#~ msgid "Role of parties." +#~ msgstr "" + +#~ msgid "ROLE_UNSPECIFIED" +#~ msgstr "" + +#~ msgid "ROLE_RECEIVER" +#~ msgstr "" + +#~ msgid "" +#~ "receiver In 2P symmetric PSI, receivers" +#~ " would always receive the result in" +#~ " the origin protocol." +#~ msgstr "" + +#~ msgid "ROLE_SENDER" +#~ msgstr "" + +#~ msgid "" +#~ "sender In 2P symmetric PSI, senders " +#~ "are the other participants apart from" +#~ " receiver." +#~ msgstr "" + +#~ msgid "ROLE_SERVER" +#~ msgstr "" + +#~ msgid "server In 2P unbalanced PSI, servers own a much larger dataset." +#~ msgstr "" + +#~ msgid "ROLE_CLIENT" +#~ msgstr "" + +#~ msgid "server In 2P unbalanced PSI, clients own a much smaller dataset." +#~ msgstr "" + +#~ msgid "UbPsiConfig.Mode" +#~ msgstr "" + +#~ msgid "MODE_UNSPECIFIED" +#~ msgstr "" + +#~ msgid "MODE_OFFLINE_GEN_CACHE" +#~ msgstr "" + +#~ msgid "Servers generate cache only. First part of offline stage." +#~ msgstr "" + +#~ msgid "MODE_OFFLINE_TRANSFER_CACHE" +#~ msgstr "" + +#~ msgid "Servers send cache to clients only. Second part of offline stage." +#~ msgstr "" + +#~ msgid "MODE_OFFLINE" +#~ msgstr "" + +#~ msgid "Run offline stage." +#~ msgstr "" + +#~ msgid "MODE_ONLINE" +#~ msgstr "" + +#~ msgid "Run online stage." +#~ msgstr "" + +#~ msgid "MODE_FULL" +#~ msgstr "" + +#~ msgid "Run all stages." +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice* This enum is " +#~ "**scheduled for removal** in a future" +#~ " release. Use **psi.v2.ProtocolConfig** instead." +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice This enum is " +#~ "**scheduled for removal** in a future" +#~ " release. Use **psi.v2.ProtocolConfig** instead." +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice This enum " +#~ "is **scheduled for removal** in a " +#~ "future release. Use **psi.v2.ProtocolConfig** " +#~ "instead." +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice**. This message is " +#~ "scheduled for removal in a future " +#~ "release. Use psi.v2.PsiConfig instead." +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice** This message is " +#~ "scheduled for removal in a future " +#~ "release." +#~ msgstr "" + +#~ msgid "" +#~ "Deprecation notice**. This message is " +#~ "scheduled for removal in a future " +#~ "release." +#~ msgstr "" + +#~ msgid "NOTICED**: No longer supported DDH based PSI" +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported Efficient " +#~ "Batched Oblivious PRF with Applications " +#~ "to Private Set Intersection " +#~ "https://eprint.iacr.org/2016/799.pdf" +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported ecdh-oprf" +#~ " 2-party Unbalanced-PSI Generate CACHE." +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported ecdh-oprf" +#~ " 2-party Unbalanced-PSI transfer CACHE." +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported ecdh-oprf" +#~ " 2-party Unbalanced-PSI offline phase." +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported ecdh-oprf" +#~ " 2-party Unbalanced-PSI online phase." +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported ecdh-oprf" +#~ " 2-party Unbalanced-PSI with shuffling " +#~ "online phase. large set party get " +#~ "intersection result" +#~ msgstr "" + +#~ msgid "" +#~ "NOTICED**: No longer supported Blazing " +#~ "Fast PSI https://eprint.iacr.org/2022/320.pdf two" +#~ " mode: fast mode or low communication" +#~ " mode" +#~ msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/reference/psi_v2_config.po b/docs/locale/zh_CN/LC_MESSAGES/reference/psi_v2_config.po new file mode 100644 index 00000000..e7b57b01 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/reference/psi_v2_config.po @@ -0,0 +1,1185 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-30 15:39+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../reference/psi_v2_config.md:1 +msgid "PSI v2 Configuration" +msgstr "" + +#: ../../reference/psi_v2_config.md:3 +msgid "Table of Contents" +msgstr "" + +#: ../../reference/psi_v2_config.md:7 ../../reference/psi_v2_config.md:40 +msgid "Messages" +msgstr "" + +#: ../../reference/psi_v2_config.md:8 +msgid "[DebugOptions](#debugoptions)" +msgstr "" + +#: ../../reference/psi_v2_config.md:9 +msgid "[EcdhConfig](#ecdhconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:10 +msgid "[InputAttr](#inputattr)" +msgstr "" + +#: ../../reference/psi_v2_config.md:11 +msgid "[InternalRecoveryRecord](#internalrecoveryrecord)" +msgstr "" + +#: ../../reference/psi_v2_config.md:12 +msgid "[IoConfig](#ioconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:13 +msgid "[KkrtConfig](#kkrtconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:14 +msgid "[OutputAttr](#outputattr)" +msgstr "" + +#: ../../reference/psi_v2_config.md:15 +msgid "[ProtocolConfig](#protocolconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:16 +msgid "[PsiConfig](#psiconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:17 +msgid "[RecoveryCheckpoint](#recoverycheckpoint)" +msgstr "" + +#: ../../reference/psi_v2_config.md:18 +msgid "[RecoveryConfig](#recoveryconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:19 +msgid "[Rr22Config](#rr22config)" +msgstr "" + +#: ../../reference/psi_v2_config.md:20 +msgid "[UbPsiConfig](#ubpsiconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md:24 ../../reference/psi_v2_config.md:388 +msgid "Enums" +msgstr "" + +#: ../../reference/psi_v2_config.md:25 +msgid "[IoType](#iotype)" +msgstr "" + +#: ../../reference/psi_v2_config.md:26 +msgid "[Protocol](#protocol)" +msgstr "" + +#: ../../reference/psi_v2_config.md:27 +msgid "[PsiConfig.AdvancedJoinType](#psiconfigadvancedjointype)" +msgstr "" + +#: ../../reference/psi_v2_config.md:28 +msgid "[RecoveryCheckpoint.Stage](#recoverycheckpointstage)" +msgstr "" + +#: ../../reference/psi_v2_config.md:29 +msgid "[Role](#role)" +msgstr "" + +#: ../../reference/psi_v2_config.md:30 +msgid "[UbPsiConfig.Mode](#ubpsiconfigmode)" +msgstr "" + +#: ../../reference/psi_v2_config.md:34 +msgid "[Scalar Value Types](#scalar-value-types)" +msgstr "" + +#: ../../reference/psi_v2_config.md:43 +msgid "DebugOptions" +msgstr "" + +#: ../../reference/psi_v2_config.md:44 +msgid "Logging level for default logger. Default to info. Supports:" +msgstr "" + +#: ../../reference/psi_v2_config.md:48 +msgid "trace: SPDLOG_LEVEL_TRACE" +msgstr "" + +#: ../../reference/psi_v2_config.md:49 +msgid "debug: SPDLOG_LEVEL_DEBUG" +msgstr "" + +#: ../../reference/psi_v2_config.md:50 +msgid "info: SPDLOG_LEVEL_INFO" +msgstr "" + +#: ../../reference/psi_v2_config.md:51 +msgid "warn: SPDLOG_LEVEL_WARN" +msgstr "" + +#: ../../reference/psi_v2_config.md:52 +msgid "err: SPDLOG_LEVEL_ERROR" +msgstr "" + +#: ../../reference/psi_v2_config.md:53 +msgid "critical: SPDLOG_LEVEL_CRITICAL" +msgstr "" + +#: ../../reference/psi_v2_config.md:54 +msgid "off: SPDLOG_LEVEL_OFF" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Field" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Description" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "logging_level" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ string](#string)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "none" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "trace_path" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "The path of trace. Deafult to /tmp/psi.trace" +msgstr "" + +#: ../../reference/psi_v2_config.md:65 +msgid "EcdhConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:66 +msgid "Configs for ECDH protocol." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "curve" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ psi.CurveType](#psicurvetype)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "batch_size" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ uint64](#uint64)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "If not set, use default value: 4096." +msgstr "" + +#: ../../reference/psi_v2_config.md:77 +msgid "InputAttr" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "keys_unique" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ bool](#bool)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Keys in input file are unique. If not set, use default value: false." +msgstr "" + +#: ../../reference/psi_v2_config.md:88 +msgid "InternalRecoveryRecord" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "stage" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ RecoveryCheckpoint.Stage](#recoverycheckpointstage)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ecdh_dual_masked_item_peer_count" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "parsed_bucket_count" +msgstr "" + +#: ../../reference/psi_v2_config.md:101 +msgid "IoConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:102 +msgid "IO configuration." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ IoType](#iotype)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "path" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Required for FILE." +msgstr "" + +#: ../../reference/psi_v2_config.md:113 +msgid "KkrtConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:114 +msgid "Configs for KKRT protocol" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "bucket_size" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Since the total input may not fit in memory, the input may be splitted " +"into buckets. bucket_size indicate the number of items in each bucket. If" +" the memory of host is limited, you should set a smaller bucket size. " +"Otherwise, you should use a larger one. If not set, use default value: 1 " +"<< 20." +msgstr "" + +#: ../../reference/psi_v2_config.md:124 +msgid "OutputAttr" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "csv_null_rep" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Null representation in output csv file. If not set, use default value: " +"\"NULL\"." +msgstr "" + +#: ../../reference/psi_v2_config.md:135 +msgid "ProtocolConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:136 +msgid "Any items related to PSI protocols." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "protocol" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ Protocol](#protocol)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "role" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ Role](#role)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "broadcast_result" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Reveal result to sender." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ecdh_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ EcdhConfig](#ecdhconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "For ECDH protocol." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "kkrt_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ KkrtConfig](#kkrtconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "For KKRT protocol." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "rr22_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ Rr22Config](#rr22config)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "For RR22 protocol." +msgstr "" + +#: ../../reference/psi_v2_config.md:151 +msgid "PsiConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:152 +msgid "The top level of Configs. run(PsiConfig)->PsiReport" +msgstr "" + +#: ../../reference/psi_v2_config.md:155 +msgid "Advanced Joins Type: Inner Join e.g. If input of receiver is" +msgstr "" + +#: ../../reference/psi_v2_config.md:166 +msgid "and input of sender is" +msgstr "" + +#: ../../reference/psi_v2_config.md:175 +msgid "After inner join. The output of receiver is:" +msgstr "" + +#: ../../reference/psi_v2_config.md:187 +msgid "The output of sender is" +msgstr "" + +#: ../../reference/psi_v2_config.md:199 +msgid "Type: Left Join After left join. The output of left side is:" +msgstr "" + +#: ../../reference/psi_v2_config.md:213 ../../reference/psi_v2_config.md:240 +#: ../../reference/psi_v2_config.md:268 ../../reference/psi_v2_config.md:291 +msgid "The output of right side is" +msgstr "" + +#: ../../reference/psi_v2_config.md:226 +msgid "Type: Right Join After right join. The output of left side is:" +msgstr "" + +#: ../../reference/psi_v2_config.md:253 +msgid "Type: Full Join After full join. The output of left side is:" +msgstr "" + +#: ../../reference/psi_v2_config.md:282 +msgid "Type: Difference After difference. The output of left side is:" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "protocol_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ ProtocolConfig](#protocolconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Configs for protocols." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "input_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ IoConfig](#ioconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Configs for input." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "output_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Configs for output." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "keys" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[repeated string](#string)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "keys for intersection." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "debug_options" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ DebugOptions](#debugoptions)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Logging level." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "skip_duplicates_check" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "If true, the check of duplicated items will be skiped." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "disable_alignment" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "It true, output is not promised to be aligned." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "recovery_config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ RecoveryConfig](#recoveryconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Configs for recovery." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "advanced_join_type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ PsiConfig.AdvancedJoinType](#psiconfigadvancedjointype)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "left_side" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Required if advanced_join_type is ADVANCED_JOIN_TYPE_LEFT_JOIN or " +"ADVANCED_JOIN_TYPE_RIGHT_JOIN." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "check_hash_digest" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Check if hash digest of keys from parties are equal to determine whether " +"to early-stop." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "input_attr" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ InputAttr](#inputattr)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Input attributes." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "output_attr" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ OutputAttr](#outputattr)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Output attributes." +msgstr "" + +#: ../../reference/psi_v2_config.md:319 +msgid "RecoveryCheckpoint" +msgstr "" + +#: ../../reference/psi_v2_config.md:320 +msgid "Save some critical information for future recovery." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Stage of PSI." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "config" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ PsiConfig](#psiconfig)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "A copy of origin PSI config." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "input_hash_digest" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ bytes](#bytes)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Hash digest of input keys." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ecdh_dual_masked_item_self_count" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Saved dual masked item count from self originally. PROTOCOL_ECDH only." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Saved dual masked item count from peer originally. PROTOCOL_ECDH only." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Saved parsed bucket count. PROTOCOL_KKRT and PROTOCOL_RR22 only." +msgstr "" + +#: ../../reference/psi_v2_config.md:335 +msgid "RecoveryConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:336 +msgid "" +"Configuration for recovery. If a PSI task failed unexpectedly, e.g. " +"network failures and restart, the task can resume to the latest " +"checkpoint to save time. However, enabling recovery would due in extra " +"disk IOs and disk space occupation." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "enabled" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "folder" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Stores status and checkpoint files." +msgstr "" + +#: ../../reference/psi_v2_config.md:351 +msgid "Rr22Config" +msgstr "" + +#: ../../reference/psi_v2_config.md:352 +msgid "Configs for RR22 protocol." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "low_comm_mode" +msgstr "" + +#: ../../reference/psi_v2_config.md:363 +msgid "UbPsiConfig" +msgstr "" + +#: ../../reference/psi_v2_config.md:364 +msgid "config for unbalanced psi." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "mode" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "[ UbPsiConfig.Mode](#ubpsiconfigmode)" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Required." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Required for all modes except MODE_OFFLINE_GEN_CACHE." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Config for origin input. Servers: Required for MODE_OFFLINE_GEN_CACHE, " +"MODE_OFFLINE, MODE_FULL. Clients: Required for MODE_ONLINE and MODE_FULL." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Join keys. Servers: Required for MODE_OFFLINE_GEN_CACHE, MODE_OFFLINE, " +"MODE_FULL. Clients: Required for MODE_ONLINE and MODE_FULL." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "server_secret_key_path" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Servers: Required for MODE_OFFLINE_GEN_CACHE, MODE_OFFLINE, MODE_ONLINE " +"and MODE_FULL." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "cache_path" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "server_get_result" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "client_get_result" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"It true, output is not promised to be aligned. Valid if both " +"server_get_result and client_get_result are true." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Required for MODE_ONLINE and MODE_FULL." +msgstr "" + +#: ../../reference/psi_v2_config.md:391 +msgid "IoType" +msgstr "" + +#: ../../reference/psi_v2_config.md:392 +msgid "TODO(junfeng): support more io types including oss, sql, etc." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Name" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Number" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "IO_TYPE_UNSPECIFIED" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "0" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "IO_TYPE_FILE_CSV" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "1" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Local csv file." +msgstr "" + +#: ../../reference/psi_v2_config.md:402 +msgid "Protocol" +msgstr "" + +#: ../../reference/psi_v2_config.md:403 +msgid "PSI protocols." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "PROTOCOL_UNSPECIFIED" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "PROTOCOL_ECDH" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"[Mea86]C. Meadows, \"A More Efficient Cryptographic Matchmaking Protocol " +"for Use in the Absence of a Continuously Available Third Party,\" 1986 " +"IEEE Symposium on Security and Privacy, Oakland, CA, USA, 1986, pp. " +"134-134, doi: 10.1109/SP.1986.10022." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "PROTOCOL_KKRT" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "2" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Efficient Batched Oblivious PRF with Applications to Private Set " +"Intersection https://eprint.iacr.org/2016/799.pdf" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "PROTOCOL_RR22" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "3" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Blazing Fast PSI https://eprint.iacr.org/2022/320.pdf" +msgstr "" + +#: ../../reference/psi_v2_config.md:415 +msgid "PsiConfig.AdvancedJoinType" +msgstr "" + +#: ../../reference/psi_v2_config.md:416 +msgid "Advanced Join allow duplicate keys." +msgstr "" + +#: ../../reference/psi_v2_config.md:417 +msgid "If selected, duplicates_check is skipped." +msgstr "" + +#: ../../reference/psi_v2_config.md:418 +msgid "If selected, both parties are allowed to contain duplicate keys." +msgstr "" + +#: ../../reference/psi_v2_config.md:419 +msgid "" +"If use left join, full join or difference, the size of difference set of " +"left party is revealed to right party." +msgstr "" + +#: ../../reference/psi_v2_config.md:421 +msgid "" +"If use right join, full join or difference, the size of difference set of" +" right party is revealed to left party." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ADVANCED_JOIN_TYPE_UNSPECIFIED" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ADVANCED_JOIN_TYPE_INNER_JOIN" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ADVANCED_JOIN_TYPE_LEFT_JOIN" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ADVANCED_JOIN_TYPE_RIGHT_JOIN" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ADVANCED_JOIN_TYPE_FULL_JOIN" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "4" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ADVANCED_JOIN_TYPE_DIFFERENCE" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "5" +msgstr "" + +#: ../../reference/psi_v2_config.md:436 +msgid "RecoveryCheckpoint.Stage" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "STAGE_UNSPECIFIED" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "STAGE_INIT_END" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "STAGE_PRE_PROCESS_END" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "STAGE_ONLINE_START" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "STAGE_ONLINE_END" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "STAGE_POST_PROCESS_END" +msgstr "" + +#: ../../reference/psi_v2_config.md:451 +msgid "Role" +msgstr "" + +#: ../../reference/psi_v2_config.md:452 +msgid "Role of parties." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ROLE_UNSPECIFIED" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ROLE_RECEIVER" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"receiver In 2P symmetric PSI, receivers would always receive the result " +"in the origin protocol." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ROLE_SENDER" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"sender In 2P symmetric PSI, senders are the other participants apart from" +" receiver." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ROLE_SERVER" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "server In 2P unbalanced PSI, servers own a much larger dataset." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ROLE_CLIENT" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "server In 2P unbalanced PSI, clients own a much smaller dataset." +msgstr "" + +#: ../../reference/psi_v2_config.md:465 +msgid "UbPsiConfig.Mode" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "MODE_UNSPECIFIED" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "MODE_OFFLINE_GEN_CACHE" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Servers generate cache only. First part of offline stage." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "MODE_OFFLINE_TRANSFER_CACHE" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Servers send cache to clients only. Second part of offline stage." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "MODE_OFFLINE" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Run offline stage." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "MODE_ONLINE" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Run online stage." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "MODE_FULL" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Run all stages." +msgstr "" + +#: ../../reference/psi_v2_config.md:481 +msgid "Scalar Value Types" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid ".proto Type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Notes" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "C++ Type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Java Type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Python Type" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

double" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "double" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "float" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

float" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

int32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint32 instead." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "int32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "int" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

int64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Uses variable-length encoding. Inefficient for encoding negative numbers " +"– if your field is likely to have negative values, use sint64 instead." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "int64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "long" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "int/long" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

uint32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Uses variable-length encoding." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "uint32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

uint64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "uint64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

sint32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int32s." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

sint64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Uses variable-length encoding. Signed int value. These more efficiently " +"encode negative numbers than regular int64s." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

fixed32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Always four bytes. More efficient than uint32 if values are often greater" +" than 2^28." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

fixed64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "" +"Always eight bytes. More efficient than uint64 if values are often " +"greater than 2^56." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

sfixed32" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Always four bytes." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

sfixed64" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "Always eight bytes." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

bool" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "bool" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "boolean" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

string" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "A string must always contain UTF-8 encoded or 7-bit ASCII text." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "string" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "String" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "str/unicode" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "

bytes" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "May contain any arbitrary sequence of bytes." +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "ByteString" +msgstr "" + +#: ../../reference/psi_v2_config.md +msgid "str" +msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/apsi_benchmark.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/apsi_benchmark.po new file mode 100644 index 00000000..a8b4afe7 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/apsi_benchmark.po @@ -0,0 +1,174 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 15:24+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/apsi_benchmark.md:1 +msgid "APSI Benchmark" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:2 +msgid "This document introduces the APSI Benchmark." +msgstr "本文档介绍APSI协议的benchmark" + +#: ../../user_guide/apsi_benchmark.md:4 +msgid "Building from source" +msgstr "源码构建" + +#: ../../user_guide/apsi_benchmark.md:11 +msgid "" +"If the build is successful, you will find an executable file named `main`" +" in the `bazel-bin/psi` directory. We will use `./main` file, combined " +"with a config file, to run APSI protocol. For exampple:" +msgstr "" +"如果构建成功,在 `bazel-bin/psi` 目录能找到 `./main` 的可执行文件。" +"传入配置文件名做参数,即可运行APSI协议。如下:" + + +#: ../../user_guide/apsi_benchmark.md:17 +msgid "Generate Data" +msgstr "生成测试数据" + +#: ../../user_guide/apsi_benchmark.md:18 +msgid "" +"To measure the performance of APSI protocols under different data scales," +" we need to generate dummy data." +msgstr "" +"要测量APSI在不同数据规模下的性能,首先需要生成一些测试数据。" + +#: ../../user_guide/apsi_benchmark.md:29 +msgid "Next, we need to copy the data and parameter files into /tmp:" +msgstr "" +"然后我们需要拷贝对一个的参数文件到/tmp目录。" + +#: ../../user_guide/apsi_benchmark.md:41 +msgid "" +"Please note that to achieve optimal APSI performance, we need to find a " +"suitable set of parameters for the corresponding data scale and label " +"length. Here, we directly use a set of default parameters provided by " +"APSI, such as `1M-1-32.json`." +msgstr "" +"请注意,我们需要找一个和数据规模匹配的参数才能达到APSI的最佳性能。" +"这里我们直接选APSI已经提供的参数文件 `1M-1-32.json` ,它的含义是sender方数据规模是1M条," +"query方的查询是一条,label的大小是32Byte。" + +#: ../../user_guide/apsi_benchmark.md:45 +msgid "Prepare config file" +msgstr "准备配置文件" + + +#: ../../user_guide/apsi_benchmark.md:46 +msgid "We use the config file to specify input data and parameter files." +msgstr "我们使用配置文件来指定输入数据和参数文件。" + +#: ../../user_guide/apsi_benchmark.md:48 +msgid "apsi_sender_setup.json" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:49 ../../user_guide/apsi_benchmark.md:88 +msgid "" +"Note that for different data scales, we need to use different " +"`params_file`." +msgstr "对不同的数据规模,选择合适的 `params_file` 。" + +#: ../../user_guide/apsi_benchmark.md:64 +msgid "apsi_sender_online.json" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:87 +msgid "apsi_receiver.json" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:116 +msgid "Run APSI with docker" +msgstr "使用docker运行APSI" + +#: ../../user_guide/apsi_benchmark.md:117 +msgid "" +"To measure the APSI benchmark under different machine and network " +"configurations, we use two Docker containers to act as sender and " +"receiver, respectively." +msgstr "" +"要测量APSI在不同的机器和网络配置下的性能,我们使用两个Docker容器来作为sender和receiver。" + +#: ../../user_guide/apsi_benchmark.md:119 +msgid "**apsi_sender(32C64G)**" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:137 +#: ../../user_guide/apsi_benchmark.md:163 +msgid "Then run:" +msgstr "然后运行" + +#: ../../user_guide/apsi_benchmark.md:146 +msgid "apsi_receiver(16C32G)" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:169 +msgid "Limit bandwidth and latency" +msgstr "带宽和延时" + +#: ../../user_guide/apsi_benchmark.md:180 +msgid "Benchmark" +msgstr "" + +#: ../../user_guide/apsi_benchmark.md:181 +msgid "" +"Here we present the APSI Benchmark measured as described above. Please " +"note that we do not record the time taken during the server-side setup " +"phase, as this process can always be completed offline." +msgstr "" +"注意我们不记录Setup阶段的时间,因为一般这个步骤是离线完成的。" + +#: ../../user_guide/apsi_benchmark.md:183 +msgid "" +"Additionally, only a small amount of performance data under specific data" +" settings is presented here. This is because performance testing for APSI" +" is quite complex; different data scales and label lengths require " +"finding a corresponding set of parameters to achieve optimal performance." +" Therefore, the data settings here are intended to provide you with a " +"rough reference." +msgstr "" +"而且,我们这里只是给出一个特定数据集上的性能数据。因为APSI的性能影响因素众多,不同的数据规模和不同的label长度" +"都需要搭配不同的数据文件来获得最佳的性能。因此,我们这里只是给出一个参考。" + +#: ../../user_guide/apsi_benchmark.md:185 +msgid "" +"If you wish to measure the APSI performance for a specific data scale and" +" label length, you can follow the steps outlined above to reproduce the " +"results. Finally, to further optimize performance, a good understanding " +"of the APSI algorithm principles is necessary. If you have any further " +"inquiries related to PIR, please feel free to contact us." +msgstr "" +"如果你想测量不同数据规模和label长度下的性能,可以根据上述步骤测量。如果要得到最近的性能," +"可能需要对特定的场景调整对应的参数。如果需要更进一步的需求,可以联系我们。" + +#: ../../user_guide/apsi_benchmark.md:187 +msgid "`ms` represents millisecond." +msgstr "`ms` 表示毫秒" + +#: ../../user_guide/apsi_benchmark.md:218 +msgid "" +"Note that the above data does not represent the optimal performance of " +"APSI. Under fixed data scale conditions, the query performance of APSI is" +" highly correlated with the corresponding parameters. Additionally, if " +"you want to support larger datasets, such as one billion data entries, we" +" also offer a bucket mode. However, this mode requires consideration of " +"more parameters, so it is not displayed in this benchmark." +msgstr "" +"以上的数据并不代表APSI的最佳性能。APSI的查询性能在特定的场景下和使用的参数高度相关。" +"并且对于超大数据集,我们提供分桶模式。" diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/faq.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/faq.po new file mode 100644 index 00000000..86b48787 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/faq.po @@ -0,0 +1,211 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-06 11:59+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/faq.rst:2 +msgid "Frequently Asked Questions (FAQ)" +msgstr "常见问题(FAQ)" + +#: ../../user_guide/faq.rst:4 +msgid "" +"We will collect some popular questions from users and update this part " +"promptly." +msgstr "我们会定期收集常见的问题" + +#: ../../user_guide/faq.rst:7 +msgid "Config Issues" +msgstr "配置问题" + +#: ../../user_guide/faq.rst:9 +msgid "" +"In PSI config, what is difference of **broadcast_result** and " +"**receiver**? Is it safe to turn on **broadcast_result**?" +msgstr "" +"在PSI配置里, **broadcast_result** 和 **receiver** 的差异是什么?打开 " +"**broadcast_result** 安全吗?" + +#: ../../user_guide/faq.rst:11 +msgid "" +"In PSI protocols, the parties who are promised to receive the " +"intersection are called **receiver**s, the other parties are called " +"**sender**s. When **broadcast_result** is turn on, **sender**s also " +"receive the intersection. Both parties must agree on the value of " +"**broadcast_result**, otherwise the program will stop." +msgstr "" +"在PSI协议里,接收结果的一方被称为 **receiver** ,另一方是 **sender** 。当 **broadcast_result** " +"打开,所有参与方都会接收到交集结果。但是该功能需要参与方都打开该功能才可以,不然的话协议会终止。" + +#: ../../user_guide/faq.rst:14 +msgid "" +"If **broadcast_result** is turn on, only **receiver**s and **sender**s " +"could receive the result while any third parties could not see. So it is " +"safe to set **broadcast_result** to true, if both **receiver**s and " +"**sender**s wish to get the result." +msgstr "" +"如果 **broadcast_result** " +"打开,只有参与协议的才能获取结果,不代表其他方能获取结果。所以,**broadcast_result** " +"是安全的,在需要参与方都获取结果的场景下可以打开。" + +#: ../../user_guide/faq.rst:16 +msgid "What is :ref:`IO_TYPE_UNSPECIFIED `?" +msgstr "什么是 :ref:`IO_TYPE_UNSPECIFIED `? " + +#: ../../user_guide/faq.rst:18 +msgid "" +"You must select a type as IoType. :ref:`IO_TYPE_UNSPECIFIED " +"` is the default value of :ref:`IoType `, " +"which is meaningless. At this moment, we only support " +":ref:`IO_TYPE_FILE_CSV `." +msgstr "" +"我们要求必须指定一个输入类型 :ref:`IoType `,如果不指定,就是 :ref:`IO_TYPE_UNSPECIFIED " +"` 。当前我们只支持 :ref:`IO_TYPE_FILE_CSV " +"`。不过后续我们会考虑把csv作为默认。" + +#: ../../user_guide/faq.rst:20 +msgid "" +"What is :ref:`ADVANCED_JOIN_TYPE_UNSPECIFIED " +"`?" +msgstr "" +"什么是 :ref:`ADVANCED_JOIN_TYPE_UNSPECIFIED " +"`?" + +#: ../../user_guide/faq.rst:22 +msgid "" +"PSI protocols doesn‘t allow duplicates in ids of inputs. However, " +"sometimes we may intend to have duplicates in ids and perform LEFT / " +"RIGHT / FULL join following rules of SQL. This is called " +":ref:`AdvancedJoinType `." +msgstr "" +"PSI协议本身是不支持有重复的ID的,但是我们有时候需要类似SQL的LEFT /RIGHT / FULL join操作。也就是所谓的 " +":ref:`AdvancedJoinType `。" + +#: ../../user_guide/faq.rst:24 +msgid "" +":ref:`ADVANCED_JOIN_TYPE_UNSPECIFIED ` is" +" same as :ref:`ADVANCED_JOIN_TYPE_INNER_JOIN " +"`." +msgstr "" +":ref:`ADVANCED_JOIN_TYPE_UNSPECIFIED ` " +"等价于 :ref:`ADVANCED_JOIN_TYPE_INNER_JOIN `." + +#: ../../user_guide/faq.rst:26 +msgid "What is the recommendation value of bucket size?" +msgstr "推荐的桶大小是多少?" + +#: ../../user_guide/faq.rst:28 +msgid "" +"The default value is 2^20. You shouldn't set this value unless you have " +"very limited computation resource." +msgstr "默认是2^20。一般保持默认值就好。" + +#: ../../user_guide/faq.rst:30 +msgid "What is :ref:`disable_alignment `?" +msgstr "什么是 :ref:`disable_alignment `?" + +#: ../../user_guide/faq.rst:32 +msgid "" +"If :ref:`disable_alignment ` turns on, the " +"intersection received by **receiver**s and **sender**s are not promised " +"to be aligned(the order doesn't match) and save time." +msgstr "如果 :ref:`disable_alignment ` 为真, 求交结果在各方的输出是不会对齐的。" + +#: ../../user_guide/faq.rst:35 +msgid "" +"What is :ref:`RetryOptionsProto ` in " +":ref:`ContextDescProto `?" +msgstr "" +"什么是 :ref:`RetryOptionsProto ` in " +":ref:`ContextDescProto `?" + +#: ../../user_guide/faq.rst:37 +msgid "" +"We have proper default values for all fields. You shouldn't set any " +"values unless the network is pretty bad. For more info, you can look up " +"`here " +"`_." +msgstr "" +"一般保持默认值就好。具体定义可以看 ` 这里 " +"`_ 。" + +#: ../../user_guide/faq.rst:41 +msgid "Feature Issues" +msgstr "特性问题" + +#: ../../user_guide/faq.rst:43 +msgid "How to enable SSL?" +msgstr "如何使用SSL?" + +#: ../../user_guide/faq.rst:45 +msgid "" +"We support mTLS and you should provide proper :ref:`ContextDescProto " +"`:" +msgstr "" +"我们支持mTLS, 配置 :ref:`ContextDescProto ` 的" + +#: ../../user_guide/faq.rst:47 +msgid "**enable_ssl** is enabled." +msgstr "**enable_ssl** 为真。" + +#: ../../user_guide/faq.rst:48 +msgid "" +"In **client_ssl_opts**, set **verify_depth** and provide peer CA file " +"with **ca_file_path**" +msgstr "设置 **client_ssl_opts** 的 **verify_depth** ,并且设置CA文件 **ca_file_path** 。" + +#: ../../user_guide/faq.rst:49 +msgid "" +"In **server_ssl_opts**, provide self certificate and private key file " +"with **certificate_path** and **private_key_path**" +msgstr "" +"设置 **server_ssl_opts** 的 **certificate_path** 为自己的证书,**private_key_path**" +" 为私钥。" + +#: ../../user_guide/faq.rst:50 +msgid "You must provide these settings at both sides." +msgstr "两边都要设置。" + +#: ../../user_guide/faq.rst:52 +msgid "example.config" +msgstr "" + +#: ../../user_guide/faq.rst:81 +msgid "How to use recovery?" +msgstr "如何使用recovery?" + +#: ../../user_guide/faq.rst:83 +msgid "We provide recovery feature in PSI v2." +msgstr "PSI v2提供了recovery特性,支持PSI可以保存检查点。" + +#: ../../user_guide/faq.rst:85 +msgid "You have to provide a proper:ref:`RecoveryConfig `:" +msgstr "需要提供 :ref:`RecoveryConfig ` 的" + +#: ../../user_guide/faq.rst:87 +msgid "**enabled** set to true." +msgstr "设置 **enabled** 为真。" + +#: ../../user_guide/faq.rst:88 +msgid "**folder** is provided to store checkpoints." +msgstr "**folder** 为检查点的目录。" + +#: ../../user_guide/faq.rst:90 +msgid "" +"If a PSI task fails, just restart the task with the same config, the " +"progress will resume." +msgstr "如果PSI任务失败了,可以从检查点重启。" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/index.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/index.po new file mode 100644 index 00000000..aff052c5 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/index.po @@ -0,0 +1,30 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 15:24+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/index.rst:2 +msgid "User Guide" +msgstr "用户指南" + +#: ../../user_guide/index.rst:4 +msgid "" +"PSI v2 is recommended to use. We are still working on PIR code " +"refactoring." +msgstr "" +"推荐使用PSI v2配置. PIR的实现我们正在开发。 " + diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/pir.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/pir.po new file mode 100644 index 00000000..e3eced77 --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/pir.po @@ -0,0 +1,343 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-26 20:09+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/pir.rst:2 +msgid "PIR QuickStart" +msgstr "PIR 快速入门" + +#: ../../user_guide/pir.rst:4 +msgid "Quick start with SPU Private Information Retrival (PIR)." +msgstr "PIR 快速入门" + +#: ../../user_guide/pir.rst:7 +msgid "Supported Protocols" +msgstr "支持的协议" + +#: ../../user_guide/pir.rst:10 +msgid "PIR protocols" +msgstr "" + +#: ../../user_guide/pir.rst:10 +msgid "Type" +msgstr "" + +#: ../../user_guide/pir.rst:10 +msgid "Server Number" +msgstr "" + +#: ../../user_guide/pir.rst:12 +msgid "SealPIR(later)" +msgstr "" + +#: ../../user_guide/pir.rst:12 +msgid "Index PIR" +msgstr "" + +#: ../../user_guide/pir.rst:12 ../../user_guide/pir.rst:14 +msgid "Single Server" +msgstr "" + +#: ../../user_guide/pir.rst:14 +msgid "APSI" +msgstr "" + +#: ../../user_guide/pir.rst:14 +msgid "Keyword PIR" +msgstr "" + +#: ../../user_guide/pir.rst:17 +msgid "At this moment, SealPIR is under development." +msgstr "SealPIR 正在开发中。" + +#: ../../user_guide/pir.rst:21 +msgid "Release Docker" +msgstr "" + +#: ../../user_guide/pir.rst:23 +msgid "" +"Check official release docker image at `dockerhub " +"`_. We also have mirrors" +" at Alibaba Cloud: `secretflow-registry.cn-" +"hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`." +msgstr "" +"我们有Docker镜像 `dockerhub `_ , 也有阿里云镜像: `secretflow-registry.cn-" +"hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`." + +#: ../../user_guide/pir.rst:27 +msgid "Keyword PIR (APSI)" +msgstr "" + +#: ../../user_guide/pir.rst:30 +msgid "Before Start" +msgstr "开始准备" + +#: ../../user_guide/pir.rst:32 +msgid "" +"We provide a simple wrapper for famous `APSI " +"`_ library. Please read the `README " +"`_ of " +"the repo carefully. We are not going to discuss any content related to " +"APSI further." +msgstr "" +"我们对 `APSI `_ 库提供了一个简单的封装. 请仔细阅读APSI仓的 " +"`README `_ 。 我们这里不再重复描述APSI文档中描述的东西。" + +#: ../../user_guide/pir.rst:36 +msgid "" +"Please check details of configs at :doc:`/reference/pir_config`. You are " +"supposed to be aware of that we provided the **EXACT** the same API to " +"APSI. So you should read `APSI CLI arguments " +"`_ as well." +msgstr "" +"配置细节可以参考 :doc:`/reference/pir_config`。基本上我们和APSI的命令行参数保持一致。所以你可以阅读 `APSI " +"CLI arguments `_ 来作为参考。" + +#: ../../user_guide/pir.rst:39 +msgid "The extra features brought are:" +msgstr "额外加的功能是:" + +#: ../../user_guide/pir.rst:41 +msgid "Use Yacl Link as communication layer." +msgstr "使用Yacl Link作为通信层。" + +#: ../../user_guide/pir.rst:42 +msgid "Experimental bucketized PIR." +msgstr "试验性的分桶PIR" + +#: ../../user_guide/pir.rst:43 +msgid "Provide APIs for further integration." +msgstr "提供了额外用来集成的API。" + +#: ../../user_guide/pir.rst:45 +msgid "" +"If you want to try a similar CLI like APSI, you could compile the source " +"code by" +msgstr "如果你想要尝试一个类似APSI的CLI,你可以通过如下编译:" + +#: ../../user_guide/pir.rst:54 +msgid "And get CLI parameters like this:" +msgstr "获取命令行参数如下:" + +#: ../../user_guide/pir.rst:65 +msgid "Prepare data and config" +msgstr "准备数据和配置:" + +#: ../../user_guide/pir.rst:67 +msgid "" +"For Senders (Servers), you must provide a input csv or a sender db file. " +"An input csv file could be turned into a sender db file after setup." +msgstr "对于 Senders (Servers), 需要提供一个CSV文件或者一个sender db文件. CSV文件会被转换成sender db文件。" + +#: ../../user_guide/pir.rst:71 +msgid "CSV File" +msgstr "CSV文件" + +#: ../../user_guide/pir.rst:73 +msgid "The csv file should looks like" +msgstr "CSV文件格式如下:" + +#: ../../user_guide/pir.rst:88 +msgid "Please make sure:" +msgstr "要确保:" + +#: ../../user_guide/pir.rst:90 +msgid "Since version **0.4.0b0**, headers line is required." +msgstr "版本0.4.0b0开始,CSV文件必须有headers行。" + +#: ../../user_guide/pir.rst:91 +msgid "The first row must be headers, only **key** and **value** are allowed." +msgstr "列名只允许 key 和 value 两列。" + +#: ../../user_guide/pir.rst:92 +msgid "The **key** column must be items(keys)" +msgstr "**key** 列必须是ID列" + +#: ../../user_guide/pir.rst:93 +msgid "The **value** column must be labels(values), this column is optional." +msgstr "**value** 列可选,是label列。" + +#: ../../user_guide/pir.rst:97 +msgid "APSI Params File" +msgstr "APSI参数文件" + +#: ../../user_guide/pir.rst:99 +msgid "" +"We use the original APSI params. For details, please check `APSI " +"PSIParams `_ ." +msgstr "" +"我们使用了大多 `APSI PSIParams `_ 的参数。" + +#: ../../user_guide/pir.rst:101 +msgid "" +"For senders: An APSI params file must be provided with CSV files. If a " +"sender db file is provided, the APSI params is not required and would be " +"ignored. For receivers: The APSI params file is optional. If not " +"provided, receivers will ask for senders. If provided, please make sure " +"receivers and senders share the same APSI params file, otherwise error " +"occurred." +msgstr "" +"对 senders 而言: APSI 参数文件需要提供。如果是已经生成的DB文件, APSI参数文件会被忽略。对 receivers 而言: " +"APSI参数文件是可选的。如果没有提供, receivers 会从 senders 处请求. 如果提供了,请确保receivers 和 " +"senders 的 APSI参数文件一致。" + +#: ../../user_guide/pir.rst:105 +msgid "" +"It's not easy to find a suitable APSI params file. So APSI provides some " +"examples at `APSI parameters " +"` as well. " +"You can refer to `here `_ to choose the appropriate parameter file." +msgstr "" +"APSI的参数是不好定的。APSI预先调试好了一些参数 `APSI parameters " +"`_ . 我们的代码仓也拷贝了一份 " +"`APSI parameters `_" +" 。参考 `这里 `_ 选择合适的参数文件。 " + +#: ../../user_guide/pir.rst:110 +msgid "" +"To launch PIR, please check LaunchConfig at " +":doc:`/reference/launch_config`, and specific config: :ref:`sender config" +" ` and :ref:`receiver config `." +msgstr "" +"要启动PIR,可以查看启动配置 :doc:`/reference/launch_config`, APSI配置: :ref:`sender " +"config ` 和 :ref:`receiver config `." + +#: ../../user_guide/pir.rst:115 +msgid "PIR Config" +msgstr "PIR 配置" + +#: ../../user_guide/pir.rst:117 +msgid "" +"Sender: Setup Stage. In this stage, sender generates sender db file with " +"csv file. This stage is offline. Since version **0.4.0b0**, the source " +"csv file for db generating should be specified as **source_file**, and " +"**db_file** is used to specify the generated db file." +msgstr "" +"Sender: 准备阶段,使用CSV输入生成DB文件。这个阶段是离线的。自 **0.4.0b0** 版本起, 用来生成DB文件的CSV文件使用 " +"**source_file** 指定, 并且 **db_file** 用来指定生成DB文件的文件夹。" + +#: ../../user_guide/pir.rst:121 +msgid "apsi_sender_setup.json" +msgstr "" + +#: ../../user_guide/pir.rst:133 +msgid "" +"Sender: Online stage. In this stage, sender generates responses to " +"receivers' queries. This stage is online." +msgstr "Sender: 在线阶段。Sender接收Reciver的Query请求生成回复。" + +#: ../../user_guide/pir.rst:135 +msgid "apsi_sender_online.json" +msgstr "" + +#: ../../user_guide/pir.rst:158 +msgid "Receiver: Online stage." +msgstr "Receiver: 在线阶段" + +#: ../../user_guide/pir.rst:160 +msgid "apsi_receiver.json" +msgstr "" + +#: ../../user_guide/pir.rst:184 +msgid "" +"params_file field is optional. If not provided, receiver will ask sender " +"for params. If provided, please make sure you provide the same one to " +"sender's." +msgstr "params_file 字段是可选的。如果没提供,Receiver会向Sender请求参数。如果提供了,请确保和Sender使用的一致。" + +#: ../../user_guide/pir.rst:188 +msgid "Full Examples" +msgstr "完整的例子" + +#: ../../user_guide/pir.rst:190 +msgid "" +"Please read `examples " +"`_. " +"For more demo configs, you can check `here " +"`_." +msgstr "" +"请查看 `examples " +"`_. " +"示例配置,可以查看 `here " +"`_." + +#: ../../user_guide/pir.rst:195 +msgid "Bucketized Mode" +msgstr "分桶模式" + +#: ../../user_guide/pir.rst:197 +msgid "" +"Searching in a large sender db is costly. So we can split data into " +"buckets. The server knows which bucket the client is querying, but does " +"not know which specific element:" +msgstr "搜索一个很大的Sender DB是很耗时的。所以我们可以将数据分桶。Server知道client查询的是哪个桶,但是不知道具体元素:" + +#: ../../user_guide/pir.rst:200 +msgid "" +"In the setup stage, sender split data into buckets. Each bucket will " +"generate a sender db." +msgstr "在准备阶段,Sender将数据分桶。每个桶会生成一个Sender DB。" + +#: ../../user_guide/pir.rst:202 +msgid "" +"In the online stage, receiver split query into subqueries. Each subquery " +"only contains items residing in the same bucket. When receivers sends a " +"subquery to the sender, bucket idx is also provided." +msgstr "" +"在在线阶段,Receiver将Query分拆成子Query。每个子Query只包含在同一个桶里的元素。当Receiver发送一个子Query给Sender时,也会提供bucket" +" idx。" + +#: ../../user_guide/pir.rst:205 +msgid "" +"For each subquery, sender only search in the corresponding sender db for " +"specific bucket." +msgstr "对每个子Query,Sender只在对应的Sender DB的桶里里搜索。" + +#: ../../user_guide/pir.rst:207 +msgid "" +"Assuming the query indindiscernibility degree is " +":math:`\\text{ind_degree}`, and sender has " +":math:`\\text{sender_data_rows}` rows, then the number of buckets should " +"be :math:`\\text{bucket_num} = \\text{sender_data_rows} / " +"\\text{ind_degree}`, you can set :ref:`experimental_bucket_cnt " +"` with :math:`\\text{bucket_num}`. If the client has " +":math:`\\text{query_rows}` rows of data, the we know client has " +":math:`\\text{query_rows_per_bucket} = \\text{query_rows} / " +"\\text{bucket_num}` rows per bucket, we can select " +":math:`\\text{ind_degree}`-:math:`\\text{query_rows_per_bucket}`-xxx.json" +" as :ref:`params_file `." +msgstr "" +"假设Query的不可区分度为 :math:`\\text{ind_degree}`,Sender有 " +":math:`\\text{sender_data_rows}` 行数据。那么桶的数量应该为 :math:`\\text{bucket_num} " +"= \\text{sender_data_rows} / \\text{ind_degree}`。你可以设置 " +":ref:`experimental_bucket_cnt ` 为 " +":math:`\\text{bucket_num}`。如果Client有 :math:`\\text{query_rows}` " +"行数据,那么每个桶里会有 :math:`\\text{query_rows_per_bucket} = \\text{query_rows} / " +"\\text{bucket_num}` 行数据。你就可以选择 " +":math:`\\text{ind_degree}`-:math:`\\text{query_rows_per_bucket}`-xxx.json作为" +" :ref:`params_file `。" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi.po new file mode 100644 index 00000000..69d9afec --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi.po @@ -0,0 +1,588 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-26 20:09+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/psi.rst:2 +msgid "PSI v1 QuickStart (Deprecated)" +msgstr "" + +#: ../../user_guide/psi.rst:4 +msgid "Quick start with Private Set Intersection (PSI) V1 APIs." +msgstr "" + +#: ../../user_guide/psi.rst:8 +msgid "Supported Protocols" +msgstr "" + +#: ../../user_guide/psi.rst:10 +msgid "" +"The :psi_code_host:`ECDH-PSI " +"` is favorable if the " +"bandwidth is the bottleneck. If the computing is the bottleneck, you " +"should try the BaRK-OPRF based PSI :psi_code_host:`KKRT-PSI " +"`." +msgstr "" + +#: ../../user_guide/psi.rst:15 +msgid "PSI protocols" +msgstr "" + +#: ../../user_guide/psi.rst:15 +msgid "Threat Model" +msgstr "" + +#: ../../user_guide/psi.rst:15 +msgid "Party Number" +msgstr "" + +#: ../../user_guide/psi.rst:15 +msgid "PsiTypeCode" +msgstr "" + +#: ../../user_guide/psi.rst:17 +msgid "ECDH-PSI" +msgstr "" + +#: ../../user_guide/psi.rst:17 ../../user_guide/psi.rst:19 +#: ../../user_guide/psi.rst:21 ../../user_guide/psi.rst:23 +#: ../../user_guide/psi.rst:27 +msgid "Semi-Honest" +msgstr "" + +#: ../../user_guide/psi.rst:17 ../../user_guide/psi.rst:19 +#: ../../user_guide/psi.rst:21 ../../user_guide/psi.rst:23 +#: ../../user_guide/psi.rst:25 ../../user_guide/psi.rst:27 +msgid "2P" +msgstr "" + +#: ../../user_guide/psi.rst:17 +msgid "1" +msgstr "" + +#: ../../user_guide/psi.rst:19 +msgid "ECDH-OPRF-PSI" +msgstr "" + +#: ../../user_guide/psi.rst:21 +msgid "`KKRT`_" +msgstr "" + +#: ../../user_guide/psi.rst:21 +msgid "2" +msgstr "" + +#: ../../user_guide/psi.rst:23 +msgid "`PCG_PSI`_" +msgstr "" + +#: ../../user_guide/psi.rst:23 +msgid "3" +msgstr "" + +#: ../../user_guide/psi.rst:25 +msgid "`Mini-PSI`_" +msgstr "" + +#: ../../user_guide/psi.rst:25 +msgid "Malicious" +msgstr "" + +#: ../../user_guide/psi.rst:27 +msgid "`DP-PSI`_" +msgstr "" + +#: ../../user_guide/psi.rst:30 +msgid "" +"MPC and PSI protocols are designed for specific Security model (or Threat" +" Models)." +msgstr "" + +#: ../../user_guide/psi.rst:32 +msgid "" +"Security model are widely considered to capture the capabilities of " +"adversaries. Adversaries of semi-honest model and malicious model are " +"Semi-honest Adversary and Malicious Adversary." +msgstr "" + +#: ../../user_guide/psi.rst:36 +msgid "" +"`Semi-honest Adversary " +"`_" +msgstr "" + +#: ../../user_guide/psi.rst:37 +msgid "" +"`Malicious Adversary " +"`_" +msgstr "" + +#: ../../user_guide/psi.rst:39 +msgid "" +"Semi-Honest PSI Must not be used in Malicious environment, may be " +"attacked and leak information." +msgstr "" + +#: ../../user_guide/psi.rst:41 +msgid "Our implementation of ECDH-PSI protocol supports multiple ECC curves:" +msgstr "" + +#: ../../user_guide/psi.rst:43 +msgid "`Curve25519 `_" +msgstr "" + +#: ../../user_guide/psi.rst:44 +msgid "`Secp256k1 `_" +msgstr "" + +#: ../../user_guide/psi.rst:45 +msgid "`FourQ `_" +msgstr "" + +#: ../../user_guide/psi.rst:46 +msgid "`SM2 `_" +msgstr "" + +#: ../../user_guide/psi.rst:53 +msgid "Please check :doc:`/development/psi_protocol_intro` for details." +msgstr "" + +#: ../../user_guide/psi.rst:56 +msgid "Prepare data and config" +msgstr "" + +#: ../../user_guide/psi.rst:58 +msgid "Please check details of configs at :doc:`/reference/psi_config`." +msgstr "" + +#: ../../user_guide/psi.rst:60 +msgid "" +"To launch PSI, please check LaunchConfig at " +":doc:`/reference/launch_config` and fillin " +"**runtime_config.legacy_psi_config**." +msgstr "" + +#: ../../user_guide/psi.rst:63 +msgid "Release Docker" +msgstr "" + +#: ../../user_guide/psi.rst:65 +msgid "" +"Check official release docker image at `dockerhub " +"`_. We also have mirrors" +" at Alibaba Cloud: secretflow-registry.cn-" +"hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8." +msgstr "" + +#: ../../user_guide/psi.rst:68 +msgid "Run PSI" +msgstr "" + +#: ../../user_guide/psi.rst:70 +msgid "In the first terminal, run the following command::" +msgstr "" + +#: ../../user_guide/psi.rst:75 +msgid "In the other terminal, run the following command simultaneously::" +msgstr "" + +#: ../../user_guide/psi.rst:81 +msgid "Building from source" +msgstr "" + +#: ../../user_guide/psi.rst:83 +msgid "You could build psi binary with bazel::" +msgstr "" + +#: ../../user_guide/psi.rst:88 +msgid "Then use binary with::" +msgstr "" + +#: ../../user_guide/psi.rst:93 +msgid "Benchmark" +msgstr "" + +#: ../../user_guide/psi.rst:95 +msgid "benchmark result without data load time" +msgstr "" + +#: ../../user_guide/psi.rst:98 +msgid "ECDH PSI Benchmark" +msgstr "" + +#: ../../user_guide/psi.rst:100 +msgid "" +":psi_code_host:`DH-PSI benchmark code " +"`" +msgstr "" + +#: ../../user_guide/psi.rst:102 +msgid "cpu limited by docker(--cpu)" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +msgid "Intel(R) Xeon(R) Platinum" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +msgid "cpu" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +#: ../../user_guide/psi.rst:145 +msgid "2^20" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +msgid "2^21" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +#: ../../user_guide/psi.rst:145 +msgid "2^22" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +msgid "2^23" +msgstr "" + +#: ../../user_guide/psi.rst:105 ../../user_guide/psi.rst:118 +#: ../../user_guide/psi.rst:145 +msgid "2^24" +msgstr "" + +#: ../../user_guide/psi.rst:108 +msgid "8269CY CPU @ 2.50GHz" +msgstr "" + +#: ../../user_guide/psi.rst:110 +msgid "with curve25519-donna" +msgstr "" + +#: ../../user_guide/psi.rst:107 ../../user_guide/psi.rst:120 +msgid "4c" +msgstr "" + +#: ../../user_guide/psi.rst:107 +msgid "40.181s" +msgstr "" + +#: ../../user_guide/psi.rst:107 +msgid "81.227s" +msgstr "" + +#: ../../user_guide/psi.rst:107 +msgid "163.509s" +msgstr "" + +#: ../../user_guide/psi.rst:107 +msgid "330.466s" +msgstr "" + +#: ../../user_guide/psi.rst:107 +msgid "666.807s" +msgstr "" + +#: ../../user_guide/psi.rst:109 ../../user_guide/psi.rst:122 +msgid "8c" +msgstr "" + +#: ../../user_guide/psi.rst:109 +msgid "20.682s" +msgstr "" + +#: ../../user_guide/psi.rst:109 +msgid "42.054s" +msgstr "" + +#: ../../user_guide/psi.rst:109 +msgid "85.272s" +msgstr "" + +#: ../../user_guide/psi.rst:109 +msgid "173.836s" +msgstr "" + +#: ../../user_guide/psi.rst:109 +msgid "354.842s" +msgstr "" + +#: ../../user_guide/psi.rst:111 ../../user_guide/psi.rst:124 +msgid "16c" +msgstr "" + +#: ../../user_guide/psi.rst:111 +msgid "11.639s" +msgstr "" + +#: ../../user_guide/psi.rst:111 +msgid "23.670s" +msgstr "" + +#: ../../user_guide/psi.rst:111 +msgid "48.965s" +msgstr "" + +#: ../../user_guide/psi.rst:111 +msgid "100.903s" +msgstr "" + +#: ../../user_guide/psi.rst:111 +msgid "208.156s" +msgstr "" + +#: ../../user_guide/psi.rst:114 +msgid "" +"`ipp-crypto Multi-buffer Functions " +"`_" +msgstr "" + +#: ../../user_guide/psi.rst:121 +msgid "8369B CPU @ 2.70GHz" +msgstr "" + +#: ../../user_guide/psi.rst:123 +msgid "curve25519(ipp-crypto)" +msgstr "" + +#: ../../user_guide/psi.rst:120 +msgid "7.37s" +msgstr "" + +#: ../../user_guide/psi.rst:120 +msgid "15.32s" +msgstr "" + +#: ../../user_guide/psi.rst:120 +msgid "31.932s" +msgstr "" + +#: ../../user_guide/psi.rst:120 +msgid "66.802s" +msgstr "" + +#: ../../user_guide/psi.rst:120 +msgid "139.994s" +msgstr "" + +#: ../../user_guide/psi.rst:122 +msgid "4.3s" +msgstr "" + +#: ../../user_guide/psi.rst:122 +msgid "9.095s" +msgstr "" + +#: ../../user_guide/psi.rst:122 +msgid "18.919s" +msgstr "" + +#: ../../user_guide/psi.rst:122 +msgid "40.828s" +msgstr "" + +#: ../../user_guide/psi.rst:122 +msgid "87.649s" +msgstr "" + +#: ../../user_guide/psi.rst:124 +msgid "2.921s" +msgstr "" + +#: ../../user_guide/psi.rst:124 +msgid "6.081s" +msgstr "" + +#: ../../user_guide/psi.rst:124 +msgid "13.186s" +msgstr "" + +#: ../../user_guide/psi.rst:124 +msgid "29.614s" +msgstr "" + +#: ../../user_guide/psi.rst:124 +msgid "65.186s" +msgstr "" + +#: ../../user_guide/psi.rst:128 +msgid "KKRT PSI Benchmark" +msgstr "" + +#: ../../user_guide/psi.rst:130 +msgid "All of our experiments use a single thread for each party." +msgstr "" + +#: ../../user_guide/psi.rst:132 +msgid "" +"If the bandwidth is enough, the upstream could try to perform multi-" +"threading optimizations" +msgstr "" + +#: ../../user_guide/psi.rst:134 +msgid "" +"bandwidth limited by `wondershaper " +"`_." +msgstr "" + +#: ../../user_guide/psi.rst:136 +msgid "10Mbps = 10240Kbps, 100Mbps = 102400Kbps, 1000Mbps = 1024000Kbps" +msgstr "" + +#: ../../user_guide/psi.rst:142 +msgid "Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz" +msgstr "" + +#: ../../user_guide/psi.rst:145 +msgid "bandwidth" +msgstr "" + +#: ../../user_guide/psi.rst:145 +msgid "phase" +msgstr "" + +#: ../../user_guide/psi.rst:145 +msgid "2^18" +msgstr "" + +#: ../../user_guide/psi.rst:148 +msgid "LAN" +msgstr "" + +#: ../../user_guide/psi.rst:147 ../../user_guide/psi.rst:151 +#: ../../user_guide/psi.rst:155 +msgid "offline" +msgstr "" + +#: ../../user_guide/psi.rst:147 ../../user_guide/psi.rst:151 +msgid "0.012s" +msgstr "" + +#: ../../user_guide/psi.rst:147 ../../user_guide/psi.rst:151 +msgid "0.014s" +msgstr "" + +#: ../../user_guide/psi.rst:149 ../../user_guide/psi.rst:153 +#: ../../user_guide/psi.rst:157 +msgid "online" +msgstr "" + +#: ../../user_guide/psi.rst:149 +msgid "0.495s" +msgstr "" + +#: ../../user_guide/psi.rst:149 +msgid "2.474s" +msgstr "" + +#: ../../user_guide/psi.rst:149 +msgid "10.765s" +msgstr "" + +#: ../../user_guide/psi.rst:149 +msgid "44.368s" +msgstr "" + +#: ../../user_guide/psi.rst:152 +msgid "100Mbps" +msgstr "" + +#: ../../user_guide/psi.rst:151 +msgid "0.024s" +msgstr "" + +#: ../../user_guide/psi.rst:153 +msgid "2.694s" +msgstr "" + +#: ../../user_guide/psi.rst:153 +msgid "11.048s" +msgstr "" + +#: ../../user_guide/psi.rst:153 +msgid "46.983s" +msgstr "" + +#: ../../user_guide/psi.rst:153 +msgid "192.37s" +msgstr "" + +#: ../../user_guide/psi.rst:156 +msgid "10Mbps" +msgstr "" + +#: ../../user_guide/psi.rst:155 +msgid "0.016s" +msgstr "" + +#: ../../user_guide/psi.rst:155 +msgid "0.019s" +msgstr "" + +#: ../../user_guide/psi.rst:155 +msgid "0.0312s" +msgstr "" + +#: ../../user_guide/psi.rst:155 +msgid "0.018s" +msgstr "" + +#: ../../user_guide/psi.rst:157 +msgid "25.434s" +msgstr "" + +#: ../../user_guide/psi.rst:157 +msgid "100.68s" +msgstr "" + +#: ../../user_guide/psi.rst:157 +msgid "415.94s" +msgstr "" + +#: ../../user_guide/psi.rst:157 +msgid "1672.21s" +msgstr "" + +#: ../../user_guide/psi.rst:162 +msgid "Security Tips" +msgstr "" + +#: ../../user_guide/psi.rst:164 +msgid "" +"Warning: `KKRT16 `_ is semi-honest" +" PSI protocols, and may be attacked in malicious model. We recommend " +"using KKRT16 PSI protocol as one-way PSI, i.e., one party gets the final " +"intersection result." +msgstr "" + +#~ msgid "" +#~ "The :psi_code_host:`ECDH-PSI " +#~ "` is favorable if" +#~ " the bandwidth is the bottleneck. If" +#~ " the computing is the bottleneck, you" +#~ " should try the BaRK-OPRF based " +#~ "PSI :psi_code_host:`KKRT-PSI " +#~ "`." +#~ msgstr "" + +#~ msgid "" +#~ ":psi_code_host:`DH-PSI benchmark code " +#~ "`" +#~ msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi_v2.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi_v2.po new file mode 100644 index 00000000..7e97fe5f --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi_v2.po @@ -0,0 +1,207 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-05 21:02+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/psi_v2.rst:2 +msgid "PSI v2 QuickStart" +msgstr "PSI v2 快速入门" + +#: ../../user_guide/psi_v2.rst:5 +msgid "Release Docker" +msgstr "Docker镜像" + +#: ../../user_guide/psi_v2.rst:7 +msgid "" +"Check official release docker image at `dockerhub " +"`_. We also have mirrors" +" at Alibaba Cloud: `secretflow-registry.cn-" +"hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`." +msgstr "" +"我们提供了发行镜像 `dockerhub `_." +" 还有阿里云镜像: `secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow" +"/psi-anolis8`." + +#: ../../user_guide/psi_v2.rst:11 +msgid "Prepare data and config" +msgstr "准备数据和配置" + +#: ../../user_guide/psi_v2.rst:13 +msgid "Please check details of configs at :ref:`here `." +msgstr "细节请参考: :ref:`here ` 。" + +#: ../../user_guide/psi_v2.rst:15 +msgid "" +"To launch PSI, please check LaunchConfig at " +":doc:`/reference/launch_config`." +msgstr "要启动PSI, 可以查看 :doc:`/reference/launch_config` 。" + +#: ../../user_guide/psi_v2.rst:18 ../../user_guide/psi_v2.rst:123 +msgid "receiver.config" +msgstr "" + +#: ../../user_guide/psi_v2.rst:68 ../../user_guide/psi_v2.rst:125 +msgid "sender.config" +msgstr "" + +#: ../../user_guide/psi_v2.rst:118 +msgid "You need to prepare following files:" +msgstr "需要准备以下文件:" + +#: ../../user_guide/psi_v2.rst:121 +msgid "File Name" +msgstr "" + +#: ../../user_guide/psi_v2.rst:121 +msgid "Location" +msgstr "" + +#: ../../user_guide/psi_v2.rst:121 +msgid "Description" +msgstr "" + +#: ../../user_guide/psi_v2.rst:123 +msgid "/tmp/receiver/receiver.config" +msgstr "" + +#: ../../user_guide/psi_v2.rst:123 +msgid "Config for receiver." +msgstr "" + +#: ../../user_guide/psi_v2.rst:125 +msgid "/tmp/sender/sender.config" +msgstr "" + +#: ../../user_guide/psi_v2.rst:125 +msgid "Config for sender." +msgstr "" + +#: ../../user_guide/psi_v2.rst:127 +msgid "receiver_input.csv" +msgstr "" + +#: ../../user_guide/psi_v2.rst:127 +msgid "/tmp/receiver/receiver_input.config" +msgstr "" + +#: ../../user_guide/psi_v2.rst:127 +msgid "Input for receiver. Make sure the file contains two id keys - id0 and id1." +msgstr "receiver方输入,请确保文件有id0列和id1列。" + +#: ../../user_guide/psi_v2.rst:129 +msgid "sender_input.csv" +msgstr "" + +#: ../../user_guide/psi_v2.rst:129 +msgid "/tmp/sender/sender_input.config" +msgstr "" + +#: ../../user_guide/psi_v2.rst:129 +msgid "Input for sender. Make sure the file contains two id keys - id0 and id1." +msgstr "sender方输入,请确保文件有id0列和id1列。" + +#: ../../user_guide/psi_v2.rst:134 +msgid "Run PSI" +msgstr "运行PSI" + +#: ../../user_guide/psi_v2.rst:136 +msgid "In the first terminal, run the following command::" +msgstr "在第一个终端,运行以下命令:" + +#: ../../user_guide/psi_v2.rst:141 +msgid "In the other terminal, run the following command simultaneously::" +msgstr "在另一个终端,运行以下命令:" + +#: ../../user_guide/psi_v2.rst:147 +msgid "Building from source" +msgstr "源码构建" + +#: ../../user_guide/psi_v2.rst:149 +msgid "You could build psi binary with bazel::" +msgstr "可以使用bazel编译PSI二进制:" + +#: ../../user_guide/psi_v2.rst:154 +msgid "Then use binary with::" +msgstr "然后::" + +#: ../../user_guide/psi_v2.rst:159 +msgid "More examples" +msgstr "更多示例" + +#: ../../user_guide/psi_v2.rst:161 +msgid "" +"Please read `README " +"`_, " +"Please check more demo configs at `psi config " +"`_." +msgstr "" +"请阅读 `README " +"`_, " +"更多demo配置可以查看 `psi config " +"`_." + +#: ../../user_guide/psi_v2.rst:165 +msgid "Ub PSI" +msgstr "非平衡PSI" + +#: ../../user_guide/psi_v2.rst:167 +msgid "" +"To launch PSI, please check LaunchConfig at " +":doc:`/reference/launch_config` and :ref:`here `." +msgstr "要启动非平衡PSI,请参考 :doc:`/reference/launch_config` 和 :ref:`here `." + +#: ../../user_guide/psi_v2.rst:169 +msgid "" +"Please read `examples " +"`_." +msgstr "" +"请参考 `示例 " +"`_." + +#: ../../user_guide/psi_v2.rst:171 +msgid "Example configs are:" +msgstr "配置示例:" + +#: ../../user_guide/psi_v2.rst:173 +msgid "server" +msgstr "" + +#: ../../user_guide/psi_v2.rst:174 +msgid "https://github.com/secretflow/psi/tree/main/examples/psi/config/ecdh_server_offline.json" +msgstr "" + +#: ../../user_guide/psi_v2.rst:175 +msgid "https://github.com/secretflow/psi/tree/main/examples/psi/config/ecdh_server_online.json" +msgstr "" + +#: ../../user_guide/psi_v2.rst:177 +msgid "client" +msgstr "" + +#: ../../user_guide/psi_v2.rst:178 +msgid "https://github.com/secretflow/psi/tree/main/examples/psi/config/ecdh_client_offline.json" +msgstr "" + +#: ../../user_guide/psi_v2.rst:179 +msgid "https://github.com/secretflow/psi/tree/main/examples/psi/config/ecdh_client_online.json" +msgstr "" + +#~ msgid "" +#~ "请阅读 `例子 " +#~ "`_." +#~ msgstr "" + diff --git a/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi_v2_benchmark.po b/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi_v2_benchmark.po new file mode 100644 index 00000000..f552e9cd --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/user_guide/psi_v2_benchmark.po @@ -0,0 +1,113 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-27 15:24+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../user_guide/psi_v2_benchmark.md:1 +msgid "PSI V2 Benchmark" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:3 +msgid "" +"This document will introduce the PSI V2 Benchmark. It uses the PSI V2 " +"version of the interface." +msgstr "" +"本文介绍了PSI V2 Benchmark。使用PSI V2 " +"接口。" + +#: ../../user_guide/psi_v2_benchmark.md:4 +msgid "Building from source" +msgstr "源码构建" + +#: ../../user_guide/psi_v2_benchmark.md:12 +msgid "" +"If the building is successful, you will find an executable file named " +"`main` in the 'bazel-bin/psi' directory. We will use `./main` file, " +"combined with config file to run different PSI protocols. Such as:" +msgstr "" +"如果构建成功,可以在 'bazel-bin/psi' 找到 `main` 文件。" +"可以使用 `./main` 搭配不同的配置文件来运行不同的PSI协议。如: " + +#: ../../user_guide/psi_v2_benchmark.md:19 +msgid "Generate Data" +msgstr "生成数据" + +#: ../../user_guide/psi_v2_benchmark.md:22 +msgid "" +"In order to measure the performance of different PSI protocols under " +"different data scales, we need to generate dummy data through " +"[generate_psi.py](https://github.com/secretflow/secretflow/blob/main/docs/developer/benchmark/resources/generate_psi.py)" +msgstr "" +"为了测量PSI在不同数据规模下的性能,我们需要生成一些测试数据。" +"可以使用脚本 " +"[generate_psi.py](https://github.com/secretflow/secretflow/blob/main/docs/developer/benchmark/resources/generate_psi.py)" + +#: ../../user_guide/psi_v2_benchmark.md:30 +msgid "Prepare config file" +msgstr "准备配置文件" + +#: ../../user_guide/psi_v2_benchmark.md:32 +msgid "We use the config file to specify different PSI protocols and input data." +msgstr "我们使用配置文件来指定协议,输入输出等。" + +#: ../../user_guide/psi_v2_benchmark.md:34 +msgid "sender.config" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:83 +msgid "receiver.config" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:132 +msgid "Run PSI with docker" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:134 +msgid "" +"In order to measure the PSI V2 benchmark under different machine " +"configurations and network configurations, we use two dockers to act as " +"sender and receiver respectively." +msgstr "" +"要测量不同机器配置和网络设定下的性能,我们使用两个镜像来扮演 sender 和 receiver." + +#: ../../user_guide/psi_v2_benchmark.md:137 +msgid "**alice**" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:156 +msgid "**bob**" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:174 +msgid "Limit bandwidth and latency" +msgstr "限制带宽和延迟" + +#: ../../user_guide/psi_v2_benchmark.md:187 +msgid "Benchmark" +msgstr "" + +#: ../../user_guide/psi_v2_benchmark.md:189 +msgid "Here we show the PSI V2 Benchmark measured as above." +msgstr "这里我们展示了一个可能的PSI V2 Benchmark结果" + +#: ../../user_guide/psi_v2_benchmark.md:190 +msgid "" +"The default time unit is seconds, `m` represents minutes, and `h` " +"represents hours." +msgstr "" +"默认的单位是秒,`m` 表示分钟, and `h` " +"表示小时。" diff --git a/docs/locale/zh_CN/LC_MESSAGES/whatsnew.po b/docs/locale/zh_CN/LC_MESSAGES/whatsnew.po new file mode 100644 index 00000000..25b39afb --- /dev/null +++ b/docs/locale/zh_CN/LC_MESSAGES/whatsnew.po @@ -0,0 +1,285 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2024, SecretFlow authors +# This file is distributed under the same license as the SecretFlow PSI +# Library package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: SecretFlow PSI Library \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-12-26 20:09+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.15.0\n" + +#: ../../whatsnew.rst:2 +msgid "Release notes" +msgstr "" + +#: ../../../RELEASE.md:1 +msgid "RELEASE" +msgstr "" + +#: ../../../RELEASE.md:3 +msgid "NOTE:" +msgstr "" + +#: ../../../RELEASE.md:5 +msgid "`[Feature]` prefix for new features." +msgstr "" + +#: ../../../RELEASE.md:6 +msgid "`[Bugfix]` prefix for bug fixes." +msgstr "" + +#: ../../../RELEASE.md:7 +msgid "`[API]` prefix for API changes." +msgstr "" + +#: ../../../RELEASE.md:8 +msgid "`[Improvement]` prefix for implementation improvement." +msgstr "" + +#: ../../../RELEASE.md:10 +msgid "v0.5.0.dev241107" +msgstr "" + +#: ../../../RELEASE.md:12 +msgid "`[API]` delete legacy ub psi function." +msgstr "" + +#: ../../../RELEASE.md:13 +msgid "`[API]` output csv null_rep can be specified." +msgstr "" + +#: ../../../RELEASE.md:14 +msgid "`[Feature]` join can be done with one receiver." +msgstr "" + +#: ../../../RELEASE.md:15 +msgid "`[Feature]` join can be done with ub psi protocol." +msgstr "" + +#: ../../../RELEASE.md:17 +msgid "v0.4.0.dev240801" +msgstr "" + +#: ../../../RELEASE.md:19 +msgid "[Bugfix] Fix MacOS and arm build." +msgstr "" + +#: ../../../RELEASE.md:21 +msgid "v0.4.0.dev240731" +msgstr "" + +#: ../../../RELEASE.md:23 +msgid "[Improvement] Port APSI again." +msgstr "" + +#: ../../../RELEASE.md:24 +msgid "[Feature] Add Bucketized APSI." +msgstr "" + +#: ../../../RELEASE.md:25 +msgid "[API] Remove SealPIR." +msgstr "" + +#: ../../../RELEASE.md:27 +msgid "v0.4.0.dev240521" +msgstr "" + +#: ../../../RELEASE.md:29 +msgid "[API] remove BC22 protocol" +msgstr "" + +#: ../../../RELEASE.md:31 +msgid "v0.4.0.dev240517" +msgstr "" + +#: ../../../RELEASE.md:33 +msgid "[Improvement] upgrade yacl to 0.4.5b0." +msgstr "" + +#: ../../../RELEASE.md:35 +msgid "v0.4.0.dev240514" +msgstr "" + +#: ../../../RELEASE.md:37 +msgid "[API] add entrypoint for docker file." +msgstr "" + +#: ../../../RELEASE.md:38 +msgid "[API] allow passing config JSON directly to main." +msgstr "" + +#: ../../../RELEASE.md:39 +msgid "[Bugfix] fix ic mode." +msgstr "" + +#: ../../../RELEASE.md:40 +msgid "[Bugfix] fix RR22, SealPIR and APSI." +msgstr "" + +#: ../../../RELEASE.md:42 +msgid "v0.4.0.dev240401" +msgstr "" + +#: ../../../RELEASE.md:44 +msgid "[Improvement] upgrade download uri of xz." +msgstr "" + +#: ../../../RELEASE.md:46 +msgid "v0.4.0.dev240329" +msgstr "" + +#: ../../../RELEASE.md:48 +msgid "[Improvement] upgrade yacl to 0.4.4b3." +msgstr "" + +#: ../../../RELEASE.md:50 +msgid "v0.3.0beta" +msgstr "" + +#: ../../../RELEASE.md:52 +msgid "[Improvement] add uuid in system temp folder." +msgstr "" + +#: ../../../RELEASE.md:53 +msgid "[Improvement] use arrow csv reader in pir." +msgstr "" + +#: ../../../RELEASE.md:54 +msgid "[Bugfix] fix typo in psi config check." +msgstr "" + +#: ../../../RELEASE.md:56 +msgid "v0.3.0.dev240304" +msgstr "" + +#: ../../../RELEASE.md:58 +msgid "[API] expose ic_mode in RunLegacyPsi api" +msgstr "" + +#: ../../../RELEASE.md:60 +msgid "v0.3.0.dev240222" +msgstr "" + +#: ../../../RELEASE.md:62 +msgid "[API] expose PIR API." +msgstr "" + +#: ../../../RELEASE.md:64 +msgid "v0.3.0.dev240219" +msgstr "" + +#: ../../../RELEASE.md:66 +msgid "[Feature] add ecdh logger for debug purposes." +msgstr "" + +#: ../../../RELEASE.md:67 +msgid "[API] modify repo structure." +msgstr "" + +#: ../../../RELEASE.md:69 +msgid "v0.2.0.dev240123" +msgstr "" + +#: ../../../RELEASE.md:71 +msgid "[Feature] add RFC9380 25519 elligator2 hash_to_curve." +msgstr "" + +#: ../../../RELEASE.md:72 +msgid "[Feature] add malicious vole psi." +msgstr "" + +#: ../../../RELEASE.md:73 +msgid "[API] expose ub psi in PSI v2 API." +msgstr "" + +#: ../../../RELEASE.md:74 +msgid "[Improvement] Modify buffer size in sort cmd." +msgstr "" + +#: ../../../RELEASE.md:75 +msgid "[Bugfix] Fix SimpleShuffledBatchProvider." +msgstr "" + +#: ../../../RELEASE.md:76 +msgid "[Bugfix] Fix flakiness in psi_test." +msgstr "" + +#: ../../../RELEASE.md:77 +msgid "[Bugfix] Fix race condition in rr22." +msgstr "" + +#: ../../../RELEASE.md:79 +msgid "v0.2.0.dev231228" +msgstr "" + +#: ../../../RELEASE.md:81 +msgid "[Bugfix] Fix RR22 race condition." +msgstr "" + +#: ../../../RELEASE.md:82 +msgid "[Improvement] modify sort buffer size." +msgstr "" + +#: ../../../RELEASE.md:84 +msgid "v0.2.0.dev231221" +msgstr "" + +#: ../../../RELEASE.md:86 +msgid "[API] Rename check_duplicates to skip_duplicates_check." +msgstr "" + +#: ../../../RELEASE.md:87 +msgid "[API] Rename sort_output to disable_alignment." +msgstr "" + +#: ../../../RELEASE.md:88 +msgid "" +"[Feature] Support left join, right join and full join. The behavior of " +"difference is modified." +msgstr "" + +#: ../../../RELEASE.md:89 +msgid "[Feature] Skip duplicate key check if recovery checkpoint exists." +msgstr "" + +#: ../../../RELEASE.md:90 +msgid "[Bugfix] Fix duplicate key check." +msgstr "" + +#: ../../../RELEASE.md:91 +msgid "[Bugfix] Fix SyncWait." +msgstr "" + +#: ../../../RELEASE.md:93 +msgid "v0.1.0beta" +msgstr "" + +#: ../../../RELEASE.md:95 +msgid "[API] Add PSI v2 API." +msgstr "" + +#: ../../../RELEASE.md:96 +msgid "[Feature] Add RR22 protocol." +msgstr "" + +#: ../../../RELEASE.md:97 +msgid "[Feature] Support recovery from failure in v2 API." +msgstr "" + +#: ../../../RELEASE.md:98 +msgid "[Feature] Support inner join in v2 API." +msgstr "" + +#: ../../../RELEASE.md:99 +msgid "[Feature] Migrate ECDH, KKRT, RR22 protocol in v2 API." +msgstr "" + diff --git a/docs/reference/launch_config.md b/docs/reference/launch_config.md index 5563fa55..0608abef 100644 --- a/docs/reference/launch_config.md +++ b/docs/reference/launch_config.md @@ -9,7 +9,21 @@ Please check psi.v2.PsiConfig and psi.v2.UbPsiConfig at **PSI v2 Configuration** - Messages - [LaunchConfig](#launchconfig) - + + + + + + +- Messages + - [AllocatedPorts](#allocatedports) + - [ClusterDefine](#clusterdefine) + - [Party](#party) + - [Port](#port) + - [Service](#service) + - [TaskInputConfig](#taskinputconfig) + - [TaskInputConfig.SfPsiConfigMapEntry](#taskinputconfigsfpsiconfigmapentry) + @@ -20,7 +34,7 @@ Please check psi.v2.PsiConfig and psi.v2.UbPsiConfig at **PSI v2 Configuration** - [PartyProto](#partyproto) - [RetryOptionsProto](#retryoptionsproto) - [SSLOptionsProto](#ssloptionsproto) - + @@ -59,21 +73,103 @@ Please check psi.v2.PsiConfig and psi.v2.UbPsiConfig at **PSI v2 Configuration** ## Messages -### ContextDescProto -Configuration for link config. +### AllocatedPorts +AllocatedPorts represents allocated ports for pod. + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| ports | [repeated Port](#port) | Allocated ports. | + + + + +### ClusterDefine +ClusterDefine represents the information of all parties. + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| parties | [repeated Party](#party) | Basic information of all parties. | +| self_party_idx | [ int32](#int32) | index of self party. | +| self_endpoint_idx | [ int32](#int32) | index of self endpoint. | + + + + +### Party +Party represents the basic information of the party. + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| name | [ string](#string) | Name of party. | +| role | [ string](#string) | role carried by party. Examples: client, server... | +| services | [repeated Service](#service) | List of services exposed by pod. | + + + + +### Port +Port represents an allocated port for pod. + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| name | [ string](#string) | Each named port in a pod must have a unique name. | +| port | [ int32](#int32) | Number of port allocated for pod. | +| scope | [ string](#string) | Scope of port. Must be Cluster,Domain,Local. Defaults to "Local". +optional | +| protocol | [ string](#string) | Protocol for port. Must be HTTP,GRPC. Defaults to "HTTP". +optional | + + + -'recv time' is the max time that a party will wait for a given event. -for example: -``` - begin recv end recv -|--------|-------recv-time----------|------------------| alice's timeline +### Service +Service represents the service address corresponding to the port. - begin send end send -|-----busy-work-------------|-------------|------------| bob's timeline -``` -in above case, when alice begins recv for a specific event, bob is still -busy doing its job, when alice's wait time exceed wait_timeout_ms, it raise -exception, although bob now is starting to send data. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| port_name | [ string](#string) | Name of port. | +| endpoints | [repeated string](#string) | Endpoint list corresponding to the port. | + + + + +### TaskInputConfig + + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| sf_psi_config_map | [map TaskInputConfig.SfPsiConfigMapEntry](#taskinputconfigsfpsiconfigmapentry) | none | + + + + +### TaskInputConfig.SfPsiConfigMapEntry + + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| key | [ string](#string) | none | +| value | [ psi.LaunchConfig](#psilaunchconfig) | none | + + + + +## Enums + + + + + +## Messages + + +### ContextDescProto +Configuration for link config. | Field | Type | Description | @@ -82,8 +178,20 @@ exception, although bob now is starting to send data. | parties | [repeated PartyProto](#partyproto) | party description, describes the world. | | connect_retry_times | [ uint32](#uint32) | connect to mesh retry time. | | connect_retry_interval_ms | [ uint32](#uint32) | connect to mesh retry interval. | -| recv_timeout_ms | [ uint64](#uint64) | recv timeout in milliseconds. so for long time work(that one party may wait for the others for very long time), this value should be changed accordingly. | -| http_max_payload_size | [ uint32](#uint32) | http max payload size, if a single http request size is greater than this limit, it will be unpacked into small chunks then reassembled. This field does affect performance. Please choose wisely. | +| recv_timeout_ms | [ uint64](#uint64) | recv timeout in milliseconds. + +'recv time' is the max time that a party will wait for a given event. for example: + + begin recv end recv |--------|-------recv-time----------|------------------| alice's timeline + + begin send end send |-----busy-work-------------|-------------|------------| bob's timeline + +in above case, when alice begins recv for a specific event, bob is still busy doing its job, when alice's wait time exceed wait_timeout_ms, it raise exception, although bob now is starting to send data. + +so for long time work(that one party may wait for the others for very long time), this value should be changed accordingly. | +| http_max_payload_size | [ uint32](#uint32) | http max payload size, if a single http request size is greater than this limit, it will be unpacked into small chunks then reassembled. + +This field does affect performance. Please choose wisely. | | http_timeout_ms | [ uint32](#uint32) | a single http request timetout. | | throttle_window_size | [ uint32](#uint32) | throttle window size for channel. if there are more than limited size messages are flying, `SendAsync` will block until messages are processed or throw exception after wait for `recv_timeout_ms` | | brpc_channel_protocol | [ string](#string) | BRPC client channel protocol. | diff --git a/docs/reference/pir_config.md b/docs/reference/pir_config.md index 5dc2498a..097ac460 100644 --- a/docs/reference/pir_config.md +++ b/docs/reference/pir_config.md @@ -8,7 +8,7 @@ - [ApsiReceiverConfig](#apsireceiverconfig) - [ApsiSenderConfig](#apsisenderconfig) - [PirResultReport](#pirresultreport) - + @@ -36,6 +36,7 @@ | params_file | [ string](#string) | Path to a JSON file describing the parameters to be used by the sender. If not set, receiver will ask sender, which results in additional communication. | | experimental_enable_bucketize | [ bool](#bool) | Must be same as sender config. | | experimental_bucket_cnt | [ uint32](#uint32) | Must be same as sender config. | +| query_batch_size | [ uint32](#uint32) | The number of query in a batch. default 1. | @@ -62,6 +63,9 @@ for details. | experimental_enable_bucketize | [ bool](#bool) | [experimental] Whether to split data in buckets and Each bucket would be a seperate SenderDB. If set, experimental_bucket_folder must be a valid folder. | | experimental_bucket_cnt | [ uint32](#uint32) | [experimental] The number of bucket to fit data. | | experimental_bucket_folder | [ string](#string) | [experimental] Folder to save bucketized small csv files and db files. | +| experimental_db_generating_process_num | [ int32](#int32) | [experimental] The number of processes to use for generating db. | +| source_file | [ string](#string) | Source file used to genenerate sender db. Currently only support csv file. | +| experimental_bucket_group_cnt | [ int32](#int32) | [experimental] The number of group of bucket, each group has a db_file, default 1024. | diff --git a/docs/reference/psi_config.md b/docs/reference/psi_config.md index dd7b8c45..35d04b70 100644 --- a/docs/reference/psi_config.md +++ b/docs/reference/psi_config.md @@ -11,13 +11,13 @@ - [MemoryPsiConfig](#memorypsiconfig) - [OutputParams](#outputparams) - [PsiResultReport](#psiresultreport) - + - Enums - [CurveType](#curvetype) - [PsiType](#psitype) - + - [Scalar Value Types](#scalar-value-types) @@ -30,6 +30,12 @@ ### BucketPsiConfig +``` + Deprecation notice. + This message is scheduled for removal in a future release. + Use psi.v2.PsiConfig instead. +``` + The Bucket-psi configuration. ```python @@ -74,6 +80,10 @@ The input parameters of dp-psi. ### InputParams +``` + Deprecation notice. + This message is scheduled for removal in a future release. +``` The input parameters of psi. @@ -87,6 +97,11 @@ The input parameters of psi. ### MemoryPsiConfig +``` + Deprecation notice. + This message is scheduled for removal in a future release. +``` + The In-memory psi configuration. ```python @@ -113,6 +128,10 @@ The In-memory psi configuration. ### OutputParams +``` + Deprecation notice. + This message is scheduled for removal in a future release. +``` The output parameters of psi. @@ -132,6 +151,8 @@ The report of psi result. | ----- | ---- | ----------- | | original_count | [ int64](#int64) | The data count of input. | | intersection_count | [ int64](#int64) | The count of intersection. Get `-1` when self party can not get result. | +| original_key_count | [ int64](#int64) | none | +| intersection_key_count | [ int64](#int64) | none | @@ -155,23 +176,29 @@ The specified elliptic curve cryptography used in psi. ### PsiType +``` + Deprecation notice. + This enum is scheduled for removal in a future release. + Use psi.v2.ProtocolConfig instead. +``` + The algorithm type of psi. | Name | Number | Description | | ---- | ------ | ----------- | | INVALID_PSI_TYPE | 0 | none | -| ECDH_PSI_2PC | 1 | DDH based PSI | -| KKRT_PSI_2PC | 2 | Efficient Batched Oblivious PRF with Applications to Private Set Intersection https://eprint.iacr.org/2016/799.pdf | +| ECDH_PSI_2PC | 1 | ``` NOTICED: No longer supported ``` DDH based PSI | +| KKRT_PSI_2PC | 2 | ``` NOTICED: No longer supported ``` Efficient Batched Oblivious PRF with Applications to Private Set Intersection https://eprint.iacr.org/2016/799.pdf | | ECDH_PSI_3PC | 4 | Multi-party PSI based on ECDH (Say A, B, C (receiver)) notice: two-party intersection cardinarlity leak (|A intersect B|) | | ECDH_PSI_NPC | 5 | Iterative running 2-party ecdh psi to get n-party PSI. Notice: two-party intersection leak | | KKRT_PSI_NPC | 6 | Iterative running 2-party kkrt psi to get n-party PSI. Notice: two-party intersection leak | -| ECDH_OPRF_UB_PSI_2PC_GEN_CACHE | 7 | ecdh-oprf 2-party Unbalanced-PSI Generate CACHE. | -| ECDH_OPRF_UB_PSI_2PC_TRANSFER_CACHE | 8 | ecdh-oprf 2-party Unbalanced-PSI transfer CACHE. | -| ECDH_OPRF_UB_PSI_2PC_OFFLINE | 9 | ecdh-oprf 2-party Unbalanced-PSI offline phase. | -| ECDH_OPRF_UB_PSI_2PC_ONLINE | 10 | ecdh-oprf 2-party Unbalanced-PSI online phase. | -| ECDH_OPRF_UB_PSI_2PC_SHUFFLE_ONLINE | 11 | ecdh-oprf 2-party Unbalanced-PSI with shuffling online phase. large set party get intersection result | +| ECDH_OPRF_UB_PSI_2PC_GEN_CACHE | 7 | ``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI Generate CACHE. | +| ECDH_OPRF_UB_PSI_2PC_TRANSFER_CACHE | 8 | ``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI transfer CACHE. | +| ECDH_OPRF_UB_PSI_2PC_OFFLINE | 9 | ``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI offline phase. | +| ECDH_OPRF_UB_PSI_2PC_ONLINE | 10 | ``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI online phase. | +| ECDH_OPRF_UB_PSI_2PC_SHUFFLE_ONLINE | 11 | ``` NOTICED: No longer supported ``` ecdh-oprf 2-party Unbalanced-PSI with shuffling online phase. large set party get intersection result | | DP_PSI_2PC | 12 | Differentially-Private PSI https://arxiv.org/pdf/2208.13249.pdf bases on ECDH-PSI, and provides: Differentially private PSI results. | -| RR22_FAST_PSI_2PC | 13 | Blazing Fast PSI https://eprint.iacr.org/2022/320.pdf two mode: fast mode or low communication mode | +| RR22_FAST_PSI_2PC | 13 | ``` NOTICED: No longer supported ``` Blazing Fast PSI https://eprint.iacr.org/2022/320.pdf two mode: fast mode or low communication mode | | RR22_LOWCOMM_PSI_2PC | 14 | none | | RR22_MALICIOUS_PSI_2PC | 15 | none | diff --git a/docs/reference/psi_v2_config.md b/docs/reference/psi_v2_config.md index 4fcf1894..82fc82b0 100644 --- a/docs/reference/psi_v2_config.md +++ b/docs/reference/psi_v2_config.md @@ -7,16 +7,18 @@ - Messages - [DebugOptions](#debugoptions) - [EcdhConfig](#ecdhconfig) + - [InputAttr](#inputattr) - [InternalRecoveryRecord](#internalrecoveryrecord) - [IoConfig](#ioconfig) - [KkrtConfig](#kkrtconfig) + - [OutputAttr](#outputattr) - [ProtocolConfig](#protocolconfig) - [PsiConfig](#psiconfig) - [RecoveryCheckpoint](#recoverycheckpoint) - [RecoveryConfig](#recoveryconfig) - [Rr22Config](#rr22config) - [UbPsiConfig](#ubpsiconfig) - + - Enums @@ -26,7 +28,7 @@ - [RecoveryCheckpoint.Stage](#recoverycheckpointstage) - [Role](#role) - [UbPsiConfig.Mode](#ubpsiconfigmode) - + - [Scalar Value Types](#scalar-value-types) @@ -67,6 +69,18 @@ Configs for ECDH protocol. | Field | Type | Description | | ----- | ---- | ----------- | | curve | [ psi.CurveType](#psicurvetype) | none | +| batch_size | [ uint64](#uint64) | If not set, use default value: 4096. | + + + + +### InputAttr + + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| keys_unique | [ bool](#bool) | Keys in input file are unique. If not set, use default value: false. | @@ -107,6 +121,17 @@ Configs for KKRT protocol +### OutputAttr + + + +| Field | Type | Description | +| ----- | ---- | ----------- | +| csv_null_rep | [ string](#string) | Null representation in output csv file. If not set, use default value: "NULL". | + + + + ### ProtocolConfig Any items related to PSI protocols. @@ -285,6 +310,8 @@ The output of right side is | advanced_join_type | [ PsiConfig.AdvancedJoinType](#psiconfigadvancedjointype) | none | | left_side | [ Role](#role) | Required if advanced_join_type is ADVANCED_JOIN_TYPE_LEFT_JOIN or ADVANCED_JOIN_TYPE_RIGHT_JOIN. | | check_hash_digest | [ bool](#bool) | Check if hash digest of keys from parties are equal to determine whether to early-stop. | +| input_attr | [ InputAttr](#inputattr) | Input attributes. | +| output_attr | [ OutputAttr](#outputattr) | Output attributes. | @@ -297,7 +324,7 @@ Save some critical information for future recovery. | ----- | ---- | ----------- | | stage | [ RecoveryCheckpoint.Stage](#recoverycheckpointstage) | Stage of PSI. | | config | [ PsiConfig](#psiconfig) | A copy of origin PSI config. | -| input_hash_digest | [ string](#string) | Hash digest of input keys. | +| input_hash_digest | [ bytes](#bytes) | Hash digest of input keys. | | ecdh_dual_masked_item_self_count | [ uint64](#uint64) | Saved dual masked item count from self originally. PROTOCOL_ECDH only. | | ecdh_dual_masked_item_peer_count | [ uint64](#uint64) | Saved dual masked item count from peer originally. PROTOCOL_ECDH only. | | parsed_bucket_count | [ uint64](#uint64) | Saved parsed bucket count. PROTOCOL_KKRT and PROTOCOL_RR22 only. | @@ -350,6 +377,10 @@ config for unbalanced psi. | disable_alignment | [ bool](#bool) | It true, output is not promised to be aligned. Valid if both server_get_result and client_get_result are true. | | output_config | [ IoConfig](#ioconfig) | Required for MODE_ONLINE and MODE_FULL. | | debug_options | [ DebugOptions](#debugoptions) | Logging level. | +| advanced_join_type | [ PsiConfig.AdvancedJoinType](#psiconfigadvancedjointype) | none | +| left_side | [ Role](#role) | Required if advanced_join_type is ADVANCED_JOIN_TYPE_LEFT_JOIN or ADVANCED_JOIN_TYPE_RIGHT_JOIN. | +| input_attr | [ InputAttr](#inputattr) | Input attributes. | +| output_attr | [ OutputAttr](#outputattr) | Output attributes. | diff --git a/docs/requirements.txt b/docs/requirements.txt index 673bb04c..8cb811ac 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,16 @@ -nbsphinx==0.8.9 +myst-parser==0.19.2 +rstcheck==6.2.4 sphinx==5.3.0 -myst-parser==0.18.1 -sphinx-intl==2.1.0 -pydata-sphinx-theme +nbsphinx==0.9.5 +sphinx-autobuild==2021.3.14 +pydata-sphinx-theme==0.15.4 +sphinx-markdown-parser==0.2.4 +sphinxcontrib-actdiag==3.0.0 +sphinxcontrib-blockdiag==3.0.0 +sphinxcontrib-nwdiag==2.0.0 +sphinxcontrib-seqdiag==3.0.0 +pytablewriter==0.64.2 +linkify-it-py==2.0.3 +sphinx_design==0.3.0 +sphinx-intl==2.2.0 +mdutils==1.6.0 diff --git a/docs/update_data.sh b/docs/update_data.sh index e91f110b..6c5f5ccc 100644 --- a/docs/update_data.sh +++ b/docs/update_data.sh @@ -1,5 +1,12 @@ #! /bin/bash +set -ex + +if ! [ -d $(pwd)/../../yacl/yacl ]; then + echo "yacl is not downloaded, please clone yacl(git@github.com:secretflow/yacl.git) repo in $(realpath $(pwd)/../../)" + exit 1 +fi + # psi_config_md.tmpl is adapted from https://github.com/pseudomuto/protoc-gen-doc/blob/master/examples/templates/grpc-md.tmpl. docker run --rm -v $(pwd)/reference/:/out \ -v $(pwd)/../:/protos \ @@ -12,7 +19,6 @@ docker run --rm -v $(pwd)/reference/:/out \ pseudomuto/protoc-gen-doc \ --doc_opt=/out/pir_config_md.tmpl,pir_config.md psi/proto/pir.proto - # psi_v2_config_md.tmpl is adapted from https://github.com/pseudomuto/protoc-gen-doc/blob/master/examples/templates/grpc-md.tmpl. docker run --rm -v $(pwd)/reference/:/out \ -v $(pwd)/../:/protos \ @@ -24,4 +30,5 @@ docker run --rm -v $(pwd)/reference/:/out \ -v $(pwd)/../:/protos \ -v $(pwd)/../../yacl/yacl:/protos/yacl \ pseudomuto/protoc-gen-doc \ - --doc_opt=/out/launch_config_md.tmpl,launch_config.md psi/proto/entry.proto yacl/link/link.proto + --doc_opt=/out/launch_config_md.tmpl,launch_config.md psi/proto/entry.proto psi/proto/kuscia.proto yacl/link/link.proto + diff --git a/docs/update_po.sh b/docs/update_po.sh new file mode 100644 index 00000000..dc6fc4ae --- /dev/null +++ b/docs/update_po.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +mkdir -p _build/gettext && +make gettext && +sphinx-intl update -p _build/gettext -l zh_CN && +echo "po files has been updated. Please update po files in locales folder." diff --git a/docs/user_guide/apsi_benchmark.md b/docs/user_guide/apsi_benchmark.md index e7ebca0e..9c7d693d 100644 --- a/docs/user_guide/apsi_benchmark.md +++ b/docs/user_guide/apsi_benchmark.md @@ -3,7 +3,7 @@ This document introduces the APSI Benchmark. ## Building from source ```bash -git clone -b v0.4.3.dev240919 git@github.com:secretflow/psi.git +git clone git@github.com:secretflow/psi.git cd psi bazel build //psi:main -c opt ``` @@ -19,10 +19,8 @@ To measure the performance of APSI protocols under different data scales, we nee ```python -# one million key-value pairs, each value's length is 32-byte, +# one million key-value pairs, each value's length is 32-byte, python examples/pir/apsi/test_data_creator.py --sender_size=1000000 --receiver_size=1 --intersection_size=1 --label_byte_count=32 -# 16 million key-value pairs, each value's length is 32-byte, -python examples/pir/apsi/test_data_creator.py --sender_size=16000000 --receiver_size=1 --intersection_size=1 --label_byte_count=32 ``` @@ -128,16 +126,16 @@ docker run -d -it --name "apsi_sender" \ --privileged=true \ --memory="64g" \ --entrypoint="bash" \ - secretflow/ubuntu-base-ci:latest + secretflow/release-ci:latest docker start apsi_sender docker exec -it apsi_sender bash ``` -Then run: +Then run: ```bash -# offline +# offline ./main --config $(pwd)/examples/pir/config/apsi_sender_setup.json # online ./main --config $(pwd)/examples/pir/config/apsi_sender_online.json diff --git a/docs/user_guide/faq.md b/docs/user_guide/faq.md deleted file mode 100644 index bfaa6e92..00000000 --- a/docs/user_guide/faq.md +++ /dev/null @@ -1,91 +0,0 @@ -# Frequently Asked Questions (FAQ) - -We will collect some popular questions from users and update this part promptly. - -## Config Issues - -1. In PSI config, what is difference of **broadcast_result** and **receiver**? Is it safe to turn on **broadcast_result**? - -In PSI protocols, the parties who are promised to receive the intersection are called **receiver**s, the other parties are called **sender**s. -When **broadcast_result** is turn on, **sender**s also receive the intersection. Both parties must agree on the value of **broadcast_result**, otherwise the program will stop. - -If **broadcast_result** is turn on, only **receiver**s and **sender**s could receive the result while any third parties could not see. So it is safe to set **broadcast_result** to true, if both **receiver**s and **sender**s wish to get the result. - -2. What is **IO_TYPE_UNSPECIFIED**? - -You must select a type as IoType. **IO_TYPE_UNSPECIFIED** is the default value of **IoType**, which is meaningless. At this moment, we only support **IO_TYPE_FILE_CSV**. - -3. What is **ADVANCED_JOIN_TYPE_UNSPECIFIED**? - -PSI protocols doesn‘t allow duplicates in ids of inputs. However, sometimes we may intend to have duplicates in ids and perform LEFT / RIGHT / FULL join following rules of SQL. This is called **AdvancedJoinType**. - -**ADVANCED_JOIN_TYPE_UNSPECIFIED** is default value of AdvancedJoinType, which means default implementation of PSI configs and duplicates is disallowed. If ids of inputs contains duplicates at this moment, the behavior is undefined. - -4. What is the recommendation value of bucket size? - -The default value is 2^20. You shouldn't set this value unless you have very limited computation resource. - -5. What is **disable_alignment**? - -If **disable_alignment** turns on, the intersection received by **receiver**s and **sender**s are not promised to be aligned(the order doesn't match) and save time. - -If any **AdvancedJoinType** is specified, aligement is promised due to implementation, **disable_alignment** is ignored. - -6. What is **RetryOptionsProto** in **ContextDescProto**? - -We have proper default values for all fields. You shouldn't set any values unless the network is pretty bad. - -## Feature Issues - -1. How to enable SSL? - -We support mTLS and you should provide proper **ContextDescProto**: - -- **enable_ssl** is enabled. -- In **client_ssl_opts**, set **verify_depth** and provide peer CA file with **ca_file_path** -- In **server_ssl_opts**, provide self certificate and private key file with **certificate_path** and **private_key_path** -- You must provide these settings at both sides. - -``` -{ - "psi_config": {}, - "link_config": { - "parties": [ - { - "id": "receiver", - "host": "127.0.0.1:5300" - }, - { - "id": "sender", - "host": "127.0.0.1:5400" - } - ], - "enable_ssl": true, - "client_ssl_opts": { - "verify_depth": 1, - "ca_file_path": "/path/to/peer/CA/file" - }, - "server_ssl_opts": { - "certificate_path": "/path/to/self/certificate/file", - "private_key_path": "/path/to/self/private/key/file" - } - }, - "self_link_party": "sender" -} -``` - -2. How to use recovery? - -We provide recovery feature in PSI v2. - -You have to provide a proper **RecoveryConfig**: - -- **enabled** set to true. -- **folder** is provided to store checkpoints. - -If a PSI task fails, just restart the task with the same config, the progress will resume. - -3. What is **Easy PSI**? Why and when to use **Easy PSI**? - -[Easy PSI](https://www.secretflow.org.cn/zh-CN/docs/easy-psi) is a standalone PSI product powered by this library. It provides a simple User Interface and utilize [Kuscia](https://www.secretflow.org.cn/docs/kuscia) to launch PSI binaries between both parties. - diff --git a/docs/user_guide/faq.rst b/docs/user_guide/faq.rst new file mode 100644 index 00000000..2724f9d5 --- /dev/null +++ b/docs/user_guide/faq.rst @@ -0,0 +1,91 @@ +Frequently Asked Questions (FAQ) +================================= + +We will collect some popular questions from users and update this part promptly. + +Config Issues +------------- + +1. In PSI config, what is difference of **broadcast_result** and **receiver**? Is it safe to turn on **broadcast_result**? + +In PSI protocols, the parties who are promised to receive the intersection are called **receiver**s, the other parties are called **sender**s. +When **broadcast_result** is turn on, **sender**s also receive the intersection. Both parties must agree on the value of **broadcast_result**, otherwise the program will stop. + +If **broadcast_result** is turn on, only **receiver**s and **sender**s could receive the result while any third parties could not see. So it is safe to set **broadcast_result** to true, if both **receiver**s and **sender**s wish to get the result. + +2. What is :ref:`IO_TYPE_UNSPECIFIED `? + +You must select a type as IoType. :ref:`IO_TYPE_UNSPECIFIED ` is the default value of :ref:`IoType `, which is meaningless. At this moment, we only support :ref:`IO_TYPE_FILE_CSV `. + +3. What is :ref:`ADVANCED_JOIN_TYPE_UNSPECIFIED `? + +PSI protocols doesn‘t allow duplicates in ids of inputs. However, sometimes we may intend to have duplicates in ids and perform LEFT / RIGHT / FULL join following rules of SQL. This is called :ref:`AdvancedJoinType `. + +:ref:`ADVANCED_JOIN_TYPE_UNSPECIFIED ` is same as :ref:`ADVANCED_JOIN_TYPE_INNER_JOIN `. + +4. What is the recommendation value of bucket size? + +The default value is 2^20. You shouldn't set this value unless you have very limited computation resource. + +5. What is :ref:`disable_alignment `? + +If :ref:`disable_alignment ` turns on, the intersection received by **receiver**s and **sender**s are not promised to be aligned(the order doesn't match) and save time. + + +6. What is :ref:`RetryOptionsProto ` in :ref:`ContextDescProto `? + +We have proper default values for all fields. You shouldn't set any values unless the network is pretty bad. +For more info, you can look up `here `_. + +Feature Issues +-------------- + +1. How to enable SSL? + +We support mTLS and you should provide proper :ref:`ContextDescProto `: + +- **enable_ssl** is enabled. +- In **client_ssl_opts**, set **verify_depth** and provide peer CA file with **ca_file_path** +- In **server_ssl_opts**, provide self certificate and private key file with **certificate_path** and **private_key_path** +- You must provide these settings at both sides. + +.. code-block:: + :caption: example.config + + { + "psi_config": {}, + "link_config": { + "parties": [ + { + "id": "receiver", + "host": "127.0.0.1:5300" + }, + { + "id": "sender", + "host": "127.0.0.1:5400" + } + ], + "enable_ssl": true, + "client_ssl_opts": { + "verify_depth": 1, + "ca_file_path": "/path/to/peer/CA/file" + }, + "server_ssl_opts": { + "certificate_path": "/path/to/self/certificate/file", + "private_key_path": "/path/to/self/private/key/file" + } + }, + "self_link_party": "sender" + } + +2. How to use recovery? + +We provide recovery feature in PSI v2. + +You have to provide a proper:ref:`RecoveryConfig `: + +- **enabled** set to true. +- **folder** is provided to store checkpoints. + +If a PSI task fails, just restart the task with the same config, the progress will resume. + diff --git a/docs/user_guide/pir.rst b/docs/user_guide/pir.rst index d67ee868..e7923919 100644 --- a/docs/user_guide/pir.rst +++ b/docs/user_guide/pir.rst @@ -14,13 +14,13 @@ Supported Protocols | APSI | Keyword PIR | Single Server | +----------------+-------------+---------------+ -At this moment, SealPIR is temporaily removed and will come back later. +At this moment, SealPIR is under development. Release Docker -------------- -Check official release docker image at `dockerhub `_. We also have mirrors at Alibaba Cloud: secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8. +Check official release docker image at `dockerhub `_. We also have mirrors at Alibaba Cloud: `secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`. Keyword PIR (APSI) @@ -29,8 +29,8 @@ Keyword PIR (APSI) Before Start >>>>>>>>>>>> -We provide a simple wrapper for famous `APSI `_ library. Please read the README of the repo carefully. -We are not going to discuss any content related to APSI further. +We provide a simple wrapper for famous `APSI `_ library. Please read the `README `_ of the repo carefully. +We are not going to discuss any content related to APSI further. Please check details of configs at :doc:`/reference/pir_config`. You are supposed to be aware of that we provided the **EXACT** the same API to APSI. @@ -40,26 +40,25 @@ The extra features brought are: 1. Use Yacl Link as communication layer. 2. Experimental bucketized PIR. -3. Turn server / client running mode to task mode. -4. Provide APIs for further integration. +3. Provide APIs for further integration. If you want to try a similar CLI like APSI, you could compile the source code by -.. code-block:: +.. code-block:: bash bazel build psi/wrapper/apsi/cli:receiver bazel build psi/wrapper/apsi/cli:sender -And run CLI like +And get CLI parameters like this: -.. code-block:: +.. code-block:: bash - ./bazel-bin/psi/wrapper/apsi/cli/sender + ./bazel-bin/psi/wrapper/apsi/cli/sender --help - ./bazel-bin/psi/wrapper/apsi/cli/receiver + ./bazel-bin/psi/wrapper/apsi/cli/receiver --help Prepare data and config @@ -71,9 +70,9 @@ For Senders (Servers), you must provide a input csv or a sender db file. An inpu CSV File """""""" -1. The csv file should looks like +The csv file should looks like -.. code-block:: +.. code-block:: None key,value Yb,Ii @@ -89,7 +88,7 @@ CSV File Please make sure: - Since version **0.4.0b0**, headers line is required. -- The first row must be headers, only **key** and **value**(optional) are allowed. +- The first row must be headers, only **key** and **value** are allowed. - The **key** column must be items(keys) - The **value** column must be labels(values), this column is optional. @@ -97,7 +96,7 @@ Please make sure: APSI Params File """""""""""""""" -We use the original APSI params. For details, please check `APSI PSIParams `_. +We use the original APSI params. For details, please check `APSI PSIParams `_ . For senders: An APSI params file must be provided with CSV files. If a sender db file is provided, the APSI params is not required and would be ignored. For receivers: The APSI params file is optional. If not provided, receivers will ask for senders. If provided, please make sure receivers and senders share @@ -105,69 +104,41 @@ the same APSI params file, otherwise error occurred. It's not easy to find a suitable APSI params file. So APSI provides some examples at `APSI parameters ` as well. +You can refer to `here `_ to choose the appropriate parameter file. -To launch PIR, please check LaunchConfig at :doc:`/reference/launch_config` and fillin **runtime_config.pir_config**. + +To launch PIR, please check LaunchConfig at :doc:`/reference/launch_config`, and +specific config: :ref:`sender config ` and :ref:`receiver config `. PIR Config """""""""" -1. Sender: Setup Stage. In this stage, sender generates sender db file with csv file. This stage is offline. +Sender: Setup Stage. In this stage, sender generates sender db file with csv file. This stage is offline. Since version **0.4.0b0**, the source csv file for db generating should be specified as **source_file**, and **db_file** -is used to specify db file. +is used to specify the generated db file. -.. code-block:: +.. code-block:: json :caption: apsi_sender_setup.json { "apsi_sender_config": { "source_file": "/tmp/db.csv", "params_file": "/tmp/1M-256-288.json", + "compress" : true, "sdb_out_file": "/tmp/sdb" } } -2. Sender: Online stage. In this stage, sender generates responses to receivers' queries. This stage is online. - -.. code-block:: - :caption: apsi_sender_online.json - - { - "apsi_sender_config": { - "db_file": "/tmp/sdb" - }, - "link_config": { - "parties": [ - { - "id": "sender", - "host": "127.0.0.1:5300" - }, - { - "id": "receiver", - "host": "127.0.0.1:5400" - - -.. code-block:: - :caption: apsi_sender_setup.json - - { - "apsi_sender_config": { - "source_file": "/tmp/db.csv", - "params_file": "/tmp/1M-256-288.json", - "sdb_out_file": "/tmp/sdb", - "save_db_only": true - } - } - - -2. Sender: Online stage. In this stage, sender generates responses to receivers' queries. This stage is online. +Sender: Online stage. In this stage, sender generates responses to receivers' queries. This stage is online. .. code-block:: :caption: apsi_sender_online.json { "apsi_sender_config": { - "db_file": "/tmp/sdb" + "compress" : true, + "db_file": "/tmp/sdb", }, "link_config": { "parties": [ @@ -184,9 +155,9 @@ is used to specify db file. "self_link_party": "sender" } -3. Receiver: Online stage. +Receiver: Online stage. -.. code-block:: +.. code-block:: json :caption: apsi_receiver.json { @@ -216,20 +187,24 @@ params_file field is optional. If not provided, receiver will ask sender for par Full Examples >>>>>>>>>>>>> -Please read https://github.com/secretflow/psi/tree/main/examples/pir/README.md -Please check more demo configs at https://github.com/secretflow/psi/tree/main/examples/pir/config +Please read `examples `_. +For more demo configs, you can check `here `_. Bucketized Mode >>>>>>>>>>>>>>> -Searching in a large sender db is costly. So can we search in a smaller db? A naive idea is: +Searching in a large sender db is costly. So we can split data into buckets. +The server knows which bucket the client is querying, but does not know which specific element: -1. In the setup stage, sender split data into buckets. Each bucket will generate a sender db. +In the setup stage, sender split data into buckets. Each bucket will generate a sender db. -2. In the online stage, receiver split query into subqueries. Each subquery only contains items residing in the same bucket. +In the online stage, receiver split query into subqueries. Each subquery only contains items residing in the same bucket. When receivers sends a subquery to the sender, bucket idx is also provided. -3. For each subquery, sender only search in the corresponding sender db for specific bucket. +For each subquery, sender only search in the corresponding sender db for specific bucket. -Bucketized Mode is experimental and for evaluation purposes only. +Assuming the query indindiscernibility degree is :math:`\text{ind_degree}`, and sender has :math:`\text{sender_data_rows}` rows, +then the number of buckets should be :math:`\text{bucket_num} = \text{sender_data_rows} / \text{ind_degree}`, you can set :ref:`experimental_bucket_cnt ` with :math:`\text{bucket_num}`. +If the client has :math:`\text{query_rows}` rows of data, the we know client has :math:`\text{query_rows_per_bucket} = \text{query_rows} / \text{bucket_num}` rows per bucket, +we can select :math:`\text{ind_degree}`-:math:`\text{query_rows_per_bucket}`-xxx.json as :ref:`params_file `. diff --git a/docs/user_guide/psi.rst b/docs/user_guide/psi.rst index af9b6cec..5a142f1d 100644 --- a/docs/user_guide/psi.rst +++ b/docs/user_guide/psi.rst @@ -1,5 +1,5 @@ -PSI v1 QuickStart -================= +PSI v1 QuickStart (Deprecated) +============================== Quick start with Private Set Intersection (PSI) V1 APIs. @@ -27,11 +27,11 @@ PSI :psi_code_host:`KKRT-PSI `. | `DP-PSI`_ | Semi-Honest | 2P | - | +---------------+--------------+--------------+--------------+ -MPC and PSI protocols are designed for specific Security model (or Threat Models). +MPC and PSI protocols are designed for specific Security model (or Threat Models). -Security model are widely considered to capture the capabilities of adversaries. +Security model are widely considered to capture the capabilities of adversaries. Adversaries of semi-honest model and malicious model are Semi-honest Adversary and -Malicious Adversary. +Malicious Adversary. - `Semi-honest Adversary `_ - `Malicious Adversary `_ @@ -82,17 +82,17 @@ Building from source You could build psi binary with bazel:: - bazel build psi/psi:main -c opt + bazel build psi/apps/psi_launcher:main -c opt Then use binary with:: - ./bazel-bin/psi/psi/main --config + ./bazel-bin/psi/apps/psi_launcher/main --config Benchmark ---------- -benchmark result without data load time +benchmark result without data load time ECDH PSI Benchmark >>>>>>>>>>>>>>>>>> @@ -127,7 +127,7 @@ cpu limited by docker(--cpu) KKRT PSI Benchmark >>>>>>>>>>>>>>>>>>> -All of our experiments use a single thread for each party. +All of our experiments use a single thread for each party. If the bandwidth is enough, the upstream could try to perform multi-threading optimizations @@ -161,6 +161,6 @@ Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz Security Tips ------------- -Warning: `KKRT16 `_ is semi-honest PSI protocols, +Warning: `KKRT16 `_ is semi-honest PSI protocols, and may be attacked in malicious model. We recommend using KKRT16 PSI protocol as one-way PSI, i.e., one party gets the final intersection result. diff --git a/docs/user_guide/psi_v2.rst b/docs/user_guide/psi_v2.rst index 3b75ddde..aaba636b 100644 --- a/docs/user_guide/psi_v2.rst +++ b/docs/user_guide/psi_v2.rst @@ -4,17 +4,18 @@ PSI v2 QuickStart Release Docker -------------- -Check official release docker image at `dockerhub `_. We also have mirrors at Alibaba Cloud: secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8. +Check official release docker image at `dockerhub `_. We also have mirrors at Alibaba Cloud: `secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8`. Prepare data and config ----------------------- -Please check details of configs at :doc:`/reference/psi_v2_config`. +Please check details of configs at :ref:`here `. -To launch PSI, please check LaunchConfig at :doc:`/reference/launch_config` and fillin **runtime_config.psi_config**. +To launch PSI, please check LaunchConfig at :doc:`/reference/launch_config`. -.. code-block:: + +.. code-block:: json :caption: receiver.config { @@ -64,7 +65,7 @@ To launch PSI, please check LaunchConfig at :doc:`/reference/launch_config` and } -.. code-block:: +.. code-block:: json :caption: sender.config { @@ -117,7 +118,7 @@ To launch PSI, please check LaunchConfig at :doc:`/reference/launch_config` and You need to prepare following files: +------------------------+------------------------------------------------+-------------------------------------------------------------------------------+ -| File Name | Location | Description | +| File Name | Location | Description | +========================+================================================+===============================================================================+ | receiver.config | /tmp/receiver/receiver.config | Config for receiver. | +------------------------+------------------------------------------------+-------------------------------------------------------------------------------+ @@ -134,12 +135,12 @@ Run PSI In the first terminal, run the following command:: - docker run -it --rm --network host --mount type=bind,source=/tmp/receiver,target=/root/receiver --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:0.1.0beta --config receiver/receiver.config + docker run -it --rm --network host --mount type=bind,source=/tmp/receiver,target=/root/receiver --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:latest --config receiver/receiver.config In the other terminal, run the following command simultaneously:: - docker run -it --rm --network host --mount type=bind,source=/tmp/sender,target=/root/sender --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:0.1.0beta --config sender/sender.config + docker run -it --rm --network host --mount type=bind,source=/tmp/sender,target=/root/sender --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --cap-add=NET_ADMIN --privileged=true secretflow-registry.cn-hangzhou.cr.aliyuncs.com/secretflow/psi-anolis8:latest --config sender/sender.config Building from source @@ -147,25 +148,25 @@ Building from source You could build psi binary with bazel:: - bazel build psi/psi:main -c opt + bazel build //psi/apps/psi_launcher:main -c opt Then use binary with:: - ./bazel-bin/psi/psi/main --config + ./bazel-bin/psi/apps/psi_launcher/main --config More examples ------------- -Please read https://github.com/secretflow/psi/tree/main/examples/psi/README.md -Please check more demo configs at https://github.com/secretflow/psi/tree/main/examples/psi/config +Please read `README `_, +Please check more demo configs at `psi config `_. Ub PSI ------ -To launch PSI, please check LaunchConfig at :doc:`/reference/launch_config` and fillin **runtime_config.ub_psi_config**. +To launch PSI, please check LaunchConfig at :doc:`/reference/launch_config` and :ref:`here `. -Please read https://github.com/secretflow/psi/tree/main/examples/psi/README.md +Please read `examples `_. Example configs are: diff --git a/examples/pir/README.md b/examples/pir/README.md index 351eb81d..b4bb3425 100644 --- a/examples/pir/README.md +++ b/examples/pir/README.md @@ -13,36 +13,38 @@ mv query.csv /tmp/query.csv cp examples/pir/apsi/parameters/100K-1-16.json /tmp/100K-1-16.json ``` -**NOTE** -1. The csv file should have head line, and the first column represents the key, and the second column which is optional represents the label. So first line of the csv file should be `key,value` or `key`. -2. We distinguish between labeled mode and unlabeled mode based on the number of columns in the db.csv file. If db.csv has 2 columns, the first column represents the key and the second column represents the value, and labeled mode is automatically enabled. Otherwise, it's unlabeled mode, which can be considered a non-balanced PSI. -3. In APSI, selecting appropriate parameters for databases of different scales is a challenging task. If you aim for optimal performance, seek support from professionals. - - +### NOTE +1. The csv file should have head line, and the first column represents the key, and the second column which is optional represents the label. +So first line of the csv file should be `key,value` or `key`. +2. We distinguish between labeled mode and unlabeled mode based on the number of columns in the db.csv file. If db.csv has 2 columns, +the first column represents the key and the second column represents the value, and labeled mode is automatically enabled. Otherwise, +it's unlabeled mode, which can be considered a non-balanced PSI. +3. In APSI, selecting appropriate parameters for databases of different scales is a challenging task. +If you aim for optimal performance, seek support from professionals. ## Sender Setup Stage At sender terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_sender_setup.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_sender_setup.json ``` **NOTE: Failure is possible. You may just retry.** -## Online stage. +## Online stage At sender terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_sender_online.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_sender_online.json ``` At receiver terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_receiver.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_receiver.json ``` ## Run Server with Full Mode (No Seperate Setup Stage) @@ -50,19 +52,20 @@ At receiver terminal, run At sender terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_sender_full.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_sender_full.json ``` At receiver terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_receiver.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_receiver.json ``` ## Advanced Topic : Bucketized Sender DB -**Please note that to support very large databases, such as those exceeding one billion rows, we offer the Bucketized Sender DB mode. However, this mode may result in reduced indistinguishability and may involve minimal leakage in server data distribution. Please evaluate whether the bucketing mode is suitable for your use case based on these considerations.** - +**Please note that to support very large databases, such as those exceeding one billion rows, we offer the Bucketized Sender DB mode. +However, this mode may result in reduced indistinguishability and may involve minimal leakage in server data distribution. +Please evaluate whether the bucketing mode is suitable for your use case based on these considerations.** ### Sender Setup Stage @@ -71,21 +74,21 @@ At sender terminal, run ```bash mkdir -p /tmp/apsi_sender_bucket/ -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_sender_setup_bucket.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_sender_setup_bucket.json ``` **NOTE: Failure is possible. You may just retry.** -### Online stage. +### Online stage At sender terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_sender_online_bucket.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_sender_online_bucket.json ``` At receiver terminal, run ```bash -./bazel-bin/psi/main --config $(pwd)/examples/pir/config/apsi_receiver_bucket.json +./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/pir/config/apsi_receiver_bucket.json ``` diff --git a/examples/pir/apsi/README.md b/examples/pir/apsi/README.md index 0e44a734..3a77cfbf 100644 --- a/examples/pir/apsi/README.md +++ b/examples/pir/apsi/README.md @@ -1 +1,3 @@ +# README + The files of this folder is copied from [APSI](https://github.com/microsoft/APSI). diff --git a/examples/pir/apsi/data/README.md b/examples/pir/apsi/data/README.md index 9148bb5b..0bce4116 100644 --- a/examples/pir/apsi/data/README.md +++ b/examples/pir/apsi/data/README.md @@ -1,11 +1,15 @@ +# Data + The files are generated with `examples/pir/apsi/test_data_creator.py` for testing purposes. 1. `labeled_db.csv` and `query_to_labeled_db.csv` are generated with -```bash -python test_data_creator.py --sender_size=1000 --receiver_size=10 --intersection_size=10 --label_byte_count=32 --item_byte_count=32 -``` + + ```bash + python test_data_creator.py --sender_size=1000 --receiver_size=10 --intersection_size=10 --label_byte_count=32 --item_byte_count=32 + ``` 2. `db.csv` and `query\.csv` are generated with -```bash -python test_data_creator.py --sender_size=1000 --receiver_size=10 --intersection_size=10 --label_byte_count=0 --item_byte_count=32 -``` + + ```bash + python test_data_creator.py --sender_size=1000 --receiver_size=10 --intersection_size=10 --label_byte_count=0 --item_byte_count=32 + ``` diff --git a/examples/psi/README.md b/examples/psi/README.md index 185d84c4..9327ec79 100644 --- a/examples/psi/README.md +++ b/examples/psi/README.md @@ -6,81 +6,80 @@ 1. Compile the binary -```bash -$ bazel build //psi:main -c opt -``` + ```bash + bazel build //psi:main -c opt + ``` 2. Generate test data -```bash -$ python examples/psi/generate_psi_data.py --receiver_item_cnt 1e6 \ - --sender_item_cnt 1e6 --intersection_cnt 8e4 --id_cnt 2 \ - --receiver_path /tmp/receiver_input.csv \ - --sender_path /tmp/sender_input.csv \ - --intersection_path /tmp/intersection.csv -``` + ```bash + $ python examples/psi/generate_psi_data.py --receiver_item_cnt 1e6 \ + --sender_item_cnt 1e6 --intersection_cnt 8e4 --id_cnt 2 \ + --receiver_path /tmp/receiver_input.csv \ + --sender_path /tmp/sender_input.csv \ + --intersection_path /tmp/intersection.csv + ``` 3. Generate recovery cache folder -```bash -$ mkdir -p /tmp/ecdh_sender_cache -$ mkdir -p /tmp/ecdh_receiver_cache - -``` + ```bash + mkdir -p /tmp/ecdh_sender_cache + mkdir -p /tmp/ecdh_receiver_cache + ``` 4. Launch PSI -In two terminals, + In two terminals, -For **receiver** terminal, + For **receiver** terminal, -```bash -$ ./bazel-bin/psi/main --config $(pwd)/examples/psi/config/ecdh_receiver_recovery.json -``` + ```bash + ./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/psi/config/ecdh_receiver_recovery.json + ``` -For **sender** terminal, + For **sender** terminal, -```bash -$ ./bazel-bin/psi/main --config $(pwd)/examples/psi/config/ecdh_sender_recovery.json -``` + ```bash + ./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/psi/config/ecdh_sender_recovery.json + ``` ## 2P UB PSI 1. Compile the binary -```bash -$ bazel build //psi:main -c opt -``` + ```bash + bazel build //psi:main -c opt + ``` 2. Generate test data -```bash -$ python examples/psi/generate_psi_data.py --receiver_item_cnt 1e3 \ - --sender_item_cnt 1e6 --intersection_cnt 1e2 --id_cnt 2 \ - --receiver_path /tmp/client_input.csv \ - --sender_path /tmp/server_input.csv \ - --intersection_path /tmp/intersection.csv -``` + ```bash + $ python examples/psi/generate_psi_data.py --receiver_item_cnt 1e3 \ + --sender_item_cnt 1e6 --intersection_cnt 1e2 --id_cnt 2 \ + --receiver_path /tmp/client_input.csv \ + --sender_path /tmp/server_input.csv \ + --intersection_path /tmp/intersection.csv + ``` 3. Generate Secret Key for Server -```bash -$ openssl rand 32 > /tmp/server_secret_key.key -``` + ```bash + openssl rand 32 > /tmp/server_secret_key.key + ``` 4. Launch UB PSI -In two terminals, + In two terminals, -For **server** terminal, + For **server** terminal, -```bash -$ ./bazel-bin/psi/main --config $(pwd)/examples/psi/config/ecdh_server_full.json -``` + ```bash + ./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/psi/config/ecdh_server_full.json + ``` -For **client** terminal, + For **client** terminal, -```bash -$ ./bazel-bin/psi/main --config $(pwd)/examples/psi/config/ecdh_client_full.json -``` + ```bash + ./bazel-bin/psi/apps/psi_launcher/main --config $(pwd)/examples/psi/config/ecdh_client_full.json + ``` diff --git a/experiment/pir/pps/README.md b/experiment/pir/pps/README.md index ee2289e2..09a7bc15 100644 --- a/experiment/pir/pps/README.md +++ b/experiment/pir/pps/README.md @@ -2,45 +2,55 @@ ## Overview -This repository contains the implementation of the Single Bits and Multi-Bits Private Information Retrieval (PIR) algorithms, which incorporate Puncturable Pseudorandom Sets (PPS) as described in the paper "Private Information Retrieval with Sublinear Online Time" (https://eprint.iacr.org/2019/1075.pdf) by Henry Corrigan-Gibbs and Dmitry Kogan. By utilizing PPS, these implementations achieve fast, sublinear-time database lookups without increasing the server-side storage requirements. The use of PPS enables the system to efficiently manage the complexity of data retrieval while ensuring the privacy of the client's queries, optimizing both Single Bits and Multi-Bits PIR functionalities. - - +This repository contains the implementation of the Single Bits and Multi-Bits Private Information Retrieval (PIR) algorithms, +which incorporate Puncturable Pseudorandom Sets (PPS) as described in the paper +"Private Information Retrieval with Sublinear Online Time" () by Henry Corrigan-Gibbs and Dmitry Kogan. +By utilizing PPS, these implementations achieve fast, sublinear-time database lookups without increasing the server-side storage requirements. +The use of PPS enables the system to efficiently manage the complexity of data retrieval while ensuring the privacy of the client's queries, +optimizing both Single Bits and Multi-Bits PIR functionalities. ## Implementation Details +This project only implements the dual-server model described in the paper. The implementation of Puncturable Pseudorandom Sets is based on +Chapter 2 of the paper, "Construction 4 (Puncturable pseudorandom set from puncturable PRF)." The implementation of the Single-Bits PIR protocol +follows "Construction 16 (Two-server PIR with sublinear online time)" from Chapter 3 of the original paper. +The implementation of the Multi-Bits PIR protocol is based on Chapter 4 and Appendix D's "Construction 44 (Multi-query offline/online PIR)." -This project only implements the dual-server model described in the paper. The implementation of Puncturable Pseudorandom Sets is based on Chapter 2 of the paper, "Construction 4 (Puncturable pseudorandom set from puncturable PRF)." The implementation of the Single-Bits PIR protocol follows "Construction 16 (Two-server PIR with sublinear online time)" from Chapter 3 of the original paper. The implementation of the Multi-Bits PIR protocol is based on Chapter 4 and Appendix D's "Construction 44 (Multi-query offline/online PIR)." - -**(Offline/online PIR)**. An offline/online PIR scheme is a tuple $\Pi$ = (**Setup**, **Hint**, **Query**, **Answer**, **Reconstruct**) of five efficient algorithms: +**(Offline/online PIR)**. An offline/online PIR scheme is a tuple $\Pi$ = (**Setup**, **Hint**, **Query**, **Answer**, **Reconstruct**) of +five efficient algorithms: -* **Setup**$(1^{\lambda}, n) \to (ck, q_h)$, a randomized algorithm that takes in security parameter $\lambda$ and database length $n$ and outputs a client key $ck$ and a hint request $q_h$. +* **Setup**$(1^{\lambda}, n) \to (ck, q_h)$, a randomized algorithm that takes in security parameter $\lambda$ and database length $n$ +and outputs a client key $ck$ and a hint request $q_h$. * **Hint**$(x, q_h) \to h$, a deterministic algorithm that takes in a database $x \in \{0, 1\}^n$ and a hint request $q_h$ and outputs a hint $h$. * **Query**$(ck, i) \to h$, a randomized algorithm that takes in the client’s key $ck$ and an index $i \in [n]$, and outputs a a query $q$. * **Answer**$(q) \to a$, a deterministic algorithm that takes as input a query $q$ and gets access to an oracle that: - * takes as input an index $j \in [n]$, and - * returns the $j$-th bit of the database $x_j ∈ \{0, 1\}$ + * takes as input an index $j \in [n]$, and + * returns the $j$-th bit of the database $x_j ∈ \{0, 1\}$ outputs an answer string $a$, and * **Reconstruct**$(h, a) \to x_i$, , a deterministic algorithm that takes as a hint $h$ and an answer $a$, and outputs a bit $x_i$. +### Puncturable pseudorandom sets -**Puncturable pseudorandom sets** +Puncturable pseudorandom sets are an extension of puncturable pseudorandom functions (PRFs). A typical pseudorandom function generates outputs that +are indistinguishable from random by any efficient algorithm, given only the outputs and not the secret key. When a PRF is punctured at a particular +point, it behaves like a normal PRF for all inputs except for the punctured point, for which the output or behavior is obscured or undefined. -Puncturable pseudorandom sets are an extension of puncturable pseudorandom functions (PRFs). A typical pseudorandom function generates outputs that are indistinguishable from random by any efficient algorithm, given only the outputs and not the secret key. When a PRF is punctured at a particular point, it behaves like a normal PRF for all inputs except for the punctured point, for which the output or behavior is obscured or undefined. +Our implementation utilizes the AES pseudorandom generator (PRG) to construct a GGM tree-based pseudorandom function (PRF), and then employs +Construction 4 from the original paper to build the Puncturable Pseudorandom Set (PPS). -Our implementation utilizes the AES pseudorandom generator (PRG) to construct a GGM tree-based pseudorandom function (PRF), and then employs Construction 4 from the original paper to build the Puncturable Pseudorandom Set (PPS). - -**Single-Bits PIR** +### Single-Bits PIR Construction 16 (Two-server PIR with sublinear online time). -**Multi-Bits PIR** +### Multi-Bits PIR Construction 44 (Multi-query offline/online PIR). -** Contact ** -email: yangw.ing@foxmail.com +### Contact + +email: diff --git a/psi/BUILD.bazel b/psi/BUILD.bazel index 86994661..931e09ae 100644 --- a/psi/BUILD.bazel +++ b/psi/BUILD.bazel @@ -22,7 +22,6 @@ psi_cc_library( "prelude.h", ], deps = [ - "//psi/proto:pir_cc_proto", "//psi/proto:psi_cc_proto", "//psi/proto:psi_v2_cc_proto", ], diff --git a/psi/algorithm/ecdh/ub_psi/ecdh_oprf_psi.cc b/psi/algorithm/ecdh/ub_psi/ecdh_oprf_psi.cc index b78723b1..5d15339f 100644 --- a/psi/algorithm/ecdh/ub_psi/ecdh_oprf_psi.cc +++ b/psi/algorithm/ecdh/ub_psi/ecdh_oprf_psi.cc @@ -106,7 +106,7 @@ size_t EcdhOprfPsiServer::FullEvaluate( std::vector shuffle_indices; PsiDataBatch batch; size_t i; - size_t local_batch_count; + size_t local_batch_count = 0; while (!stop_flag) { if (stop_flag) { break; diff --git a/psi/algorithm/nty/BUILD.bazel b/psi/algorithm/nty/BUILD.bazel new file mode 100644 index 00000000..1b5578fe --- /dev/null +++ b/psi/algorithm/nty/BUILD.bazel @@ -0,0 +1,72 @@ +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:psi.bzl", "psi_cc_library", "psi_cc_test") + +package(default_visibility = ["//visibility:public"]) + +psi_cc_library( + name = "nty_mp_psi", + srcs = [ + "nty_mp_psi.cc", + ], + hdrs = [ + "nty_mp_psi.h", + ], + deps = [ + ":server_aided_psi", + "//psi/algorithm/rr22:rr22_utils", + "//psi/algorithm/rr22/okvs:baxos", + "//psi/utils:communication", + "//psi/utils:sync", + "//psi/utils:test_utils", + "@abseil-cpp//absl/types:span", + "@sparsehash", + "@yacl//yacl/base:exception", + "@yacl//yacl/base:int128", + "@yacl//yacl/crypto/aes:aes_intrinsics", + "@yacl//yacl/crypto/hash:hash_utils", + "@yacl//yacl/crypto/rand", + "@yacl//yacl/kernel/algorithms:base_ot", + "@yacl//yacl/kernel/algorithms:iknp_ote", + "@yacl//yacl/kernel/algorithms:kkrt_ote", + "@yacl//yacl/link", + ], +) + +psi_cc_library( + name = "server_aided_psi", + srcs = [ + "server_aided_psi.cc", + ], + hdrs = [ + "server_aided_psi.h", + ], + deps = [ + "@yacl//yacl/base:int128", + "@yacl//yacl/crypto/aes:aes_intrinsics", + "@yacl//yacl/crypto/rand", + "@yacl//yacl/link", + ], +) + +psi_cc_test( + name = "nty_mp_psi_test", + srcs = ["nty_mp_psi_test.cc"], + tags = ["manual"], + deps = [ + ":nty_mp_psi", + "@yacl//yacl/utils:elapsed_timer", + ], +) diff --git a/psi/algorithm/nty/nty_mp_psi.cc b/psi/algorithm/nty/nty_mp_psi.cc new file mode 100644 index 00000000..ba0debd8 --- /dev/null +++ b/psi/algorithm/nty/nty_mp_psi.cc @@ -0,0 +1,390 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/nty/nty_mp_psi.h" + +#include + +#include "sparsehash/dense_hash_map" +#include "yacl/crypto/aes/aes_intrinsics.h" +#include "yacl/crypto/hash/hash_utils.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/utils/serialize.h" + +#include "psi/algorithm/rr22/okvs/baxos.h" +#include "psi/algorithm/rr22/rr22_utils.h" +#include "psi/algorithm/rr22/sparseconfig.h" +#include "psi/utils/communication.h" +#include "psi/utils/sync.h" + +namespace psi::nty { + +namespace { +// Statistical security parameter +constexpr size_t kDefaultSSP = 40; + +struct NoHash { + inline size_t operator()(const uint128_t& v) const { + uint32_t v32; + std::memcpy(&v32, &v, sizeof(uint32_t)); + + return v32; + } +}; + +} // namespace + +NtyMPsi::NtyMPsi(const NtyMPsiOptions& options) : options_{options} { + YACL_ENFORCE(options_.aided_server_rank != options_.helper_rank && + options_.aided_server_rank != options_.receiver_rank && + options_.helper_rank != options_.receiver_rank); + YACL_ENFORCE(options_.link_ctx != nullptr, "link_ctx should be initialized"); + options_.num_threads = std::max(1, options_.num_threads); + auto [ctx, wsize, self_rank] = CollectContext(); + YACL_ENFORCE(options_.aided_server_rank < wsize && + options_.helper_rank < wsize && options_.receiver_rank < wsize); + YACL_ENFORCE(wsize >= 3, + "the number of participants should be larger than 3"); + p2p_.resize(wsize); + for (size_t dst = 0; dst < wsize; ++dst) { + if (self_rank != dst) { + p2p_[dst] = CreateP2PLinkCtx("nty_mpsi", ctx, dst); + } + } + SPDLOG_DEBUG("party{} create p2p link success", self_rank); +} + +std::vector NtyMPsi::Run(const std::vector& inputs) { + auto [ctx, wsize, self_rank] = CollectContext(); + std::vector intersection; + if (self_rank == options_.receiver_rank) { + SPDLOG_INFO("aided_server_rank is {}", options_.aided_server_rank); + SPDLOG_INFO("helper_rank is {}", options_.helper_rank); + SPDLOG_INFO("receiver_rank is {}", options_.receiver_rank); + } + if (wsize == 3) { + SPDLOG_INFO("party{} start three party psi", self_rank); + ThreePartyPsi(inputs, intersection); + } else { + SPDLOG_INFO("party{} start multi party psi", self_rank); + MultiPartyPsi(inputs, intersection); + } + return intersection; +} + +void NtyMPsi::MultiPartyPsi(const std::vector& inputs, + std::vector& intersection) { + auto [ctx, wsize, self_rank] = CollectContext(); + auto counts = AllGatherItemsSize(ctx, inputs.size()); + // It is recommended that the party with smaller set be designated as + // p0 and pi(i > 2), the party with larger set be designated as p1 and p2. + if (self_rank == options_.aided_server_rank) { + // generate okvs and prf key + std::vector seeds; + for (uint64_t i = 0; i < wsize; ++i) { + if (i == options_.aided_server_rank || i == options_.helper_rank || + i == options_.receiver_rank) { + continue; + } + uint128_t seed = yacl::crypto::RandU128(); + seeds.push_back(seed); + yacl::ByteContainerView seed_buf(&seed, sizeof(uint128_t)); + p2p_[i]->SendAsyncThrottled(p2p_[i]->NextRank(), seed_buf, + fmt::format("send seed_buf")); + } + std::vector hashed_items(inputs.size()); + std::vector tmp(inputs.size()); + for (const auto& seed : seeds) { + yacl::crypto::AES_KEY aes_key; + AES_set_encrypt_key(seed, &aes_key); + AES_ecb_encrypt_blks(aes_key, absl::MakeConstSpan(inputs), + absl::MakeSpan(tmp)); + for (uint64_t i = 0; i < inputs.size(); ++i) { + hashed_items[i] ^= tmp[i]; + } + } + + GenOkvs(inputs, hashed_items, counts[self_rank], + p2p_[options_.receiver_rank]); + SPDLOG_DEBUG("aided server send okvs result to receiver success"); + // act as server-aided two party psi server + ServerAidedTwoPartyPsi::ServerAssist(options_.helper_rank, + options_.receiver_rank, p2p_); + SPDLOG_INFO("aided server finished server-aided two party psi"); + + if (options_.broadcast_result) { + auto buffer = yacl::link::Broadcast( + options_.link_ctx, {}, options_.receiver_rank, "broadcast result"); + intersection.resize(buffer.size() / sizeof(uint128_t)); + std::memcpy(intersection.data(), buffer.data(), buffer.size()); + } + } else if (self_rank == options_.helper_rank) { + // decode okvs and xor in multiparty settings + std::vector> recv_hashed_items(wsize); + std::vector hashed_items(inputs.size()); + auto recv_okvs = [&](size_t id) { + recv_hashed_items[id].resize(inputs.size()); + DecodeOkvs(inputs, counts[id], p2p_[id], recv_hashed_items[id]); + }; + std::vector> futures; + for (uint64_t i = 0; i < wsize; ++i) { + if (i != options_.aided_server_rank && i != options_.helper_rank && + i != options_.receiver_rank) { + futures.push_back( + std::async(std::launch::async, std::ref(recv_okvs), i)); + } + } + for (auto& f : futures) { + f.get(); + } + SPDLOG_DEBUG("helper recv and decode okvs success"); + for (uint64_t i = 0; i < wsize; ++i) { + if (i != options_.aided_server_rank && i != options_.helper_rank && + i != options_.receiver_rank) { + for (uint64_t j = 0; j < inputs.size(); ++j) + hashed_items[j] ^= recv_hashed_items[i][j]; + } + } + + // avoid collisions in okvs decoding, + // which is not necessary if okvs is bug free + std::transform(inputs.begin(), inputs.end(), hashed_items.begin(), + hashed_items.begin(), + [](uint128_t a, uint128_t b) { return a ^ b; }); + // two party psi with server-aided + std::vector raw_intersection_result; + ServerAidedTwoPartyPsi::ServerAidedPsi( + hashed_items, self_rank, options_.aided_server_rank, + options_.helper_rank, options_.receiver_rank, p2p_, + raw_intersection_result); + SPDLOG_INFO("helper finished server-aided two party psi"); + + if (options_.broadcast_result) { + auto buffer = yacl::link::Broadcast( + options_.link_ctx, {}, options_.receiver_rank, "broadcast result"); + intersection.resize(buffer.size() / sizeof(uint128_t)); + std::memcpy(intersection.data(), buffer.data(), buffer.size()); + } + } else if (self_rank == options_.receiver_rank) { + std::vector recv_hashed_items(inputs.size()); + DecodeOkvs(inputs, counts[options_.aided_server_rank], + p2p_[options_.aided_server_rank], recv_hashed_items); + SPDLOG_DEBUG("receiver recv and decode okvs success"); + std::transform(inputs.begin(), inputs.end(), recv_hashed_items.begin(), + recv_hashed_items.begin(), + [](uint128_t a, uint128_t b) { return a ^ b; }); + // two party psi with server-aided + std::vector raw_intersection_result; + ServerAidedTwoPartyPsi::ServerAidedPsi( + recv_hashed_items, self_rank, options_.aided_server_rank, + options_.helper_rank, options_.receiver_rank, p2p_, + raw_intersection_result); + GetIntersection(inputs, recv_hashed_items, raw_intersection_result, + intersection); + SPDLOG_INFO("receiver get intersection results success"); + + if (options_.broadcast_result) { + auto buffer = yacl::Buffer(intersection.data(), + intersection.size() * sizeof(uint128_t)); + yacl::link::Broadcast(options_.link_ctx, buffer, options_.receiver_rank, + "broadcast result"); + } + } else { + // compute prf and okvs + uint128_t prf_seed; + yacl::Buffer prf_seed_buf = p2p_[options_.aided_server_rank]->Recv( + p2p_[options_.aided_server_rank]->NextRank(), + fmt::format("recv prf seed")); + YACL_ENFORCE(prf_seed_buf.size() == sizeof(uint128_t)); + std::memcpy(&prf_seed, prf_seed_buf.data(), prf_seed_buf.size()); + std::vector hashed_items(inputs.size()); + yacl::crypto::AES_KEY aes_key; + AES_set_encrypt_key(prf_seed, &aes_key); + AES_ecb_encrypt_blks(aes_key, absl::MakeConstSpan(inputs), + absl::MakeSpan(hashed_items)); + + GenOkvs(inputs, hashed_items, counts[self_rank], + p2p_[options_.helper_rank]); + + SPDLOG_INFO("party {} finished generating and sending okvs result", + self_rank); + + if (options_.broadcast_result) { + auto buffer = yacl::link::Broadcast( + options_.link_ctx, {}, options_.receiver_rank, "broadcast result"); + intersection.resize(buffer.size() / sizeof(uint128_t)); + std::memcpy(intersection.data(), buffer.data(), buffer.size()); + } + } +} + +void NtyMPsi::ThreePartyPsi(const std::vector& inputs, + std::vector& intersection) { + auto [ctx, wsize, self_rank] = CollectContext(); + auto counts = AllGatherItemsSize(ctx, inputs.size()); + + if (self_rank == options_.aided_server_rank) { + // gen okvs and prf key + uint128_t seed = yacl::crypto::RandU128(); + yacl::ByteContainerView seed_buf(&seed, sizeof(uint128_t)); + + p2p_[options_.helper_rank]->SendAsyncThrottled( + p2p_[options_.helper_rank]->NextRank(), seed_buf, + fmt::format("send seed_buf")); + + std::vector hashed_items(inputs.size()); + yacl::crypto::AES_KEY aes_key; + AES_set_encrypt_key(seed, &aes_key); + AES_ecb_encrypt_blks(aes_key, absl::MakeConstSpan(inputs), + absl::MakeSpan(hashed_items)); + // gen okvs encode + + GenOkvs(inputs, hashed_items, counts[self_rank], + p2p_[options_.receiver_rank]); + ServerAidedTwoPartyPsi::ServerAssist(options_.helper_rank, + options_.receiver_rank, p2p_); + SPDLOG_INFO("aided server finished server-aided two party psi"); + + if (options_.broadcast_result) { + auto buffer = yacl::link::Broadcast( + options_.link_ctx, {}, options_.receiver_rank, "broadcast result"); + intersection.resize(buffer.size() / sizeof(uint128_t)); + std::memcpy(intersection.data(), buffer.data(), buffer.size()); + } + } else if (self_rank == options_.helper_rank) { + uint128_t prf_seed; + yacl::Buffer prf_seed_buf = p2p_[options_.aided_server_rank]->Recv( + p2p_[options_.aided_server_rank]->NextRank(), + fmt::format("recv prf seed")); + YACL_ENFORCE(prf_seed_buf.size() == sizeof(uint128_t)); + std::memcpy(&prf_seed, prf_seed_buf.data(), prf_seed_buf.size()); + // compute prf + std::vector hashed_items(inputs.size()); + yacl::crypto::AES_KEY aes_key; + AES_set_encrypt_key(prf_seed, &aes_key); + AES_ecb_encrypt_blks(aes_key, absl::MakeConstSpan(inputs), + absl::MakeSpan(hashed_items)); + SPDLOG_DEBUG("helper get oprf result success"); + std::transform(inputs.begin(), inputs.end(), hashed_items.begin(), + hashed_items.begin(), + [](uint128_t a, uint128_t b) { return a ^ b; }); + std::vector raw_intersection_result; + ServerAidedTwoPartyPsi::ServerAidedPsi( + hashed_items, self_rank, options_.aided_server_rank, + options_.helper_rank, options_.receiver_rank, p2p_, + raw_intersection_result); + SPDLOG_INFO("helper finished server-aided two party psi"); + + if (options_.broadcast_result) { + auto buffer = yacl::link::Broadcast( + options_.link_ctx, {}, options_.receiver_rank, "broadcast result"); + intersection.resize(buffer.size() / sizeof(uint128_t)); + std::memcpy(intersection.data(), buffer.data(), buffer.size()); + } + } else if (self_rank == options_.receiver_rank) { + std::vector recv_hashed_items(inputs.size()); + DecodeOkvs(inputs, counts[options_.aided_server_rank], + p2p_[options_.aided_server_rank], recv_hashed_items); + SPDLOG_DEBUG("receiver recv and decode okvs success"); + std::transform(inputs.begin(), inputs.end(), recv_hashed_items.begin(), + recv_hashed_items.begin(), + [](uint128_t a, uint128_t b) { return a ^ b; }); + // 2psi with server aid + std::vector raw_intersection_result; + ServerAidedTwoPartyPsi::ServerAidedPsi( + recv_hashed_items, self_rank, options_.aided_server_rank, + options_.helper_rank, options_.receiver_rank, p2p_, + raw_intersection_result); + GetIntersection(inputs, recv_hashed_items, raw_intersection_result, + intersection); + SPDLOG_INFO("receiver get intersection results success"); + + if (options_.broadcast_result) { + auto buffer = yacl::Buffer(intersection.data(), + intersection.size() * sizeof(uint128_t)); + yacl::link::Broadcast(options_.link_ctx, buffer, options_.receiver_rank, + "broadcast result"); + } + } else { + SPDLOG_ERROR("input wrong party number"); + } +} + +void NtyMPsi::GenOkvs(const std::vector& items, + std::vector& hashed_items, + const size_t& okvs_size, + const std::shared_ptr& ctx) { + // gen okvs encode + uint128_t baxos_seed = yacl::crypto::RandU128(); + psi::rr22::okvs::Baxos baxos; + baxos.Init(okvs_size, bin_size_, paxos_weight_, kDefaultSSP, + psi::rr22::okvs::PaxosParam::DenseType::GF128, baxos_seed); + yacl::ByteContainerView paxos_seed_buf(&baxos_seed, sizeof(uint128_t)); + ctx->SendAsyncThrottled(ctx->NextRank(), paxos_seed_buf, + fmt::format("send baxos_seed_buf")); + + std::vector p128_v(baxos.size(), 0); + auto p128_span = absl::MakeSpan(p128_v); + auto hashed_span = absl::MakeSpan(hashed_items); + baxos.Solve(absl::MakeSpan(items), hashed_span, p128_span, nullptr, + options_.num_threads); + psi::rr22::SendChunked(ctx, p128_span); +} + +void NtyMPsi::DecodeOkvs(const std::vector& items, + const size_t& okvs_size, + const std::shared_ptr& ctx, + std::vector& recv_hashed_items) { + // decode okvs + psi::rr22::okvs::Baxos baxos; + // recv seed from p2~pn-2 + uint128_t baxos_seed; + yacl::Buffer baxos_seed_buf = + ctx->Recv(ctx->NextRank(), fmt::format("recv baxos seed")); + YACL_ENFORCE(baxos_seed_buf.size() == sizeof(uint128_t)); + std::memcpy(&baxos_seed, baxos_seed_buf.data(), baxos_seed_buf.size()); + baxos.Init(okvs_size, bin_size_, paxos_weight_, kDefaultSSP, + psi::rr22::okvs::PaxosParam::DenseType::GF128, baxos_seed); + + uint64_t baxos_size_ = baxos.size(); + auto p_solve = psi::rr22::RecvChunked(ctx, baxos_size_); + absl::Span p128_span = absl::MakeSpan( + reinterpret_cast(p_solve.data()), baxos.size()); + baxos.Decode(absl::MakeConstSpan(items), absl::MakeSpan(recv_hashed_items), + p128_span, options_.num_threads); +} + +void NtyMPsi::GetIntersection(const std::vector& inputs, + const std::vector& hashed_items, + const std::vector& raw_result, + std::vector& intersection) { + google::dense_hash_map map(hashed_items.size()); + map.set_empty_key(yacl::crypto::RandU128()); + std::vector intersection_idx; + for (uint64_t i = 0; i < hashed_items.size(); ++i) { + map.insert({hashed_items[i], i}); + } + for (const auto& inter : raw_result) { + auto iter = map.find(inter); + if (iter != map.end()) { + intersection_idx.push_back(iter->second); + } + } + + for (uint64_t i = 0; i < intersection_idx.size(); ++i) { + intersection.emplace_back(inputs[intersection_idx[i]]); + } +} + +} // namespace psi::nty diff --git a/psi/algorithm/nty/nty_mp_psi.h b/psi/algorithm/nty/nty_mp_psi.h new file mode 100644 index 00000000..5f13bd44 --- /dev/null +++ b/psi/algorithm/nty/nty_mp_psi.h @@ -0,0 +1,98 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include + +#include "yacl/base/int128.h" +#include "yacl/link/link.h" + +#include "psi/algorithm/nty/server_aided_psi.h" + +namespace psi::nty { + +// Simple, Fast Malicious Multiparty Private Set Intersection +// https://eprint.iacr.org/2021/1221.pdf + +struct NtyMPsiOptions { + NtyMPsiOptions(size_t num_threads_params, size_t aided_server_rank_params, + size_t helper_rank_params, size_t receiver_rank_params, + bool broadcast_result_params = true, + bool malicious_params = false) + : num_threads(num_threads_params), + aided_server_rank(aided_server_rank_params), + helper_rank(helper_rank_params), + receiver_rank(receiver_rank_params), + broadcast_result(broadcast_result_params), + malicious(malicious_params) {} + // number of threads + size_t num_threads = 1; + // aided_server is p_1 in the original paper, who generates prf key and ovks + // encode reuslt p, and acts as the server to aid 2psi + size_t aided_server_rank = 0; + // helper is p_{n-1} + size_t helper_rank = 1; + // receiver is p_n + size_t receiver_rank = 2; + // broadcast intersection result to all + bool broadcast_result = true; + // run the protocol with malicious security + // not supported by now + bool malicious = false; + std::shared_ptr link_ctx; +}; + +class NtyMPsi { + public: + explicit NtyMPsi(const NtyMPsiOptions& options); + + std::vector Run(const std::vector& inputs); + + private: + void MultiPartyPsi(const std::vector& inputs, + std::vector& outputs); + + void ThreePartyPsi(const std::vector& inputs, + std::vector& outputs); + + void GenOkvs(const std::vector& items, + std::vector& hashed_items, const size_t& okvs_size, + const std::shared_ptr& ctx); + + void DecodeOkvs(const std::vector& items, const size_t& okvs_size, + const std::shared_ptr& ctx, + std::vector& recv_hashed_items); + + void GetIntersection(const std::vector& inputs, + const std::vector& hashed_items, + const std::vector& raw_result, + std::vector& intersection); + + // (ctx, world_size, self_rank) + auto CollectContext() const { + return std::make_tuple(options_.link_ctx, options_.link_ctx->WorldSize(), + options_.link_ctx->Rank()); + } + + NtyMPsiOptions options_; + std::vector> p2p_; + uint64_t bin_size_ = 1 << 14; + uint64_t paxos_weight_ = 3; +}; + +} // namespace psi::nty diff --git a/psi/algorithm/nty/nty_mp_psi_test.cc b/psi/algorithm/nty/nty_mp_psi_test.cc new file mode 100644 index 00000000..7d867570 --- /dev/null +++ b/psi/algorithm/nty/nty_mp_psi_test.cc @@ -0,0 +1,136 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/nty/nty_mp_psi.h" + +#include +#include +#include + +#include "gtest/gtest.h" +#include "yacl/link/test_util.h" +#include "yacl/utils/elapsed_timer.h" + +#include "psi/utils/test_utils.h" + +namespace psi::nty { + +namespace { + +struct NtyMPTestParams { + std::vector item_size; + size_t intersection_size; + size_t aided_server_rank = 0; + size_t helper_rank = 1; + size_t receiver_rank = 2; + size_t num_threads = 1; + bool broadcast_result = true; +}; + +std::vector> CreateNPartyItems( + const NtyMPTestParams& params) { + std::vector> ret(params.item_size.size() + 1); + ret[params.item_size.size()] = + test::CreateItemHashes(1, params.intersection_size); + + for (size_t idx = 0; idx < params.item_size.size(); ++idx) { + ret[idx] = + test::CreateItemHashes((idx + 1) * 100000000, params.item_size[idx]); + } + + for (size_t idx = 0; idx < params.item_size.size(); ++idx) { + std::unordered_set idx_set; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, params.item_size[idx] - 1); + + while (idx_set.size() < params.intersection_size) { + idx_set.insert(dis(gen)); + } + size_t j = 0; + for (const auto& iter : idx_set) { + ret[idx][iter] = ret[params.item_size.size()][j++]; + } + } + return ret; +} + +} // namespace + +class NtyMPsiTest : public testing::TestWithParam {}; + +TEST_P(NtyMPsiTest, Works) { + yacl::ElapsedTimer timer; + std::vector> items; + auto params = GetParam(); + SPDLOG_INFO("begin create test data"); + items = CreateNPartyItems(params); + SPDLOG_INFO("end create test data"); + SPDLOG_DEBUG("create test data time is {} ms", timer.CountMs()); + + timer.Restart(); + + auto ctxs = yacl::link::test::SetupWorld(params.item_size.size()); + size_t num_threads = params.num_threads; + size_t aided_server_rank = params.aided_server_rank; + size_t helper_rank = params.helper_rank; + size_t receiver_rank = params.receiver_rank; + bool broadcast_result = params.broadcast_result; + bool malicious = false; + auto proc = [&](int idx) -> std::vector { + NtyMPsiOptions opts(num_threads, aided_server_rank, helper_rank, + receiver_rank, broadcast_result, malicious); + opts.link_ctx = ctxs[idx]; + NtyMPsi mpsi(opts); + return mpsi.Run(items[idx]); + }; + + size_t world_size = ctxs.size(); + std::vector>> f_links(world_size); + for (size_t i = 0; i < world_size; i++) { + f_links[i] = std::async(proc, i); + } + + std::vector intersection = items[params.item_size.size()]; + std::sort(intersection.begin(), intersection.end()); + + std::vector> results(world_size); + for (size_t i = 0; i < world_size; i++) { + results[i] = f_links[i].get(); + } + if (broadcast_result) { + for (size_t i = 0; i < world_size; i++) { + std::sort(results[i].begin(), results[i].end()); + EXPECT_EQ(results[i].size(), intersection.size()); + EXPECT_EQ(results[i], intersection); + } + } else { + std::sort(results[receiver_rank].begin(), results[receiver_rank].end()); + EXPECT_EQ(results[receiver_rank].size(), intersection.size()); + EXPECT_EQ(results[receiver_rank], intersection); + } + SPDLOG_DEBUG("multiparty psi time is {} ms", timer.CountMs()); +} + +INSTANTIATE_TEST_SUITE_P( + Works_Instances, NtyMPsiTest, + testing::Values( + NtyMPTestParams{{1 << 12, 1 << 12, 1 << 12, 1 << 12}, 1 << 3, 1, 2, 3}, + NtyMPTestParams{{1 << 16, 1 << 16, 1 << 16, 1 << 16}, 1 << 16}, + NtyMPTestParams{ + {1 << 20, 1 << 20, 1 << 20, 1 << 20}, 1 << 20, 1, 2, 3, 8, false}, + NtyMPTestParams{{1 << 12, 1 << 12, 1 << 12}, 1 << 12}, + NtyMPTestParams{{1 << 16, 1 << 16, 1 << 16}, 1 << 16}, + NtyMPTestParams{{1 << 20, 1 << 20, 1 << 20}, 1 << 20})); +} // namespace psi::nty diff --git a/psi/algorithm/nty/server_aided_psi.cc b/psi/algorithm/nty/server_aided_psi.cc new file mode 100644 index 00000000..b85d8cf7 --- /dev/null +++ b/psi/algorithm/nty/server_aided_psi.cc @@ -0,0 +1,119 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/nty/server_aided_psi.h" + +#include +#include + +#include "yacl/crypto/aes/aes_intrinsics.h" +#include "yacl/crypto/rand/rand.h" + +namespace psi::nty { + +void SendEncItems(const std::vector& items, + const uint128_t& aes_seed, + const std::shared_ptr& ctx) { + yacl::crypto::AES_KEY aes_key; + AES_set_encrypt_key(aes_seed, &aes_key); + std::vector enc_items(items.size()); + AES_ecb_encrypt_blks(aes_key, absl::MakeConstSpan(items), + absl::MakeSpan(enc_items)); + std::mt19937 g(yacl::crypto::SecureRandU64()); + std::shuffle(enc_items.begin(), enc_items.end(), g); + yacl::ByteContainerView enc_items_buf(enc_items.data(), + sizeof(uint128_t) * items.size()); + ctx->SendAsyncThrottled(ctx->NextRank(), enc_items_buf, + fmt::format("send enc items")); +} + +void ServerAidedTwoPartyPsi::ServerAidedPsi( + const std::vector& items, size_t self_rank, + size_t aided_server_rank, size_t helper_rank, size_t receiver_rank, + const std::vector>& p2p, + std::vector& outputs) { + uint128_t aes_seed; + if (self_rank == receiver_rank) { + yacl::Buffer aes_seed_buf = p2p[helper_rank]->Recv( + p2p[helper_rank]->NextRank(), fmt::format("recv aes seed")); + YACL_ENFORCE(aes_seed_buf.size() == sizeof(uint128_t)); + std::memcpy(&aes_seed, aes_seed_buf.data(), aes_seed_buf.size()); + SendEncItems(items, aes_seed, p2p[aided_server_rank]); + // p2 get raw intersection data + yacl::Buffer recv_data = + p2p[aided_server_rank]->Recv(p2p[aided_server_rank]->NextRank(), + fmt::format("recv raw intersection data")); + if (recv_data.size() % sizeof(uint128_t) != 0) { + SPDLOG_ERROR("recv data size should be a multiple of {} bytes", + sizeof(uint128_t)); + } + + outputs.resize(recv_data.size() / sizeof(uint128_t)); + std::vector recv_cipher(recv_data.size() / sizeof(uint128_t)); + std::memcpy(recv_cipher.data(), recv_data.data(), recv_data.size()); + + // dec + yacl::crypto::AES_KEY aes_key; + AES_set_decrypt_key(aes_seed, &aes_key); + AES_ecb_decrypt_blks(aes_key, absl::MakeConstSpan(recv_cipher), + absl::MakeSpan(outputs)); + } else { + yacl::crypto::AES_KEY aes_key; + aes_seed = yacl::crypto::RandU128(); + yacl::ByteContainerView seed_buf(&aes_seed, sizeof(uint128_t)); + p2p[receiver_rank]->SendAsyncThrottled( + p2p[receiver_rank]->NextRank(), seed_buf, fmt::format("send seed_buf")); + SendEncItems(items, aes_seed, p2p[aided_server_rank]); + } +} + +void ServerAidedTwoPartyPsi::ServerAssist( + size_t helper_rank, size_t receiver_rank, + const std::vector>& p2p) { + std::vector helper_prf, receiver_prf; + auto recv_prf = [&](std::vector& data, uint64_t id) { + yacl::Buffer recv_data = + p2p[id]->Recv(p2p[id]->NextRank(), fmt::format("recv data")); + if (recv_data.size() % sizeof(uint128_t) != 0) { + SPDLOG_ERROR("recv data size should be a multiple of {} bytes", + sizeof(uint128_t)); + } + data.resize(recv_data.size() / sizeof(uint128_t)); + std::memcpy(data.data(), recv_data.data(), recv_data.size()); + std::sort(data.begin(), data.end()); + }; + auto future0 = std::async(std::launch::async, std::ref(recv_prf), + std::ref(helper_prf), helper_rank); + auto future1 = std::async(std::launch::async, std::ref(recv_prf), + std::ref(receiver_prf), receiver_rank); + future0.get(); + future1.get(); + + // compute intersection + std::vector res; + std::set_intersection(helper_prf.begin(), helper_prf.end(), + receiver_prf.begin(), receiver_prf.end(), + std::back_inserter(res)); + yacl::ByteContainerView res_buf(res.data(), sizeof(uint128_t) * res.size()); + auto send_result = [&](yacl::ByteContainerView& res_buf, uint64_t id) { + p2p[id]->SendAsyncThrottled(p2p[id]->NextRank(), res_buf, + fmt::format("send result")); + }; + auto send_future = std::async(std::launch::async, std::ref(send_result), + std::ref(res_buf), receiver_rank); + send_future.get(); + SPDLOG_INFO("send intersection reuslt to receiver"); +} + +} // namespace psi::nty diff --git a/psi/algorithm/nty/server_aided_psi.h b/psi/algorithm/nty/server_aided_psi.h new file mode 100644 index 00000000..0b9f0ca7 --- /dev/null +++ b/psi/algorithm/nty/server_aided_psi.h @@ -0,0 +1,37 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "yacl/base/int128.h" +#include "yacl/link/link.h" + +namespace psi::nty { +class ServerAidedTwoPartyPsi { + public: + static void ServerAidedPsi( + const std::vector& items, size_t self_rank, + size_t aided_server_rank, size_t helper_rank, size_t receiver_rank, + const std::vector>& p2p, + std::vector& outputs); + + static void ServerAssist( + size_t helper_rank, size_t receiver_rank, + const std::vector>& p2p); +}; + +} // namespace psi::nty diff --git a/psi/algorithm/kwpir/BUILD.bazel b/psi/algorithm/pir_interface/BUILD.bazel similarity index 76% rename from psi/algorithm/kwpir/BUILD.bazel rename to psi/algorithm/pir_interface/BUILD.bazel index 83cb4541..6b6625d5 100644 --- a/psi/algorithm/kwpir/BUILD.bazel +++ b/psi/algorithm/pir_interface/BUILD.bazel @@ -28,6 +28,7 @@ psi_cc_library( "-lm", ], deps = [ + "pir_db", "//psi/utils:cuckoo_index", "@yacl//yacl/base:byte_container_view", "@yacl//yacl/base:exception", @@ -44,3 +45,23 @@ psi_cc_test( "//psi/algorithm/sealpir:seal_pir", ], ) + +psi_cc_library( + name = "pir_db", + srcs = ["pir_db.cc"], + hdrs = ["pir_db.h"], + deps = [ + "@abseil-cpp//absl/types:span", + "@yacl//yacl/base:exception", + "@yacl//yacl/crypto/rand", + "@yacl//yacl/utils:parallel", + ], +) + +psi_cc_test( + name = "pir_db_test", + srcs = ["pir_db_test.cc"], + deps = [ + ":pir_db", + ], +) diff --git a/psi/algorithm/kwpir/index_pir.h b/psi/algorithm/pir_interface/index_pir.h similarity index 63% rename from psi/algorithm/kwpir/index_pir.h rename to psi/algorithm/pir_interface/index_pir.h index 17db21c4..965b8e25 100644 --- a/psi/algorithm/kwpir/index_pir.h +++ b/psi/algorithm/pir_interface/index_pir.h @@ -12,26 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. #pragma once + #include #include "yacl/base/byte_container_view.h" -namespace psi::kwpir { +#include "psi/algorithm/pir_interface/pir_db.h" -class IndexPirServer { - public: - virtual ~IndexPirServer() = default; - virtual void SetDatabase( - const std::vector& db_vec) = 0; - virtual yacl::Buffer GenerateIndexReply(const yacl::Buffer& query_buffer) = 0; -}; +namespace psi::pir { class IndexPirClient { public: virtual ~IndexPirClient() = default; - virtual yacl::Buffer GenerateIndexQuery(uint64_t ele_index, - uint64_t& offset) = 0; - virtual std::vector DecodeIndexReply( - const yacl::Buffer& reply_buffer, uint64_t offset) = 0; + + virtual yacl::Buffer GenerateIndexQuery(uint64_t raw_idx) const = 0; + + virtual std::vector DecodeIndexResponse( + const yacl::Buffer& response_buffer, uint64_t raw_idx) const = 0; }; -} // namespace psi::kwpir \ No newline at end of file + +class IndexPirServer { + public: + virtual ~IndexPirServer() = default; + virtual void SetDatabase(const psi::pir_utils::RawDatabase& raw_database) = 0; + virtual yacl::Buffer GenerateIndexResponse( + const yacl::Buffer& query_buffer) const = 0; +}; + +} // namespace psi::pir diff --git a/psi/algorithm/kwpir/kw_pir.cc b/psi/algorithm/pir_interface/kw_pir.cc similarity index 68% rename from psi/algorithm/kwpir/kw_pir.cc rename to psi/algorithm/pir_interface/kw_pir.cc index f63cd983..9c0b19b3 100644 --- a/psi/algorithm/kwpir/kw_pir.cc +++ b/psi/algorithm/pir_interface/kw_pir.cc @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "psi/algorithm/kwpir/kw_pir.h" +#include "psi/algorithm/pir_interface/kw_pir.h" #include "yacl/crypto/hash/hash_utils.h" -namespace psi::kwpir { +namespace psi::pir { void KwPirServer::SetDatabase( const std::vector< @@ -58,38 +58,36 @@ void KwPirServer::SetDatabase( } YACL_ENFORCE_EQ(index_db_vec_store.size(), bins.size()); - std::vector index_db_vec; - index_db_vec.reserve(bins.size()); - for (uint64_t i = 0; i < bins.size(); ++i) { - index_db_vec.emplace_back(index_db_vec_store[i]); - } - pir_server_->SetDatabase(index_db_vec); + pir_utils::RawDatabase raw_db(index_db_vec_store); + + pir_server_->SetDatabase(raw_db); } -std::vector KwPirServer::GenerateReply( - const std::vector& query) { +std::vector KwPirServer::GenerateResponse( + const std::vector& query) const { uint64_t num_hash = options_.cuckoo_options_.num_hash; YACL_ENFORCE_EQ(query.size(), num_hash); std::vector reply_vec; reply_vec.reserve(num_hash); for (uint64_t hash_index = 0; hash_index < num_hash; ++hash_index) { - yacl::Buffer reply = pir_server_->GenerateIndexReply(query[hash_index]); + yacl::Buffer reply = pir_server_->GenerateIndexResponse(query[hash_index]); reply_vec.emplace_back(std::move(reply)); } return reply_vec; } -yacl::Buffer KwPirServer::GenerateReply(const yacl::Buffer& query) { - yacl::Buffer reply = pir_server_->GenerateIndexReply(query); +yacl::Buffer KwPirServer::GenerateResponse(const yacl::Buffer& query) const { + yacl::Buffer reply = pir_server_->GenerateIndexResponse(query); return reply; } -std::vector KwPirClient::GenerateQuery( - yacl::ByteContainerView keyword, std::vector& offset) { +std::pair, std::vector> +KwPirClient::GenerateQuery(yacl::ByteContainerView keyword) const { uint64_t num_hash = options_.cuckoo_options_.num_hash; - offset.clear(); - offset.resize(num_hash); + + std::vector idx_vec; + idx_vec.reserve(num_hash); std::vector query_vec; query_vec.reserve(num_hash); @@ -99,36 +97,37 @@ std::vector KwPirClient::GenerateQuery( CuckooIndex::HashRoom hash_room(key_hash); uint64_t ele_index = hash_room.GetHash(hash_index) % options_.cuckoo_options_.NumBins(); + idx_vec.push_back(ele_index); - yacl::Buffer query = - pir_client_->GenerateIndexQuery(ele_index, offset[hash_index]); + auto query = pir_client_->GenerateIndexQuery(ele_index); query_vec.emplace_back(std::move(query)); } - return query_vec; + return std::make_pair(query_vec, idx_vec); } -std::vector KwPirClient::DecodeReply(const yacl::Buffer& reply, - uint64_t offset) { - std::vector ele = pir_client_->DecodeIndexReply(reply, offset); +std::vector KwPirClient::DecodeResponse(const yacl::Buffer& response, + uint64_t raw_idx) const { + std::vector ele = + pir_client_->DecodeIndexResponse(response, raw_idx); return ele; } -std::vector> KwPirClient::DecodeReply( - const std::vector& reply, - const std::vector& offset) { +std::vector> KwPirClient::DecodeResponse( + const std::vector& response, + const std::vector& raw_idxs) const { uint64_t num_hash = options_.cuckoo_options_.num_hash; - YACL_ENFORCE_EQ(reply.size(), num_hash); - YACL_ENFORCE_EQ(offset.size(), num_hash); + YACL_ENFORCE_EQ(response.size(), num_hash); + YACL_ENFORCE_EQ(raw_idxs.size(), num_hash); std::vector> ele_vec; ele_vec.reserve(num_hash); for (uint64_t hash_index = 0; hash_index < num_hash; ++hash_index) { - std::vector ele = - pir_client_->DecodeIndexReply(reply[hash_index], offset[hash_index]); + std::vector ele = pir_client_->DecodeIndexResponse( + response[hash_index], raw_idxs[hash_index]); ele_vec.emplace_back(std::move(ele)); } return ele_vec; } -} // namespace psi::kwpir +} // namespace psi::pir diff --git a/psi/algorithm/kwpir/kw_pir.h b/psi/algorithm/pir_interface/kw_pir.h similarity index 75% rename from psi/algorithm/kwpir/kw_pir.h rename to psi/algorithm/pir_interface/kw_pir.h index 84d07777..3ccbf99e 100644 --- a/psi/algorithm/kwpir/kw_pir.h +++ b/psi/algorithm/pir_interface/kw_pir.h @@ -24,10 +24,10 @@ #include "yacl/base/byte_container_view.h" #include "yacl/crypto/rand/rand.h" -#include "psi/algorithm/kwpir/index_pir.h" +#include "psi/algorithm/pir_interface/index_pir.h" #include "psi/utils/cuckoo_index.h" -namespace psi::kwpir { +namespace psi::pir { struct KwPirOptions { CuckooIndex::Options cuckoo_options_{1 << 16, 0, 3, 1.3}; @@ -61,9 +61,11 @@ class KwPirServer : public KwPir { void SetDatabase( const std::vector< std::pair>& db_vec); - std::vector GenerateReply( - const std::vector& query_vec); - yacl::Buffer GenerateReply(const yacl::Buffer& query_vec); + + std::vector GenerateResponse( + const std::vector& query_vec) const; + + yacl::Buffer GenerateResponse(const yacl::Buffer& query_vec) const; private: psi::CuckooIndex cuckoo_index_; @@ -77,15 +79,16 @@ class KwPirClient : public KwPir { : KwPir(options), pir_client_(std::move(pir_client)) {} ~KwPirClient() override = default; - std::vector GenerateQuery(yacl::ByteContainerView keyword, - std::vector& offset); + std::pair, std::vector> GenerateQuery( + yacl::ByteContainerView keyword) const; - std::vector> DecodeReply( - const std::vector& reply, - const std::vector& offset); - std::vector DecodeReply(const yacl::Buffer& reply, uint64_t offset); + std::vector> DecodeResponse( + const std::vector& response, + const std::vector& raw_idxs) const; + std::vector DecodeResponse(const yacl::Buffer& response, + uint64_t raw_idx) const; private: std::unique_ptr pir_client_; }; -} // namespace psi::kwpir +} // namespace psi::pir diff --git a/psi/algorithm/kwpir/kw_pir_test.cc b/psi/algorithm/pir_interface/kw_pir_test.cc similarity index 89% rename from psi/algorithm/kwpir/kw_pir_test.cc rename to psi/algorithm/pir_interface/kw_pir_test.cc index 07f22fce..dae5b0d3 100644 --- a/psi/algorithm/kwpir/kw_pir_test.cc +++ b/psi/algorithm/pir_interface/kw_pir_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "psi/algorithm/kwpir/kw_pir.h" +#include "psi/algorithm/pir_interface/kw_pir.h" #include #include @@ -23,7 +23,7 @@ #include "psi/algorithm/sealpir/seal_pir.h" -namespace psi::kwpir { +namespace psi::pir { struct TestParams { uint64_t num_input = 1000; @@ -76,13 +76,10 @@ TEST_P(KwpirTest, Works) { } psi::sealpir::SealPirOptions seal_options{params.N, params.NumBins(), - key_size + value_size, - params.ind_degree, params.d}; - std::shared_ptr plaintext_store = - std::make_shared(); + key_size + value_size, params.d}; std::unique_ptr seal_server( - new psi::sealpir::SealPirServer(seal_options, plaintext_store)); + new psi::sealpir::SealPirServer(seal_options)); std::unique_ptr seal_client( new psi::sealpir::SealPirClient(seal_options)); @@ -102,15 +99,14 @@ TEST_P(KwpirTest, Works) { yacl::ByteContainerView query_key = db_vec[ele_index].first; yacl::ByteContainerView query_value = db_vec[ele_index].second; - std::vector offset_vec; + // std::vector offset_vec; SPDLOG_INFO("generating query...\n"); - std::vector query_vec = - client.GenerateQuery(query_key, offset_vec); + auto [query_vec, offset_vec] = client.GenerateQuery(query_key); SPDLOG_INFO("generating reply...\n"); - std::vector reply_vec = server.GenerateReply(query_vec); + std::vector reply_vec = server.GenerateResponse(query_vec); SPDLOG_INFO("decoding reply...\n"); std::vector> decoded_vec = - client.DecodeReply(reply_vec, offset_vec); + client.DecodeResponse(reply_vec, offset_vec); EXPECT_EQ(decoded_vec.size(), num_hash); bool success = false; @@ -134,6 +130,7 @@ INSTANTIATE_TEST_SUITE_P( Works_Instances, KwpirTest, testing::Values(TestParams{1000, 3, 1.3, 16, 256, 128, 4096, 2, 0}, TestParams{1000, 2, 2.4, 16, 256, 128, 4096, 2, 0}, + TestParams{1000, 2, 2.4, 16, 20000, 128, 4096, 2, 0}, TestParams{1000, 3, 1.3, 16, 128, 128, 4096, 1, 400}, TestParams{1000, 2, 2.4, 16, 128, 128, 4096, 1, 400}, TestParams{203, 3, 1.3, 16, 8, 128, 4096, 1, 0}, @@ -142,6 +139,7 @@ INSTANTIATE_TEST_SUITE_P( // N = 8192 TestParams{1000, 3, 1.3, 16, 256, 128, 8192, 1, 0}, TestParams{1000, 2, 2.4, 16, 256, 128, 8192, 1, 0}, + // TestParams{1000, 2, 2.4, 16, 20000, 128, 8192, 1, 0}, TestParams{3000, 3, 1.3, 16, 256, 128, 8192, 2, 1000}, TestParams{1000, 3, 1.3, 16, 16, 128, 8192, 2, 400}, @@ -152,4 +150,4 @@ INSTANTIATE_TEST_SUITE_P( TestParams{(1 << 22) - (1 << 10), 3, 1.3, 16, 64, 128, 4096, 2, 0})); -} // namespace psi::kwpir +} // namespace psi::pir diff --git a/psi/algorithm/pir_interface/pir_db.cc b/psi/algorithm/pir_interface/pir_db.cc new file mode 100644 index 00000000..4f8f065a --- /dev/null +++ b/psi/algorithm/pir_interface/pir_db.cc @@ -0,0 +1,125 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/pir_interface/pir_db.h" + +// 1. "psi/algorithm/pir_interface/pir_db.h" ---> +// "psi/algorithm/pir_interface/pir_db.h" + +// 2. "//psi/algorithm/pir_interface:pir_db", ----> +// "//psi/algorithm/pir_interface:pir_db" + +#include "absl/types/span.h" +#include "spdlog/spdlog.h" +#include "yacl/crypto/tools/prg.h" +#include "yacl/utils/parallel.h" + +namespace psi::pir_utils { + +RawDatabase RawDatabase::Random(uint64_t rows, uint64_t row_byte_len) { + std::vector> db; + db.reserve(rows); + yacl::crypto::Prg prg; + for (size_t i = 0; i < rows; ++i) { + std::vector tmp(row_byte_len); + prg.Fill(absl::MakeSpan(tmp)); + db.push_back(tmp); + } + + RawDatabase raw_db; + raw_db.rows_ = rows; + raw_db.row_byte_len_ = row_byte_len; + raw_db.db_ = std::move(db); + + return raw_db; +} + +std::vector RawDatabase::Combine( + const std::vector>& data, size_t row_byte_len) { + if (data.size() == 1) { + YACL_ENFORCE_EQ(data[0].size(), row_byte_len); + return data[0]; + } + + // assert each partition's length is same + size_t m = data[0].size(); + for (const auto& tmp : data) { + YACL_ENFORCE_EQ(tmp.size(), m); + } + + YACL_ENFORCE_GE(data.size() * m, row_byte_len); + + std::vector result; + result.reserve(row_byte_len); + + for (size_t i = 0; i < data.size(); ++i) { + if (i < data.size() - 1) { + // just insert + result.insert(result.end(), data[i].begin(), data[i].end()); + } else { + size_t end = row_byte_len - i * m; + result.insert(result.end(), data[i].begin(), data[i].begin() + end); + } + } + return result; +} + +std::vector RawDatabase::Partition( + size_t partition_byte_len) const { + // row_byte_len_ >= partition_byte_len + YACL_ENFORCE_GE(row_byte_len_, partition_byte_len); + + size_t partition_num = + (row_byte_len_ + partition_byte_len - 1) / partition_byte_len; + if (partition_num == 1) { + return std::vector{RawDatabase(rows_, row_byte_len_, db_)}; + } + + std::vector result; + result.reserve(partition_num); + + // first process the [0, partition_num - 2] + for (size_t i = 0; i < partition_num - 1; ++i) { + size_t start_col = i * partition_byte_len; + // end_col should <= row_byet_len_ + size_t end_col = start_col + partition_byte_len; + + std::vector> sub_db; + sub_db.reserve(rows_); + for (size_t n = 0; n < rows_; ++n) { + std::vector chunk(db_[n].begin() + start_col, + db_[n].begin() + end_col); + sub_db.push_back(std::move(chunk)); + } + // construct a RawDatabase + result.emplace_back(rows_, partition_byte_len, std::move(sub_db)); + } + // then handle the last partiiton + size_t start_col = (partition_num - 1) * partition_byte_len; + size_t end_col = std::min(start_col + partition_byte_len, row_byte_len_); + std::vector> sub_db; + sub_db.reserve(rows_); + for (size_t n = 0; n < rows_; ++n) { + // default padding zeros + std::vector chunk(partition_byte_len, 0); + std::copy(db_[n].begin() + start_col, db_[n].begin() + end_col, + chunk.begin()); + sub_db.push_back(std::move(chunk)); + } + result.emplace_back(rows_, partition_byte_len, std::move(sub_db)); + + return result; +} + +} // namespace psi::pir_utils diff --git a/psi/algorithm/pir_interface/pir_db.h b/psi/algorithm/pir_interface/pir_db.h new file mode 100644 index 00000000..901fff00 --- /dev/null +++ b/psi/algorithm/pir_interface/pir_db.h @@ -0,0 +1,83 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#include + +#include "yacl/base/exception.h" + +namespace { + +// ensure each row byte len is same +void ValidateDb(const std::vector>& db) { + size_t first_row_len = db[0].size(); + for (const auto& inner : db) { + YACL_ENFORCE_EQ(first_row_len, inner.size()); + } +} + +void ValidateDb(const std::vector>& db, + size_t target_len) { + for (const auto& inner : db) { + YACL_ENFORCE_EQ(target_len, inner.size()); + } +} + +} // namespace + +namespace psi::pir_utils { + +// Raw datbase, n * l , n is the rows, l is the byte len of each row +class RawDatabase { + public: + RawDatabase() = default; + + RawDatabase(std::vector> db) + : rows_(db.size()), row_byte_len_(db[0].size()), db_(std::move(db)) { + ValidateDb(Db()); + } + RawDatabase(size_t rows, size_t row_byte_len, + std::vector> db) + : rows_(rows), row_byte_len_(row_byte_len), db_(std::move(db)) { + ValidateDb(Db(), RowByteLen()); + } + + static RawDatabase Random(uint64_t rows, uint64_t row_byte_len); + + static std::vector Combine( + const std::vector>& data, size_t row_byte_len); + + size_t Rows() const { return rows_; } + + size_t RowByteLen() const { return row_byte_len_; } + + const std::vector>& Db() const { return db_; } + + const std::vector& At(size_t i) const { return db_.at(i); } + + // Partition the database to some sub-database, for exapmle: + // the RawDatabase is 100 rows, 64-byte, the partition_byte_len = 16-byte + // the partition result is 4 sub-databases, each sub database is 100 rows, + // 16-byte + std::vector Partition(size_t partition_byte_len) const; + + private: + size_t rows_ = 0; + + size_t row_byte_len_ = 0; + + std::vector> db_; +}; +} // namespace psi::pir_utils diff --git a/psi/algorithm/pir_interface/pir_db_test.cc b/psi/algorithm/pir_interface/pir_db_test.cc new file mode 100644 index 00000000..d6fcfdfc --- /dev/null +++ b/psi/algorithm/pir_interface/pir_db_test.cc @@ -0,0 +1,82 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/pir_interface/pir_db.h" + +#include + +#include "gtest/gtest.h" + +namespace psi::pir_utils { + +TEST(RawDatabase, Work) { + RawDatabase db = RawDatabase::Random(100, 256); + + RawDatabase db2 = RawDatabase::Random(1000000, 256); + + RawDatabase db3 = RawDatabase::Random(1ULL << 20, 256); +} + +TEST(RawDatabase, Partition) { + size_t row_byte_len = 256; + size_t rows = 100000; + RawDatabase db = RawDatabase::Random(rows, row_byte_len); + + size_t partition_byte_len = 64; + auto sub_dbs = db.Partition(partition_byte_len); + ASSERT_EQ(sub_dbs.size(), row_byte_len / partition_byte_len); + + partition_byte_len = 65; + sub_dbs = db.Partition(partition_byte_len); + ASSERT_EQ(sub_dbs.size(), + (row_byte_len + partition_byte_len - 1) / partition_byte_len); + + partition_byte_len = 257; + ASSERT_THROW(db.Partition(partition_byte_len), yacl::EnforceNotMet); + + // large num 100-kb + row_byte_len = 102400; + rows = 10000; + db = RawDatabase::Random(rows, row_byte_len); + + partition_byte_len = 10240; + sub_dbs = db.Partition(partition_byte_len); + ASSERT_EQ(sub_dbs.size(), row_byte_len / partition_byte_len); +} + +TEST(RawDatabase, Combine) { + size_t row_byte_len = 257; + size_t rows = 100000; + RawDatabase db = RawDatabase::Random(rows, row_byte_len); + + size_t partition_byte_len = 64; + auto sub_dbs = db.Partition(partition_byte_len); + + size_t partition_num = + (row_byte_len + partition_byte_len - 1) / partition_byte_len; + + std::random_device rd; + std::mt19937_64 rng(rd()); + + size_t idx = rng() % rows; + std::vector> subs; + for (size_t j = 0; j < partition_num; ++j) { + subs.push_back(sub_dbs[j].At(idx)); + } + // combine + std::vector combine = RawDatabase::Combine(subs, row_byte_len); + ASSERT_EQ(combine, db.At(idx)); +} + +} // namespace psi::pir_utils \ No newline at end of file diff --git a/psi/algorithm/sealpir/BUILD.bazel b/psi/algorithm/sealpir/BUILD.bazel index b195699e..9e68ec17 100644 --- a/psi/algorithm/sealpir/BUILD.bazel +++ b/psi/algorithm/sealpir/BUILD.bazel @@ -41,7 +41,8 @@ psi_cc_library( deps = [ ":seal_pir_utils", ":serializable_cc_proto", - "//psi/algorithm/kwpir:kw_pir", + "//psi/algorithm/pir_interface:kw_pir", + "//psi/algorithm/pir_interface:pir_db", "@openssl", "@seal", "@yacl//yacl/base:byte_container_view", @@ -67,5 +68,6 @@ psi_cc_test( deps = [ ":seal_pir", "@seal", + "@yacl//yacl/crypto/tools:prg", ], ) diff --git a/psi/algorithm/sealpir/README.md b/psi/algorithm/sealpir/README.md index d244750f..5dbc5949 100644 --- a/psi/algorithm/sealpir/README.md +++ b/psi/algorithm/sealpir/README.md @@ -1,11 +1,17 @@ +# SEALPIR + This folder currently implements a classic pir algorithm, providing a solid foundation for further developments. -### Future Enhancements +## Future Enhancements + We plan to expand this by introducing additional algorithms based on the current one. Our roadmap includes: -Keyword PIR to Index PIR Conversion: We aim to support seamless conversion between Keyword PIR and Index PIR, enhancing the flexibility and applicability of the solution. +Keyword PIR to Index PIR Conversion: We aim to support seamless conversion between Keyword PIR and Index PIR, +enhancing the flexibility and applicability of the solution. Algorithm Utilization: Future updates will leverage these new algorithms to optimize and broaden the project's capabilities. -### Stay Tuned -We are excited about these upcoming enhancements and encourage you to watch this repository for future updates. Your interest and support are greatly appreciated as we continue to innovate and expand our project. \ No newline at end of file +## Stay Tuned + +We are excited about these upcoming enhancements and encourage you to watch this repository for future updates. +Your interest and support are greatly appreciated as we continue to innovate and expand our project. diff --git a/psi/algorithm/sealpir/seal_pir.cc b/psi/algorithm/sealpir/seal_pir.cc index 3269e76a..ad54cb45 100644 --- a/psi/algorithm/sealpir/seal_pir.cc +++ b/psi/algorithm/sealpir/seal_pir.cc @@ -31,12 +31,20 @@ using namespace seal; namespace psi::sealpir { namespace { uint64_t ElementsPerPtxt(uint32_t logt, uint64_t N, uint64_t ele_size) { + if (ele_size > static_cast(floor((logt * N) / 8))) { + return 1; + } + uint64_t coeffs_per_element = ceil((ele_size * 8) / (double)logt); uint64_t elements_per_plaintext = N / coeffs_per_element; YACL_ENFORCE_GT(elements_per_plaintext, 0UL); return elements_per_plaintext; } +uint64_t GetPartitionSize(uint64_t logt, uint64_t N, uint64_t ele_size) { + return min(static_cast(floor((logt * N) / 8)), ele_size); +} + uint64_t PlaintextsPerDb(uint32_t logt, uint64_t N, uint64_t ele_num, uint64_t ele_size) { uint64_t elements_per_plaintext = ElementsPerPtxt(logt, N, ele_size); @@ -165,8 +173,8 @@ vector ComputeIndices(uint64_t desiredIndex, return result; } -vector DecomposeToPlaintexts(seal::EncryptionParameters params, - const seal::Ciphertext &ct) { +vector DecomposeToPlaintexts( + const seal::EncryptionParameters ¶ms, const seal::Ciphertext &ct) { const auto N = params.poly_modulus_degree(); const auto coeff_mod_count = params.coeff_modulus().size(); const uint32_t logt = log2(params.plain_modulus().value()); @@ -199,7 +207,7 @@ vector DecomposeToPlaintexts(seal::EncryptionParameters params, return result; } -void ComposeToCiphertext(seal::EncryptionParameters params, +void ComposeToCiphertext(const seal::EncryptionParameters ¶ms, vector::const_iterator pt_iter, const size_t ct_poly_count, seal::Ciphertext &ct) { const auto N = params.poly_modulus_degree(); @@ -232,7 +240,7 @@ void ComposeToCiphertext(seal::EncryptionParameters params, } } -void ComposeToCiphertext(seal::EncryptionParameters params, +void ComposeToCiphertext(const seal::EncryptionParameters ¶ms, const vector &pts, seal::Ciphertext &ct) { return ComposeToCiphertext(params, pts.begin(), @@ -257,65 +265,64 @@ void VectorToPlaintext(const vector &coeffs, seal::Plaintext &plain) { /********************************************************************************** SealPir **********************************************************************************/ -void SealPir::SetSealContext(size_t degree) { +void SealPir::SetSealContext(size_t poly_modulus_degree, size_t logt) { // degree >= 4096 - YACL_ENFORCE_GE(degree, (size_t)4096); + YACL_ENFORCE_GE(poly_modulus_degree, (size_t)4096); enc_params_ = make_unique(seal::scheme_type::bfv); - enc_params_->set_poly_modulus_degree(degree); + enc_params_->set_poly_modulus_degree(poly_modulus_degree); enc_params_->set_plain_modulus( - seal::PlainModulus::Batching(degree, options_.logt + 1)); - enc_params_->set_coeff_modulus(seal::CoeffModulus::BFVDefault(degree)); + seal::PlainModulus::Batching(poly_modulus_degree, logt + 1)); + enc_params_->set_coeff_modulus( + seal::CoeffModulus::BFVDefault(poly_modulus_degree)); context_ = make_unique(*(enc_params_)); // verify - if (!context_->parameters_set()) { - YACL_THROW("SEAL parameters not valid."); - } - if (!context_->using_keyswitching()) { - YACL_THROW("SEAL parameters do not support key switching."); - } - if (!context_->first_context_data()->qualifiers().using_batching) { - YACL_THROW("SEAL parameters do not support batching."); - } + YACL_ENFORCE(context_->using_keyswitching(), + "SEAL parameters do not support key switching."); + YACL_ENFORCE(context_->first_context_data()->qualifiers().using_batching, + "SEAL parameters do not support batching."); encoder_ = make_unique(*context_); - if (encoder_->slot_count() != enc_params_->poly_modulus_degree()) { - YACL_THROW("Slot count not equal to poly modulus degree"); - } - evaluator_ = std::make_unique(*context_); } -void SealPir::SetPirParams(size_t ele_num, size_t ele_size, size_t d) { +void SealPir::SetPirParams(size_t ele_num, size_t ele_size, size_t dimension) { uint32_t N = enc_params_->poly_modulus_degree(); - seal::Modulus t = enc_params_->plain_modulus(); - uint32_t logt = floor(log2(t.value())); + uint32_t logt = floor(log2(enc_params_->plain_modulus().value())); uint64_t elements_per_plaintext = ElementsPerPtxt(logt, N, ele_size); uint64_t num_of_plaintexts = PlaintextsPerDb(logt, N, ele_num, ele_size); - vector dimension_vec = GetDimensions(num_of_plaintexts, d); + uint64_t partition_size = GetPartitionSize(logt, N, ele_size); + uint64_t partition_num = (ele_size + partition_size - 1) / partition_size; - uint32_t expansion_ratio = 0; + vector dimension_vec = GetDimensions(num_of_plaintexts, dimension); + + uint32_t single_poly_expansion_ratio = 0; for (uint32_t i = 0; i < enc_params_->coeff_modulus().size(); ++i) { double logqi = log2(enc_params_->coeff_modulus()[i].value()); - expansion_ratio += ceil(logqi / logt); + single_poly_expansion_ratio += ceil(logqi / logt); } - pir_params_.dimension = d; + pir_params_.logt = logt; + pir_params_.dimension = dimension; pir_params_.ele_num = ele_num; pir_params_.ele_size = ele_size; pir_params_.elements_per_plaintext = elements_per_plaintext; pir_params_.num_of_plaintexts = num_of_plaintexts; - pir_params_.expansion_ratio = expansion_ratio << 1; + pir_params_.partition_size = partition_size; + pir_params_.partition_num = partition_num; + pir_params_.expansion_ratio = single_poly_expansion_ratio << 1; pir_params_.dimension_vec = dimension_vec; pir_params_.slot_cnt = N; pir_params_.enable_batching = true; - pir_params_.enable_symmetric = false; + pir_params_.enable_symmetric = true; pir_params_.enable_mswitching = true; + + SPDLOG_INFO("{}", pir_params_.ToString()); } -void SealPir::PrintPirParams() { - const PirParams pir_params = pir_params_; +void SealPir::PrintPirParams() const { + const SealPirParams pir_params = pir_params_; uint32_t prod = accumulate(pir_params.dimension_vec.begin(), pir_params.dimension_vec.end(), 1, multiplies()); @@ -338,10 +345,13 @@ void SealPir::PrintPirParams() { SPDLOG_INFO("Using recursive mod switching: {}", pir_params.enable_mswitching); SPDLOG_INFO("slot count: {}", pir_params.slot_cnt); + SPDLOG_INFO("partition num: {}", pir_params.partition_num); + SPDLOG_INFO("partition size: {}", pir_params.partition_size); SPDLOG_INFO("=============================="); } -string SealPir::SerializePlaintexts(const vector &plains) { +string SealPir::SerializePlaintexts( + const vector &plains) const { PlaintextsProto plains_proto; for (const auto &plain : plains) { @@ -353,7 +363,7 @@ string SealPir::SerializePlaintexts(const vector &plains) { } vector SealPir::DeSerializePlaintexts( - const string &plaintext_bytes, bool safe_load) { + const string &plaintext_bytes, bool safe_load) const { PlaintextsProto plains_proto; plains_proto.ParseFromArray(plaintext_bytes.data(), plaintext_bytes.length()); @@ -370,7 +380,7 @@ vector SealPir::DeSerializePlaintexts( } yacl::Buffer SealPir::SerializeCiphertexts( - const vector &ciphers) { + const vector &ciphers) const { CiphertextsProto ciphers_proto; for (const auto &cipher : ciphers) { @@ -385,7 +395,7 @@ yacl::Buffer SealPir::SerializeCiphertexts( } vector SealPir::DeSerializeCiphertexts( - const CiphertextsProto &ciphers_proto, bool safe_load) { + const CiphertextsProto &ciphers_proto, bool safe_load) const { vector ciphers(ciphers_proto.ciphers_size()); yacl::parallel_for(0, ciphers_proto.ciphers_size(), @@ -399,7 +409,7 @@ vector SealPir::DeSerializeCiphertexts( } vector SealPir::DeSerializeCiphertexts( - const yacl::Buffer &ciphers_buffer, bool safe_load) { + const yacl::Buffer &ciphers_buffer, bool safe_load) const { CiphertextsProto ciphers_proto; ciphers_proto.ParseFromArray(ciphers_buffer.data(), ciphers_buffer.size()); @@ -408,7 +418,7 @@ vector SealPir::DeSerializeCiphertexts( yacl::Buffer SealPir::SerializeQuery( SealPirQueryProto *query_proto, - const vector> &query_ciphers) { + const vector> &query_ciphers) const { for (const auto &query_cipher : query_ciphers) { CiphertextsProto *ciphers_proto = query_proto->add_query_cipher(); for (const auto &ciphertext : query_cipher) { @@ -424,92 +434,123 @@ yacl::Buffer SealPir::SerializeQuery( } yacl::Buffer SealPir::SerializeQuery( - const vector> &query_ciphers, size_t start_pos) { + const vector> &query_ciphers) const { SealPirQueryProto query_proto; + return SerializeQuery(&query_proto, query_ciphers); +} - query_proto.set_ind_degree(0); - query_proto.set_start_pos(start_pos); +yacl::Buffer SealPir::SerializeSeededQuery( + SealPirQueryProto *query_proto, + const vector> &query_ciphers) const { + for (const auto &query_cipher : query_ciphers) { + CiphertextsProto *ciphers_proto = query_proto->add_query_cipher(); + for (const auto &ciphertext : query_cipher) { + ciphers_proto->add_ciphers(ciphertext.data(), ciphertext.length()); + } + } - return SerializeQuery(&query_proto, query_ciphers); + yacl::Buffer b(query_proto->ByteSizeLong()); + query_proto->SerializePartialToArray(b.data(), b.size()); + return b; +} + +yacl::Buffer SealPir::SerializeSeededQuery( + const vector> &query_ciphers) const { + SealPirQueryProto query_proto; + return SerializeSeededQuery(&query_proto, query_ciphers); } vector> SealPir::DeSerializeQuery( - const SealPirQueryProto &query_proto, bool safe_load) { + const SealPirQueryProto &query_proto, bool safe_load) const { vector> pir_query(query_proto.query_cipher_size()); - yacl::parallel_for( - 0, query_proto.query_cipher_size(), [&](int64_t begin, int64_t end) { - for (int64_t i = begin; i < end; ++i) { - const auto &ciphers = query_proto.query_cipher(i); + for (int64_t i = 0; i < query_proto.query_cipher_size(); ++i) { + const auto &ciphers = query_proto.query_cipher(i); + pir_query[i].resize(ciphers.ciphers_size()); - pir_query[i].resize(ciphers.ciphers_size()); - for (int j = 0; j < ciphers.ciphers_size(); ++j) { - pir_query[i][j] = DeSerializeSealObject( - ciphers.ciphers(j), safe_load); - } - } - }); + for (int j = 0; j < ciphers.ciphers_size(); ++j) { + pir_query[i][j] = DeSerializeSealObject( + ciphers.ciphers(j), safe_load); + } + } return pir_query; } vector> SealPir::DeSerializeQuery( - const yacl::Buffer &query_buffer, bool safe_load) { + const yacl::Buffer &query_buffer, bool safe_load) const { SealPirQueryProto query_proto; query_proto.ParseFromArray(query_buffer.data(), query_buffer.size()); return DeSerializeQuery(query_proto, safe_load); } +yacl::Buffer SealPir::SerializeReply( + SealPirReplyProto *reply_proto, + const vector> &reply_ciphers) const { + for (const auto &reply_cipher : reply_ciphers) { + CiphertextsProto *ciphers_proto = reply_proto->add_reply_cipher(); + for (const auto &ciphertext : reply_cipher) { + string cipher_bytes = SerializeSealObject(ciphertext); + ciphers_proto->add_ciphers(cipher_bytes.data(), cipher_bytes.length()); + } + } + yacl::Buffer b(reply_proto->ByteSizeLong()); + reply_proto->SerializePartialToArray(b.data(), b.size()); + return b; +} +yacl::Buffer SealPir::SerializeReply( + const vector> &reply_ciphers) const { + SealPirReplyProto reply_proto; + return SerializeReply(&reply_proto, reply_ciphers); +} +std::vector> SealPir::DeSerializeReply( + const SealPirReplyProto &reply_proto, bool safe_load) const { + vector> pir_reply(reply_proto.reply_cipher_size()); + yacl::parallel_for( + 0, reply_proto.reply_cipher_size(), [&](int64_t begin, int64_t end) { + for (int64_t i = begin; i < end; ++i) { + const auto &ciphers = reply_proto.reply_cipher(i); + pir_reply[i].resize(ciphers.ciphers_size()); + for (int j = 0; j < ciphers.ciphers_size(); ++j) { + pir_reply[i][j] = DeSerializeSealObject( + ciphers.ciphers(j), safe_load); + } + } + }); + return pir_reply; +} +std::vector> SealPir::DeSerializeReply( + const yacl::Buffer &reply_buffer, bool safe_load) const { + SealPirReplyProto reply_proto; + reply_proto.ParseFromArray(reply_buffer.data(), reply_buffer.size()); + return DeSerializeReply(reply_proto, safe_load); +} + /********************************************************************************** SealPirServer **********************************************************************************/ - -SealPirServer::SealPirServer(const SealPirOptions &options, - shared_ptr plaintext_store) - : SealPir(options), - plaintext_store_(std::move(plaintext_store)), - is_db_preprocessed_(false) {} - -void SealPirServer::SetDatabase(const vector &db_vec) { - vector db_flatten_bytes(db_vec.size() * options_.element_size); - for (uint32_t i = 0; i < db_vec.size(); ++i) { - YACL_ENFORCE_EQ(db_vec[i].size(), options_.element_size); - memcpy(&db_flatten_bytes[i * options_.element_size], db_vec[i].data(), - db_vec[i].size()); - } - - shared_ptr db_provider = - make_shared(std::move(db_flatten_bytes), - options_.element_size); - - return SetDatabaseByProvider(db_provider); +SealPirServer::SealPirServer(const SealPirOptions &options) + : SealPir(options), db_seted_(false) { + plaintext_store_.resize(pir_params_.partition_num); + for_each(plaintext_store_.begin(), plaintext_store_.end(), + [](shared_ptr &ptr) { + ptr = make_shared(); + }); } -void SealPirServer::SetDatabaseByProvider( - const shared_ptr &db_provider) { - uint64_t db_size = options_.element_number * pir_params_.ele_size; - YACL_ENFORCE_EQ(db_provider->GetDbByteSize(), db_size); +void SealPirServer::SetDatabase( + const psi::pir_utils::RawDatabase &raw_database) { + vector partition_db = + raw_database.Partition(pir_params_.partition_size); + YACL_ENFORCE_EQ(pir_params_.partition_num, partition_db.size()); uint32_t N = enc_params_->poly_modulus_degree(); uint32_t logt = floor(log2(enc_params_->plain_modulus().value())); uint64_t num_of_ptxt = pir_params_.num_of_plaintexts; uint64_t ele_per_ptxt = pir_params_.elements_per_plaintext; - uint64_t bytes_per_ptxt = ele_per_ptxt * pir_params_.ele_size; - uint64_t coeffs_per_ele = CoefficientsPerElement(logt, pir_params_.ele_size); - uint64_t coeffs_per_ptxt = ele_per_ptxt * coeffs_per_ele; - YACL_ENFORCE_LE(coeffs_per_ptxt, N); - - uint64_t db_num; - if (options_.ind_degree == 0) { - db_num = 1; - num_of_ptxt = - PlaintextsPerDb(logt, N, options_.element_number, pir_params_.ele_size); - } else { - db_num = ceil((double)options_.element_number / options_.ind_degree); - num_of_ptxt = - PlaintextsPerDb(logt, N, options_.ind_degree, pir_params_.ele_size); - } + + uint64_t db_num = 1; uint64_t prod = 1; for (uint32_t i = 0; i < pir_params_.dimension; ++i) { @@ -517,226 +558,247 @@ void SealPirServer::SetDatabaseByProvider( } YACL_ENFORCE_GT(prod, num_of_ptxt); - plaintext_store_->SetSubDbNumber(db_num); - - for (uint64_t db_idx = 0; db_idx < db_num; ++db_idx) { - vector db_vec; - db_vec.reserve(prod); + uint64_t partition_num = pir_params_.partition_num; + + for (uint64_t partition_idx = 0; partition_idx < partition_num; + ++partition_idx) { + plaintext_store_[partition_idx]->SetSubDbNumber(db_num); + uint64_t loc_ele_size = partition_db[partition_idx].At(0).size(); + + uint64_t bytes_per_ptxt = ele_per_ptxt * loc_ele_size; + uint64_t coeffs_per_ele = CoefficientsPerElement(logt, loc_ele_size); + uint64_t coeffs_per_ptxt = ele_per_ptxt * coeffs_per_ele; + YACL_ENFORCE(coeffs_per_ptxt <= N); + + for (uint64_t db_idx = 0; db_idx < db_num; ++db_idx) { + vector<Plaintext> db_vec; + db_vec.reserve(prod); + + uint32_t offset = 0; + for (uint64_t i = 0; i < num_of_ptxt; ++i) { + uint32_t process_bytes = 0; + + vector<uint8_t> bytes; + bytes.reserve(bytes_per_ptxt); + while (process_bytes + loc_ele_size <= bytes_per_ptxt && + offset < pir_params_.ele_num) { + process_bytes += loc_ele_size; + bytes.insert(bytes.end(), + partition_db[partition_idx].At(offset).begin(), + partition_db[partition_idx].At(offset).end()); + offset++; + } + YACL_ENFORCE_EQ(bytes.size(), process_bytes); + + uint64_t ele_in_chunk = process_bytes / loc_ele_size; + + vector<uint64_t> coeffs(coeffs_per_ptxt); + for (uint64_t ele = 0; ele < ele_in_chunk; ++ele) { + vector<uint64_t> ele_coeffs = BytesToCoeffs( + logt, + gsl::span<uint8_t>(bytes.data() + (loc_ele_size * ele), + bytes.data() + (loc_ele_size * (ele + 1)))); + copy(ele_coeffs.begin(), ele_coeffs.end(), + coeffs.begin() + coeffs_per_ele * ele); + } - uint32_t offset = db_idx * options_.ind_degree * pir_params_.ele_size; + uint64_t used = coeffs.size(); + YACL_ENFORCE_LE(used, coeffs_per_ptxt); - for (uint64_t i = 0; i < num_of_ptxt; ++i) { - uint32_t process_bytes = 0; + // padding + for (uint64_t j = 0; j < (N - used); ++j) { + coeffs.push_back(1); + } - if (offset >= db_size) { - break; - } else if (offset + bytes_per_ptxt >= db_size) { - process_bytes = db_size - offset; - } else { - process_bytes = bytes_per_ptxt; - } - YACL_ENFORCE_EQ(process_bytes % pir_params_.ele_size, 0UL); - - vector<uint8_t> bytes = db_provider->ReadElement(offset, process_bytes); - uint64_t ele_in_chunk = process_bytes / pir_params_.ele_size; - - vector<uint64_t> coeffs(coeffs_per_ptxt); - for (uint64_t ele = 0; ele < ele_in_chunk; ++ele) { - vector<uint64_t> ele_coeffs = BytesToCoeffs( - logt, gsl::span<uint8_t>( - bytes.data() + (pir_params_.ele_size * ele), - bytes.data() + (pir_params_.ele_size * (ele + 1)))); - copy(ele_coeffs.begin(), ele_coeffs.end(), - coeffs.begin() + coeffs_per_ele * ele); + Plaintext plain; + encoder_->encode(coeffs, plain); + db_vec.emplace_back(std::move(plain)); } - offset += process_bytes; - uint64_t used = coeffs.size(); - YACL_ENFORCE_LE(used, coeffs_per_ptxt); + uint64_t current_ptxts = db_vec.size(); + uint64_t matrix_ptxts = prod; + YACL_ENFORCE_LE(current_ptxts, num_of_ptxt); + + vector<uint64_t> padding(N, 1); - // padding - for (uint64_t j = 0; j < (N - used); ++j) { - coeffs.push_back(1); + for (uint64_t i = 0; i < (matrix_ptxts - current_ptxts); ++i) { + Plaintext plain; + VectorToPlaintext(padding, plain); + db_vec.push_back(plain); } - Plaintext plain; - encoder_->encode(coeffs, plain); - db_vec.push_back(std::move(plain)); + yacl::parallel_for(0, db_vec.size(), [&](int64_t begin, int64_t end) { + for (uint32_t i = begin; i < end; i++) { + evaluator_->transform_to_ntt_inplace(db_vec[i], + context_->first_parms_id()); + } + }); + plaintext_store_[partition_idx]->SavePlaintexts(db_vec, db_idx); } + } - uint64_t current_ptxts = db_vec.size(); - uint64_t matrix_ptxts = prod; - YACL_ENFORCE_LE(current_ptxts, num_of_ptxt); - - vector<uint64_t> padding(N, 1); - - for (uint64_t i = 0; i < (matrix_ptxts - current_ptxts); ++i) { - Plaintext plain; - VectorToPlaintext(padding, plain); - db_vec.push_back(plain); - } + db_seted_ = true; +} - yacl::parallel_for(0, db_vec.size(), [&](int64_t begin, int64_t end) { - for (uint32_t i = begin; i < end; i++) { - evaluator_->transform_to_ntt_inplace(db_vec[i], - context_->first_parms_id()); - } - }); - plaintext_store_->SavePlaintexts(db_vec, db_idx); +void SealPirServer::SetDatabase(const vector<yacl::ByteContainerView> &db_vec) { + vector<vector<uint8_t>> db_flatten_bytes(db_vec.size()); + for (uint32_t i = 0; i < db_vec.size(); ++i) { + db_flatten_bytes[i].resize(pir_params_.ele_size); + YACL_ENFORCE_EQ(db_vec[i].size(), pir_params_.ele_size); + memcpy(db_flatten_bytes[i].data(), db_vec[i].data(), db_vec[i].size()); } - is_db_preprocessed_ = true; + psi::pir_utils::RawDatabase rawDatabase(std::move(db_flatten_bytes)); + + return SetDatabase(rawDatabase); } -yacl::Buffer SealPirServer::GenerateIndexReply( - const yacl::Buffer &query_buffer) { +yacl::Buffer SealPirServer::GenerateIndexResponse( + const yacl::Buffer &query_buffer) const { SealPirQueryProto query_proto; query_proto.ParseFromArray(query_buffer.data(), query_buffer.size()); PirQuery query = DeSerializeQuery(query_proto); - yacl::Buffer reply_buffer = - SerializeCiphertexts(GenerateReply(query, query_proto.start_pos(), 0)); + yacl::Buffer reply_buffer = SerializeReply(GenerateResponse(query, 0)); return reply_buffer; } -SealPir::PirReply SealPirServer::GenerateReply(const SealPir::PirQuery &query, - uint32_t start_pos, - uint32_t client_id) { +SealPir::PirReply SealPirServer::GenerateResponse( + const SealPir::PirQuery &query, uint32_t client_id) const { int N = enc_params_->poly_modulus_degree(); uint32_t expansion_ratio = pir_params_.expansion_ratio; vector<uint64_t> dimension_vec = pir_params_.dimension_vec; - uint32_t sub_db_idx = 0; - if (options_.ind_degree > 0) { - YACL_ENFORCE_EQ(start_pos % options_.ind_degree, 0UL); - sub_db_idx = start_pos / options_.ind_degree; - } - vector<Plaintext> db_plaintext = plaintext_store_->ReadPlaintexts(sub_db_idx); + PirReply reply; + reply.reserve(pir_params_.partition_num); + for (uint64_t partition_idx = 0; partition_idx < pir_params_.partition_num; + ++partition_idx) { + uint64_t prod = 1; + for (uint32_t i = 0; i < dimension_vec.size(); ++i) { + prod *= dimension_vec[i]; + } - vector<Plaintext> *cur = &db_plaintext; - vector<Plaintext> intermediate_plain; + vector<Plaintext> db_plaintext = + plaintext_store_[partition_idx]->ReadPlaintexts(0); - uint64_t prod = 1; - for (uint32_t i = 0; i < dimension_vec.size(); ++i) { - prod *= dimension_vec[i]; - } + vector<Plaintext> *cur = &db_plaintext; + vector<Plaintext> intermediate_plain; - for (uint32_t i = 0; i < dimension_vec.size(); ++i) { - SPDLOG_INFO("Server: {}-th recursion level started ", i + 1); - vector<Ciphertext> expanded_query; - uint64_t ni = dimension_vec[i]; - - for (uint32_t j = 0; j < query[i].size(); ++j) { - uint64_t total = N; - - if (j == query[i].size() - 1) { - uint64_t ni_mod_N = ni % N; - // add the branch to handle the case that ni mod N == 0 - if (ni_mod_N != 0) { - total = ni_mod_N; + for (uint32_t i = 0; i < dimension_vec.size(); ++i) { + SPDLOG_DEBUG("Server: {}-th recursion level started ", i + 1); + vector<Ciphertext> expanded_query; + uint64_t ni = dimension_vec[i]; + + for (uint32_t j = 0; j < query[i].size(); ++j) { + uint64_t total = N; + + if (j == query[i].size() - 1) { + uint64_t ni_mod_N = ni % N; + // add the branch to handle the case that ni mod N == 0 + if (ni_mod_N != 0) { + total = ni_mod_N; + } } - } - vector<Ciphertext> part_expanded_query = - ExpandQuery(query[i][j], total, client_id); + vector<Ciphertext> part_expanded_query = + ExpandQuery(query[i][j], total, client_id); - expanded_query.insert(expanded_query.end(), - make_move_iterator(part_expanded_query.begin()), - make_move_iterator(part_expanded_query.end())); - part_expanded_query.clear(); - } - YACL_ENFORCE_EQ(expanded_query.size(), ni); + expanded_query.insert(expanded_query.end(), + make_move_iterator(part_expanded_query.begin()), + make_move_iterator(part_expanded_query.end())); + part_expanded_query.clear(); + } + YACL_ENFORCE_EQ(expanded_query.size(), ni); - yacl::parallel_for( - 0, expanded_query.size(), [&](uint32_t begin, uint32_t end) { + yacl::parallel_for( + 0, expanded_query.size(), [&](uint32_t begin, uint32_t end) { + for (uint32_t jj = begin; jj < end; ++jj) { + evaluator_->transform_to_ntt_inplace(expanded_query[jj]); + } + }); + + if ((!db_seted_) || i > 0) { + yacl::parallel_for(0, cur->size(), [&](uint32_t begin, uint32_t end) { for (uint32_t jj = begin; jj < end; ++jj) { - evaluator_->transform_to_ntt_inplace(expanded_query[jj]); + evaluator_->transform_to_ntt_inplace((*cur)[jj], + context_->first_parms_id()); } }); + } - if ((!is_db_preprocessed_) || i > 0) { - yacl::parallel_for(0, cur->size(), [&](uint32_t begin, uint32_t end) { - for (uint32_t jj = begin; jj < end; ++jj) { - evaluator_->transform_to_ntt_inplace((*cur)[jj], - context_->first_parms_id()); - } - }); - } - - prod /= ni; + prod /= ni; - vector<Ciphertext> intermediateCtxts(prod); + vector<Ciphertext> intermediateCtxts(prod); - yacl::parallel_for(0, prod, [&](int64_t begin, int64_t end) { - for (int k = begin; k < end; ++k) { - evaluator_->multiply_plain(expanded_query[0], (*cur)[k], - intermediateCtxts[k]); + yacl::parallel_for(0, prod, [&](int64_t begin, int64_t end) { + for (int k = begin; k < end; ++k) { + evaluator_->multiply_plain(expanded_query[0], (*cur)[k], + intermediateCtxts[k]); - Ciphertext tmp; - for (uint64_t j = 1; j < ni; ++j) { - evaluator_->multiply_plain(expanded_query[j], (*cur)[j * prod + k], - tmp); - evaluator_->add_inplace(intermediateCtxts[k], tmp); + Ciphertext tmp; + for (uint64_t j = 1; j < ni; ++j) { + evaluator_->multiply_plain(expanded_query[j], (*cur)[j * prod + k], + tmp); + evaluator_->add_inplace(intermediateCtxts[k], tmp); + } } - } - }); + }); - yacl::parallel_for( - 0, intermediateCtxts.size(), [&](int64_t begin, int64_t end) { - for (uint32_t jj = begin; jj < end; jj++) { - evaluator_->transform_from_ntt_inplace(intermediateCtxts[jj]); - } - }); + yacl::parallel_for( + 0, intermediateCtxts.size(), [&](int64_t begin, int64_t end) { + for (uint32_t jj = begin; jj < end; jj++) { + evaluator_->transform_from_ntt_inplace(intermediateCtxts[jj]); + } + }); - if (i == dimension_vec.size() - 1) { - return intermediateCtxts; - } else { - intermediate_plain.clear(); - intermediate_plain.reserve(expansion_ratio * prod); - cur = &intermediate_plain; - - for (uint32_t j = 0; j < prod; ++j) { - EncryptionParameters parms; - if (pir_params_.enable_mswitching) { - evaluator_->mod_switch_to_inplace(intermediateCtxts[j], - context_->last_parms_id()); - parms = context_->last_context_data()->parms(); - } else { - parms = context_->first_context_data()->parms(); - } + if (i == dimension_vec.size() - 1) { + reply.emplace_back(std::move(intermediateCtxts)); + break; + } else { + intermediate_plain.clear(); + intermediate_plain.reserve(expansion_ratio * prod); + cur = &intermediate_plain; + + for (uint32_t j = 0; j < prod; ++j) { + EncryptionParameters parms; + if (pir_params_.enable_mswitching) { + evaluator_->mod_switch_to_inplace(intermediateCtxts[j], + context_->last_parms_id()); + parms = context_->last_context_data()->parms(); + } else { + parms = context_->first_context_data()->parms(); + } - vector<Plaintext> part_intermediate_plain = - DecomposeToPlaintexts(parms, intermediateCtxts[j]); + vector<Plaintext> part_intermediate_plain = + DecomposeToPlaintexts(parms, intermediateCtxts[j]); - intermediate_plain.insert( - intermediate_plain.end(), - make_move_iterator(part_intermediate_plain.begin()), - make_move_iterator(part_intermediate_plain.end())); + intermediate_plain.insert( + intermediate_plain.end(), + make_move_iterator(part_intermediate_plain.begin()), + make_move_iterator(part_intermediate_plain.end())); + } + prod = intermediate_plain.size(); } - prod = intermediate_plain.size(); } } - YACL_ENFORCE(0); - vector<Ciphertext> fail(1); - return fail; + return reply; } inline vector<Ciphertext> SealPirServer::ExpandQuery( - const seal::Ciphertext &encrypted, uint64_t m, uint32_t client_id) { + const seal::Ciphertext &encrypted, uint64_t m, uint32_t client_id) const { SPDLOG_INFO("expanding query......"); int N = enc_params_->poly_modulus_degree(); uint32_t logm = ceil(log2(m)); YACL_ENFORCE_LE(logm, ceil(log2(N))); - // handle the case that m = 1, logm = 0 if (logm == 0) { vector<Ciphertext> result(1, encrypted); return result; } - GaloisKeys &galkey = galoisKeys_[client_id]; + const GaloisKeys &galkey = galois_keys_.at(client_id); vector<int> galelts; for (int i = 0; i < ceil(log2(N)); ++i) { galelts.push_back((N + seal::util::exponentiate_uint(2, i)) / @@ -796,7 +858,7 @@ inline vector<Ciphertext> SealPirServer::ExpandQuery( inline void SealPirServer::MultiplyPowerOfX(const Ciphertext &encrypted, Ciphertext &destination, - uint32_t index) { + uint32_t index) const { int N = enc_params_->poly_modulus_degree(); size_t coeff_mod_cnt = enc_params_->coeff_modulus().size() - 1; size_t encrypted_cnt = encrypted.size(); @@ -813,10 +875,10 @@ inline void SealPirServer::MultiplyPowerOfX(const Ciphertext &encrypted, } void SealPirServer::SetGaloisKey(uint32_t client_id, seal::GaloisKeys galkey) { - galoisKeys_[client_id] = galkey; + galois_keys_[client_id] = galkey; } -string SealPirServer::SerializeDbPlaintext(int db_index) { +string SealPirServer::SerializeDbPlaintext(int db_index) const { return SerializePlaintexts(*db_vec_[db_index].get()); } @@ -828,11 +890,6 @@ void SealPirServer::DeSerializeDbPlaintext(const string &db_serialize_bytes, db_vec_[db_index] = make_unique<vector<seal::Plaintext>>(plaintext_vec); } -void SealPirServer::SetOneCt(Ciphertext one) { - one_ = one; - evaluator_->transform_to_ntt_inplace(one_); -} - /********************************************************************************** SealPirClient **********************************************************************************/ @@ -849,38 +906,40 @@ SealPirClient::SealPirClient(const SealPirOptions &options) : SealPir(options) { decryptor_ = make_unique<seal::Decryptor>(*context_, secret_key); } -yacl::Buffer SealPirClient::GenerateIndexQuery(uint64_t ele_index, - uint64_t &offset) { - uint64_t query_index = ele_index; - size_t start_pos = 0; - if (options_.ind_degree > 0) { - query_index = ele_index % options_.ind_degree; - start_pos = ele_index - query_index; - } - - uint64_t index = GetFVIndex(query_index); - offset = GetFVOffset(query_index); - yacl::Buffer query_buffer = SerializeQuery(GenerateQuery(index), start_pos); +// std::pair<yacl::Buffer, uint64_t> SealPirClient::GenerateIndexQuery( +// uint64_t raw_idx) const { +// uint64_t pt_idx = GetPtIndex(raw_idx); +// uint64_t pt_offset = GetPtOffset(raw_idx); +// // we default use the seed to compress our query ciphertext +// yacl::Buffer query_buffer = +// SerializeSeededQuery(GenerateSeededQuery(pt_idx)); return {query_buffer, +// pt_offset}; +// } + +yacl::Buffer SealPirClient::GenerateIndexQuery(uint64_t raw_idx) const { + uint64_t pt_idx = GetPtIndex(raw_idx); + // we default use the seed to compress our query ciphertext + yacl::Buffer query_buffer = SerializeSeededQuery(GenerateSeededQuery(pt_idx)); return query_buffer; } -SealPir::PirQuery SealPirClient::GenerateQuery(uint64_t index) { - indices_ = ComputeIndices(index, pir_params_.dimension_vec); +SealPir::PirQuery SealPirClient::GenerateQuery(uint64_t pt_idx) const { + std::vector<uint64_t> indices = + ComputeIndices(pt_idx, pir_params_.dimension_vec); SealPir::PirQuery result(pir_params_.dimension); int N = enc_params_->poly_modulus_degree(); - Plaintext pt(enc_params_->poly_modulus_degree()); - for (uint32_t i = 0; i < indices_.size(); ++i) { + Plaintext pt(N); + for (uint32_t i = 0; i < indices.size(); ++i) { uint32_t num_ptxts = ceil(pir_params_.dimension_vec[i] / (double)N); for (uint32_t j = 0; j < num_ptxts; ++j) { pt.set_zero(); - if (indices_[i] >= j * N && indices_[i] < (j + 1) * N) { - uint64_t real_index = indices_[i] - j * N; + if (indices[i] >= j * N && indices[i] < (j + 1) * N) { + uint64_t real_index = indices[i] - j * N; uint64_t ni = pir_params_.dimension_vec[i]; - uint64_t total = N; if (j == num_ptxts - 1) { uint64_t ni_mod_N = ni % N; @@ -889,17 +948,52 @@ SealPir::PirQuery SealPirClient::GenerateQuery(uint64_t index) { } } uint64_t logm = ceil(log2(total)); - pt[real_index] = InvertMod(pow(2, logm), enc_params_->plain_modulus()); } - + // note that here Ciphertext is Serializable<Ciphertext> Ciphertext ct; if (pir_params_.enable_symmetric) { encryptor_->encrypt_symmetric(pt, ct); } else { encryptor_->encrypt(pt, ct); } + result[i].push_back(ct); + } + } + return result; +} + +SealPir::PirSeededQuery SealPirClient::GenerateSeededQuery( + uint64_t pt_idx) const { + std::vector<uint64_t> indices = + ComputeIndices(pt_idx, pir_params_.dimension_vec); + + SealPir::PirSeededQuery result(pir_params_.dimension); + int N = enc_params_->poly_modulus_degree(); + + Plaintext pt(N); + for (uint32_t i = 0; i < indices.size(); ++i) { + uint32_t num_ptxts = ceil(pir_params_.dimension_vec[i] / (double)N); + for (uint32_t j = 0; j < num_ptxts; ++j) { + pt.set_zero(); + if (indices[i] >= j * N && indices[i] < (j + 1) * N) { + uint64_t real_index = indices[i] - j * N; + uint64_t ni = pir_params_.dimension_vec[i]; + uint64_t total = N; + if (j == num_ptxts - 1) { + uint64_t ni_mod_N = ni % N; + if (ni_mod_N != 0) { + total = ni_mod_N; + } + } + uint64_t logm = ceil(log2(total)); + pt[real_index] = InvertMod(pow(2, logm), enc_params_->plain_modulus()); + } + // encryptor_->encrypt_symmetric(pt) will return a + // Serializable<Ciphertext> this is a compressed Ciphertext using seed in + // SEAL lib. + string ct = SerializeSealObject(encryptor_->encrypt_symmetric(pt)); result[i].push_back(ct); } } @@ -907,20 +1001,34 @@ SealPir::PirQuery SealPirClient::GenerateQuery(uint64_t index) { return result; } -vector<uint8_t> SealPirClient::DecodeIndexReply( - const yacl::Buffer &reply_buffer, uint64_t offset) { - PirReply reply = DeSerializeCiphertexts(reply_buffer); - vector<uint8_t> elems = DecodeReply(reply, offset); +vector<uint8_t> SealPirClient::DecodeIndexResponse( + const yacl::Buffer &response_buffer, uint64_t raw_idx) const { + PirReply reply = DeSerializeReply(response_buffer); + vector<uint8_t> elems = DecodeResponse(reply, raw_idx); return elems; } -vector<uint8_t> SealPirClient::DecodeReply(SealPir::PirReply &reply, - uint64_t offset) { - Plaintext ptxt = DecodeReply(reply); - return ExtractBytes(ptxt, offset); +vector<uint8_t> SealPirClient::DecodeResponse(SealPir::PirReply &response, + uint64_t raw_idx) const { + vector<Plaintext> ptxt = DecodeResponse(response); + uint64_t offset = GetPtOffset(raw_idx); + YACL_ENFORCE_EQ(ptxt.size(), pir_params_.partition_num); + vector<uint8_t> decoded; + decoded.reserve(pir_params_.partition_num); + for (uint64_t i = 0; i < pir_params_.partition_num; ++i) { + uint64_t loc_ele_size = pir_params_.partition_size; + if (i == pir_params_.partition_num - 1) { + loc_ele_size = pir_params_.ele_size - i * pir_params_.partition_size; + } + vector<uint8_t> tmp = ExtractBytes(ptxt[i], offset, loc_ele_size); + decoded.insert(decoded.end(), make_move_iterator(tmp.begin()), + make_move_iterator(tmp.end())); + } + return decoded; } -Plaintext SealPirClient::DecodeReply(SealPir::PirReply &reply) { +std::vector<seal::Plaintext> SealPirClient::DecodeResponse( + SealPir::PirReply &reply) const { EncryptionParameters parms; parms_id_type parms_id; if (pir_params_.enable_mswitching) { @@ -933,42 +1041,45 @@ Plaintext SealPirClient::DecodeReply(SealPir::PirReply &reply) { uint32_t expansion_ratio = ComputeExpansionRatio(parms); uint32_t d = pir_params_.dimension; - vector<Ciphertext> tmp = reply; - uint32_t ct_poly_count = tmp[0].size(); - for (uint32_t i = 0; i < d; ++i) { - vector<Ciphertext> newtmp; - vector<Plaintext> tmpplain; + vector<Plaintext> decoded; + for (uint64_t partition_idx = 0; partition_idx < pir_params_.partition_num; + ++partition_idx) { + vector<Ciphertext> tmp = reply[partition_idx]; + uint32_t ct_poly_count = tmp[0].size(); + for (uint32_t i = 0; i < d; ++i) { + vector<Ciphertext> newtmp; + vector<Plaintext> tmpplain; - for (uint32_t j = 0; j < tmp.size(); ++j) { - Plaintext ptxt; - decryptor_->decrypt(tmp[j], ptxt); - tmpplain.push_back(ptxt); + for (uint32_t j = 0; j < tmp.size(); ++j) { + Plaintext ptxt; + decryptor_->decrypt(tmp[j], ptxt); + tmpplain.push_back(ptxt); - if (j != 0 && (j + 1) % (expansion_ratio * ct_poly_count) == 0) { - Ciphertext ctxt(*context_, parms_id); - ComposeToCiphertext(parms, tmpplain, ctxt); + if (j != 0 && (j + 1) % (expansion_ratio * ct_poly_count) == 0) { + Ciphertext ctxt(*context_, parms_id); + ComposeToCiphertext(parms, tmpplain, ctxt); - newtmp.push_back(ctxt); + newtmp.push_back(ctxt); - tmpplain.clear(); + tmpplain.clear(); + } } - } - if (i == d - 1) { - YACL_ENFORCE_EQ(tmp.size(), 1UL); - return tmpplain[0]; - } else { - tmpplain.clear(); - tmp = newtmp; + if (i == d - 1) { + YACL_ENFORCE_EQ(tmp.size(), 1UL); + decoded.emplace_back(std::move(tmpplain[0])); + break; + } else { + tmpplain.clear(); + tmp = newtmp; + } } } - YACL_ENFORCE(0); - Plaintext fail; - return fail; + return decoded; } -seal::GaloisKeys SealPirClient::GenerateGaloisKeys() { +seal::GaloisKeys SealPirClient::GenerateGaloisKeys() const { vector<uint32_t> galois_elts; int N = enc_params_->poly_modulus_degree(); int logN = seal::util::get_power_of_two(N); @@ -983,23 +1094,17 @@ seal::GaloisKeys SealPirClient::GenerateGaloisKeys() { return gal_keys; } -uint64_t SealPirClient::GetFVIndex(uint64_t element_index) { +uint64_t SealPirClient::GetPtIndex(uint64_t element_index) const { return static_cast<uint64_t>(element_index / pir_params_.elements_per_plaintext); } -uint64_t SealPirClient::GetFVOffset(uint64_t element_index) { +uint64_t SealPirClient::GetPtOffset(uint64_t element_index) const { return element_index % pir_params_.elements_per_plaintext; } -Plaintext SealPirClient::Decrypt(Ciphertext ct) { - Plaintext pt; - decryptor_->decrypt(ct, pt); - return pt; -} - -vector<uint8_t> SealPirClient::ExtractBytes(seal::Plaintext pt, - uint64_t offset) { +vector<uint8_t> SealPirClient::ExtractBytes(seal::Plaintext pt, uint64_t offset, + uint64_t loc_ele_size) const { uint32_t logt = floor(log2(enc_params_->plain_modulus().value())); uint64_t bytes_per_ptxt = pir_params_.elements_per_plaintext * pir_params_.ele_size; @@ -1009,19 +1114,8 @@ vector<uint8_t> SealPirClient::ExtractBytes(seal::Plaintext pt, encoder_->decode(pt, coeffs); CoeffsToBytes(logt, coeffs, elems, pir_params_.ele_size); - return vector<uint8_t>(elems.begin() + offset * pir_params_.ele_size, - elems.begin() + (offset + 1) * pir_params_.ele_size); -} - -Ciphertext SealPirClient::GetOne() { - Plaintext pt("1"); - Ciphertext ct; - if (pir_params_.enable_symmetric) { - encryptor_->encrypt_symmetric(pt, ct); - } else { - encryptor_->encrypt(pt, ct); - } - return ct; + return vector<uint8_t>(elems.begin() + offset * loc_ele_size, + elems.begin() + (offset + 1) * loc_ele_size); } } // namespace psi::sealpir diff --git a/psi/algorithm/sealpir/seal_pir.h b/psi/algorithm/sealpir/seal_pir.h index eb18f291..d9a7c7d3 100644 --- a/psi/algorithm/sealpir/seal_pir.h +++ b/psi/algorithm/sealpir/seal_pir.h @@ -23,68 +23,82 @@ #include "seal/util/polyarithsmallmod.h" #include "yacl/base/byte_container_view.h" -#include "psi/algorithm/kwpir/index_pir.h" +#include "psi/algorithm/pir_interface/index_pir.h" +#include "psi/algorithm/pir_interface/pir_db.h" #include "psi/algorithm/sealpir/seal_pir_utils.h" #include "psi/algorithm/sealpir/serializable.pb.h" namespace psi::sealpir { -struct PirParams { - bool enable_symmetric; - bool enable_batching; // pack as many elements as possible into a BFV - // plaintext (recommended) - bool enable_mswitching; - uint64_t ele_num; - uint64_t ele_size; - uint64_t elements_per_plaintext; - uint64_t num_of_plaintexts; - uint32_t expansion_ratio; - uint32_t dimension; - std::vector<uint64_t> dimension_vec; - uint32_t slot_cnt; -}; - +// user-defined options struct SealPirOptions { // RLWE polynomial degree - uint32_t poly_modulus_degree; + uint32_t poly_modulus_degree = 4096; // db element number - uint64_t element_number; + uint64_t element_number = 0; // byte size of per element - uint64_t element_size; - // number of real query data - uint64_t ind_degree = 0; + uint64_t element_size = 0; // number of dimension - uint32_t dimension = 0; + uint32_t dimension = 2; // log2 of plaintext modulus uint32_t logt = 20; }; class SealPir { public: + // we can construct SealPirParams from SealPirOptions + struct SealPirParams { + uint64_t ele_num = 0; + uint64_t ele_size = 0; + uint64_t elements_per_plaintext = 0; + uint64_t num_of_plaintexts = 0; + uint64_t partition_size = 0; + uint64_t partition_num = 1; + uint32_t expansion_ratio = 0; + uint32_t dimension = 2; + std::vector<uint64_t> dimension_vec; + uint32_t slot_cnt = 0; + uint32_t logt = 0; + bool enable_symmetric = true; + bool enable_batching = true; + bool enable_mswitching = true; + + std::string ToString() { + std::ostringstream ss; + ss << "PirParams: " << "\n"; + ss << "database rows: " << ele_num << ", each row length: " << ele_size + << " bytes"; + ss << ", poly degree: " << slot_cnt << ", logt: " << logt + << ", number of plaintexts: " << num_of_plaintexts; + ss << ", dimension:{"; + for (size_t i = 0; i < dimension_vec.size(); ++i) { + ss << dimension_vec[i]; + ss << (i + 1 == dimension_vec.size() ? "}" : ", "); + } + return ss.str(); + } + }; + using PirQuery = std::vector<std::vector<seal::Ciphertext>>; - using PirReply = std::vector<seal::Ciphertext>; + // we use the seal::Serializable<seal::Ciphertext>> to compress the query + using PirSeededQuery = std::vector<std::vector<std::string>>; + using PirReply = std::vector<std::vector<seal::Ciphertext>>; using Database = std::vector<seal::Plaintext>; - explicit SealPir(const SealPirOptions &options) : options_(options) { + explicit SealPir(const SealPirOptions &options) { // init some Seal Object and verify - SetSealContext(options.poly_modulus_degree); - - if (options.ind_degree > 0) { - SetPirParams(options.ind_degree, options.element_size, options.dimension); - } else { - SetPirParams(options.element_number, options.element_size, - options.dimension); - } + SetSealContext(options.poly_modulus_degree, options.logt); + SetPirParams(options.element_number, options.element_size, + options.dimension); } - void SetSealContext(size_t degree); - void VerifyEncryptionParams(); - void SetPirParams(size_t ele_num, size_t ele_size, size_t d); - void PrintPirParams(); + void SetSealContext(size_t poly_modulus_degree, size_t logt); + void SetPirParams(size_t ele_num, size_t ele_size, size_t dimension); + void PrintPirParams() const; template <typename T> - std::string SerializeSealObject(const T &object) { + std::string SerializeSealObject(const T &object) const { std::ostringstream output; object.save(output); return output.str(); @@ -92,7 +106,7 @@ class SealPir { template <typename T> T DeSerializeSealObject(const std::string &object_bytes, - bool safe_load = false) { + bool safe_load = false) const { T seal_object; std::istringstream object_input(object_bytes); if (safe_load) { @@ -103,115 +117,135 @@ class SealPir { return seal_object; } - std::string SerializePlaintexts(const std::vector<seal::Plaintext> &plains); + std::string SerializePlaintexts( + const std::vector<seal::Plaintext> &plains) const; std::vector<seal::Plaintext> DeSerializePlaintexts( - const std::string &plaintext_bytes, bool safe_load = false); + const std::string &plaintext_bytes, bool safe_load = false) const; yacl::Buffer SerializeCiphertexts( - const std::vector<seal::Ciphertext> &ciphers); + const std::vector<seal::Ciphertext> &ciphers) const; std::vector<seal::Ciphertext> DeSerializeCiphertexts( - const CiphertextsProto &ciphers_proto, bool safe_load = false); + const CiphertextsProto &ciphers_proto, bool safe_load = false) const; std::vector<seal::Ciphertext> DeSerializeCiphertexts( - const yacl::Buffer &ciphers_buffer, bool safe_load = false); + const yacl::Buffer &ciphers_buffer, bool safe_load = false) const; + + yacl::Buffer SerializeReply( + SealPirReplyProto *reply_proto, + const std::vector<std::vector<seal::Ciphertext>> &reply_ciphers) const; + yacl::Buffer SerializeReply( + const std::vector<std::vector<seal::Ciphertext>> &reply_ciphers) const; + std::vector<std::vector<seal::Ciphertext>> DeSerializeReply( + const yacl::Buffer &reply_buffer, bool safe_load = false) const; + std::vector<std::vector<seal::Ciphertext>> DeSerializeReply( + const SealPirReplyProto &reply_proto, bool safe_load = false) const; yacl::Buffer SerializeQuery( SealPirQueryProto *query_proto, - const std::vector<std::vector<seal::Ciphertext>> &query_ciphers); - + const std::vector<std::vector<seal::Ciphertext>> &query_ciphers) const; yacl::Buffer SerializeQuery( - const std::vector<std::vector<seal::Ciphertext>> &query_ciphers, - size_t start_pos); + const std::vector<std::vector<seal::Ciphertext>> &query_ciphers) const; + + yacl::Buffer SerializeSeededQuery( + const std::vector<std::vector<std::string>> &query_ciphers) const; + yacl::Buffer SerializeSeededQuery( + SealPirQueryProto *query_proto, + const std::vector<std::vector<std::string>> &query_ciphers) const; std::vector<std::vector<seal::Ciphertext>> DeSerializeQuery( - const yacl::Buffer &query_buffer, bool safe_load = false); + const yacl::Buffer &query_buffer, bool safe_load = false) const; std::vector<std::vector<seal::Ciphertext>> DeSerializeQuery( - const SealPirQueryProto &query_proto, bool safe_load = false); - const PirParams &GetPirParams() { return pir_params_; } - const seal::EncryptionParameters &GetEncParams() { return *enc_params_; } + const SealPirQueryProto &query_proto, bool safe_load = false) const; + + const SealPirParams &GetPirParams() const { return pir_params_; } + const seal::EncryptionParameters &GetEncParams() const { + return *enc_params_; + } protected: - SealPirOptions options_; - PirParams pir_params_; - std::unique_ptr<seal::EncryptionParameters> enc_params_; + SealPirParams pir_params_; + std::unique_ptr<seal::EncryptionParameters> enc_params_; std::unique_ptr<seal::SEALContext> context_; std::unique_ptr<seal::Evaluator> evaluator_; std::unique_ptr<seal::BatchEncoder> encoder_; }; -class SealPirServer : public SealPir, public psi::kwpir::IndexPirServer { +class SealPirServer : public SealPir, public psi::pir::IndexPirServer { public: - SealPirServer(const SealPirOptions &options, - std::shared_ptr<IDbPlaintextStore> plaintext_store); + SealPirServer(const SealPirOptions &options); ~SealPirServer() override = default; - void SetDatabaseByProvider( - const std::shared_ptr<IDbElementProvider> &db_provider); - void SetDatabase(const std::vector<yacl::ByteContainerView> &db_vec) override; + void SetDatabase(const std::vector<yacl::ByteContainerView> &db_vec); + void SetDatabase(const psi::pir_utils::RawDatabase &raw_database) override; + void SetDatabase(std::vector<std::vector<uint8_t>> raw_database) { + pir_utils::RawDatabase raw_db(std::move(raw_database)); + SetDatabase(raw_db); + } - std::vector<seal::Ciphertext> ExpandQuery(const seal::Ciphertext &encrypted, - uint64_t m, uint32_t client_id); + PirReply GenerateResponse( + const std::vector<std::vector<seal::Ciphertext>> &query, + uint32_t client_id) const; - PirReply GenerateReply(const PirQuery &query, uint32_t start_pos, - uint32_t client_id); - yacl::Buffer GenerateIndexReply(const yacl::Buffer &query_buffer) override; + yacl::Buffer GenerateIndexResponse( + const yacl::Buffer &query_buffer) const override; void SetGaloisKey(uint32_t client_id, seal::GaloisKeys galkey); - std::string SerializeDbPlaintext(int db_index = 0); + std::string SerializeDbPlaintext(int db_index = 0) const; void DeSerializeDbPlaintext(const std::string &db_serialize_bytes, int db_index = 0); - void SetOneCt(seal::Ciphertext one); - private: std::vector<std::unique_ptr<std::vector<seal::Plaintext>>> db_vec_; - std::shared_ptr<IDbPlaintextStore> plaintext_store_; - bool is_db_preprocessed_; - std::unordered_map<int, seal::GaloisKeys> galoisKeys_; - seal::Ciphertext one_; + std::vector<std::shared_ptr<IDbPlaintextStore>> plaintext_store_; + + bool db_seted_ = false; + + std::unordered_map<uint32_t, seal::GaloisKeys> galois_keys_; void MultiplyPowerOfX(const seal::Ciphertext &encrypted, - seal::Ciphertext &destination, uint32_t index); + seal::Ciphertext &destination, uint32_t index) const; + + std::vector<seal::Ciphertext> ExpandQuery(const seal::Ciphertext &encrypted, + uint64_t m, + uint32_t client_id) const; }; -class SealPirClient : public SealPir, public psi::kwpir::IndexPirClient { +class SealPirClient : public SealPir, public psi::pir::IndexPirClient { public: SealPirClient(const SealPirOptions &options); ~SealPirClient() override = default; - PirQuery GenerateQuery(uint64_t index); - yacl::Buffer GenerateIndexQuery(uint64_t ele_index, - uint64_t &offset) override; - seal::Plaintext DecodeReply(PirReply &reply); - std::vector<uint8_t> DecodeReply(PirReply &reply, uint64_t offset); - std::vector<uint8_t> DecodeIndexReply(const yacl::Buffer &reply_buffer, - uint64_t offset) override; + // get Pliantext of fhe index from the index of raw database + uint64_t GetPtIndex(uint64_t raw_idx) const; - seal::GaloisKeys GenerateGaloisKeys(); + // get Plaintext of fhe offset from the index of raw database + uint64_t GetPtOffset(uint64_t raw_idx) const; - uint64_t GetFVIndex(uint64_t element_index); - uint64_t GetFVOffset(uint64_t element_index); + PirQuery GenerateQuery(uint64_t pt_idx) const; - seal::Plaintext Decrypt(seal::Ciphertext ct); + PirSeededQuery GenerateSeededQuery(uint64_t pt_idx) const; - std::vector<uint8_t> ExtractBytes(seal::Plaintext pt, uint64_t offset); + yacl::Buffer GenerateIndexQuery(uint64_t raw_idx) const override; - seal::Ciphertext GetOne(); + seal::GaloisKeys GenerateGaloisKeys() const; + + std::vector<seal::Plaintext> DecodeResponse(PirReply &reply) const; + std::vector<uint8_t> DecodeResponse(PirReply &reply, uint64_t raw_idx) const; + std::vector<uint8_t> DecodeIndexResponse(const yacl::Buffer &reponse_buffer, + uint64_t raw_idx) const override; private: std::unique_ptr<seal::Encryptor> encryptor_; std::unique_ptr<seal::Decryptor> decryptor_; std::unique_ptr<seal::KeyGenerator> keygen_; - std::vector<uint64_t> indices_; - std::vector<uint64_t> inverse_scales_; - - friend class SealPirServer; + std::vector<uint8_t> ExtractBytes(seal::Plaintext pt, uint64_t offset, + uint64_t loc_ele_size) const; }; } // namespace psi::sealpir diff --git a/psi/algorithm/sealpir/seal_pir_test.cc b/psi/algorithm/sealpir/seal_pir_test.cc index a94750f8..7254b4f0 100644 --- a/psi/algorithm/sealpir/seal_pir_test.cc +++ b/psi/algorithm/sealpir/seal_pir_test.cc @@ -23,6 +23,8 @@ #include "gtest/gtest.h" #include "spdlog/spdlog.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/crypto/tools/prg.h" using namespace std::chrono; using namespace std; @@ -32,11 +34,8 @@ namespace psi::sealpir { namespace { struct TestParams { uint32_t N = 4096; - uint64_t num_of_items; - uint64_t size_per_item = 288; - uint64_t ind_degree = 0; - uint32_t d = 2; - uint32_t logt = 20; + uint64_t rows; + uint64_t row_byte_len = 256; bool isSerialized = false; }; } // namespace @@ -44,44 +43,31 @@ class SealPirTest : public testing::TestWithParam<TestParams> {}; TEST_P(SealPirTest, Works) { auto params = GetParam(); - uint32_t num_of_items = params.num_of_items; - uint32_t size_per_item = params.size_per_item; - uint32_t N = params.N; - uint32_t d = params.d; + uint32_t rows = params.rows; + uint32_t row_byte_len = params.row_byte_len; bool isSerialized = params.isSerialized; - SPDLOG_INFO( - "N: {}, size_per_item: {} bytes, num_of_items: 2^{:.2f} = {}, " - "ind_degree(Indistinguishable degree) {}, dimension: {}", - N, size_per_item, std::log2(num_of_items), num_of_items, - params.ind_degree, d); - SealPirOptions options{params.N, params.num_of_items, params.size_per_item, - params.ind_degree, params.d}; + // default using d = 2 + SealPirOptions options{params.N, params.rows, params.row_byte_len, 2}; // Initialize PIR Server SPDLOG_INFO("Main: Initializing server and client"); SealPirClient client(options); - std::shared_ptr<IDbPlaintextStore> plaintext_store = - std::make_shared<MemoryDbPlaintextStore>(); - SealPirServer server(options, plaintext_store); + SealPirServer server(options); SPDLOG_INFO("Main: Initializing the database (this may take some time) ..."); - vector<uint8_t> db_data(num_of_items * size_per_item); - random_device rd; - for (uint64_t i = 0; i < num_of_items; i++) { - for (uint64_t j = 0; j < size_per_item; j++) { - uint8_t val = rd() % 256; - db_data[(i * size_per_item) + j] = val; - } + vector<vector<uint8_t>> db_data(rows); + for (uint64_t i = 0; i < rows; ++i) { + db_data[i].resize(row_byte_len); + yacl::crypto::Prg<uint8_t> prg(yacl::crypto::SecureRandU128()); + prg.Fill(absl::MakeSpan(db_data[i])); } - shared_ptr<IDbElementProvider> db_provider = - make_shared<MemoryDbElementProvider>(std::move(db_data), - params.size_per_item); + psi::pir_utils::RawDatabase raw_db(std::move(db_data)); // Measure database setup - server.SetDatabaseByProvider(db_provider); + server.SetDatabase(raw_db); SPDLOG_INFO("Main: database pre processed "); // Set galois key for client with id 0 @@ -96,71 +82,52 @@ TEST_P(SealPirTest, Works) { server.SetGaloisKey(0, galois_keys); } - uint64_t ele_index = rd() % num_of_items; // element in DB at random position + uint64_t ele_index = + yacl::crypto::RandU64() % rows; // element in DB at random position + uint64_t target_raw_idx = ele_index; - uint64_t query_index = ele_index; - size_t start_pos = 0; - if (params.ind_degree > 0) { - query_index = ele_index % params.ind_degree; - start_pos = ele_index - query_index; - } - - uint64_t index = client.GetFVIndex(query_index); // index of FV plaintext - uint64_t offset = client.GetFVOffset(query_index); // offset in FV plaintext - SPDLOG_INFO("Main: element index = {} from [0, {}]", ele_index, - num_of_items - 1); - SPDLOG_INFO("Main: FV index = {}, FV offset = {}", index, offset); + uint64_t pt_idx = + client.GetPtIndex(target_raw_idx); // pt_idx of FV plaintext + uint64_t pt_offset = + client.GetPtOffset(target_raw_idx); // pt_offset in FV plaintext + SPDLOG_INFO("Main: raw_idx = {} from [0, {}]", ele_index, rows - 1); + SPDLOG_INFO("Main: FV pt_idx = {}, FV pt_offset = {}", pt_idx, pt_offset); // Measure query generation - vector<uint8_t> elems; if (isSerialized) { - uint64_t offset; - yacl::Buffer query_buffer = client.GenerateIndexQuery(ele_index, offset); + yacl::Buffer query_buffer = client.GenerateIndexQuery(target_raw_idx); SPDLOG_INFO("Main: query generated"); - yacl::Buffer reply_buffer = server.GenerateIndexReply(query_buffer); + yacl::Buffer reply_buffer = server.GenerateIndexResponse(query_buffer); SPDLOG_INFO("Main: reply generated"); - elems = client.DecodeIndexReply(reply_buffer, offset); + elems = client.DecodeIndexResponse(reply_buffer, target_raw_idx); SPDLOG_INFO("Main: reply decoded"); } else { - SealPir::PirQuery query = client.GenerateQuery(index); + SealPir::PirQuery query = client.GenerateQuery(pt_idx); SPDLOG_INFO("Main: query generated"); - SealPir::PirReply reply = server.GenerateReply(query, start_pos, 0); + SealPir::PirReply reply = server.GenerateResponse(query, 0); SPDLOG_INFO("Main: reply generated"); - elems = client.DecodeReply(reply, offset); + elems = client.DecodeResponse(reply, target_raw_idx); SPDLOG_INFO("Main: reply decoded"); } SPDLOG_INFO("Main: query finished"); - EXPECT_EQ(elems.size(), size_per_item); + EXPECT_EQ(elems.size(), row_byte_len); // Check that we retrieved the correct element - EXPECT_EQ(elems, db_provider->ReadElement(ele_index * size_per_item)); + EXPECT_EQ(elems, raw_db.At(ele_index)); SPDLOG_INFO("Main: PIR result correct!"); } -INSTANTIATE_TEST_SUITE_P( - Works_Instances, SealPirTest, - testing::Values(TestParams{4096, 1000}, TestParams{4096, 1000, 10}, - TestParams{4096, 1000, 20}, TestParams{4096, 1000, 400}, - TestParams{4096, 203, 288, 100}, - TestParams{4096, 3000, 288, 1000}, - // N = 8192 - TestParams{8192, 1000}, TestParams{8192, 1000, 10}, - TestParams{8192, 1000, 20}, TestParams{8192, 1000, 400}, - TestParams{8192, 203, 288, 100}, - TestParams{8192, 3000, 288, 1000}, - // large num items - TestParams{4096, 1 << 16, 10, 0, 2}, - TestParams{4096, 1 << 18, 10, 0, 2}, - TestParams{4096, 1 << 20, 10, 0, 2}, - // corner case - TestParams{4096, (1 << 22) - (1 << 10), 10}, - // serializing - TestParams{4096, 1 << 18, 10, 0, 2, 20, true}, - TestParams{4096, 1000, 288, 100, 2, 20, true}, - TestParams{8192, 1000, 288, 0, 2, 20, true})); +INSTANTIATE_TEST_SUITE_P(Works_Instances, SealPirTest, + testing::Values( + // large num items + TestParams{4096, 1000000, 256}, + TestParams{4096, 100000, 256, true}, + // large value + TestParams{4096, 10000, 10241, true}, + TestParams{4096, 1000, 10240 * 10, true})); } // namespace psi::sealpir diff --git a/psi/algorithm/sealpir/seal_pir_utils.cc b/psi/algorithm/sealpir/seal_pir_utils.cc index 0d8ba27c..e406afbf 100644 --- a/psi/algorithm/sealpir/seal_pir_utils.cc +++ b/psi/algorithm/sealpir/seal_pir_utils.cc @@ -20,9 +20,7 @@ namespace psi::sealpir { std::vector<uint8_t> MemoryDbElementProvider::ReadElement(size_t index) { YACL_ENFORCE(index < items_.size()); - std::vector<uint8_t> element(element_size_); - std::memcpy(element.data(), &items_[index], element_size_); return element; } @@ -30,9 +28,7 @@ std::vector<uint8_t> MemoryDbElementProvider::ReadElement(size_t index) { std::vector<uint8_t> MemoryDbElementProvider::ReadElement(size_t index, size_t size) { YACL_ENFORCE((index + size) <= items_.size()); - std::vector<uint8_t> element(size); - std::memcpy(element.data(), &items_[index], size); return element; } @@ -53,9 +49,9 @@ void MemoryDbPlaintextStore::SavePlaintexts( } } -std::vector<seal::Plaintext> MemoryDbPlaintextStore::ReadPlaintexts( - size_t sub_db_index) { - // return std::move(db_vec_[sub_db_index]); +const std::vector<seal::Plaintext>& MemoryDbPlaintextStore::ReadPlaintexts( + size_t sub_db_index) const { + YACL_ENFORCE_LT(sub_db_index, db_vec_.size()); return db_vec_[sub_db_index]; } diff --git a/psi/algorithm/sealpir/seal_pir_utils.h b/psi/algorithm/sealpir/seal_pir_utils.h index 42e93aff..ec16eef7 100644 --- a/psi/algorithm/sealpir/seal_pir_utils.h +++ b/psi/algorithm/sealpir/seal_pir_utils.h @@ -27,7 +27,7 @@ class IDbElementProvider { public: virtual ~IDbElementProvider() = default; - // Read at `index` item and return data. An empty returned vector + // Read at `index` item and return data. An empty returned vector // is treated as the end of stream. virtual std::vector<uint8_t> ReadElement(size_t index) = 0; virtual std::vector<uint8_t> ReadElement(size_t index, size_t size) = 0; @@ -48,7 +48,8 @@ class IDbPlaintextStore { virtual void SavePlaintexts(const std::vector<seal::Plaintext>& plaintext, size_t sub_db_index) = 0; - virtual std::vector<seal::Plaintext> ReadPlaintexts(size_t sub_db_index) = 0; + virtual const std::vector<seal::Plaintext>& ReadPlaintexts( + size_t sub_db_index) const = 0; }; class MemoryDbElementProvider : public IDbElementProvider { @@ -81,7 +82,8 @@ class MemoryDbPlaintextStore : public IDbPlaintextStore { void SavePlaintexts(const std::vector<seal::Plaintext>& plaintexts, size_t sub_db_index) override; - std::vector<seal::Plaintext> ReadPlaintexts(size_t sub_db_index) override; + const std::vector<seal::Plaintext>& ReadPlaintexts( + size_t sub_db_index) const override; private: std::vector<std::vector<seal::Plaintext>> db_vec_; diff --git a/psi/algorithm/sealpir/serializable.proto b/psi/algorithm/sealpir/serializable.proto index 7e6989df..902bcb4c 100644 --- a/psi/algorithm/sealpir/serializable.proto +++ b/psi/algorithm/sealpir/serializable.proto @@ -25,14 +25,14 @@ message CiphertextsProto { repeated bytes ciphers = 1; } +message SealPirReplyProto { + repeated CiphertextsProto reply_cipher = 1; +} + message SealPirQueryProto { - int32 ind_degree = 1; - int32 start_pos = 2; - repeated CiphertextsProto query_cipher = 3; + repeated CiphertextsProto query_cipher = 1; } message SealPirAnswerProto { - int32 ind_degree = 1; - int32 start_pos = 2; - CiphertextsProto answer = 3; + CiphertextsProto answer = 1; } \ No newline at end of file diff --git a/psi/algorithm/spiral/BUILD.bazel b/psi/algorithm/spiral/BUILD.bazel index 6f737133..a9733085 100644 --- a/psi/algorithm/spiral/BUILD.bazel +++ b/psi/algorithm/spiral/BUILD.bazel @@ -17,6 +17,16 @@ load(":copts.bzl", "spiral_copts") package(default_visibility = ["//visibility:public"]) +proto_library( + name = "serializable_proto", + srcs = ["serializable.proto"], +) + +cc_proto_library( + name = "serializable_cc_proto", + deps = [":serializable_proto"], +) + psi_cc_library( name = "common", hdrs = ["common.h"], @@ -68,12 +78,12 @@ psi_cc_library( copts = spiral_copts(), deps = [ ":params", + ":serializable_cc_proto", ":util", "//psi/algorithm/spiral/arith:arith_params", "//psi/algorithm/spiral/arith:ntt", "@abseil-cpp//absl/strings", "@abseil-cpp//absl/types:span", - "@yacl//yacl/base:aligned_vector", "@yacl//yacl/base:exception", "@yacl//yacl/base:int128", "@yacl//yacl/crypto/rand", @@ -93,14 +103,14 @@ psi_cc_library( hdrs = ["poly_matrix_utils.h"], copts = spiral_copts(), deps = [ - "poly_matrix", + ":discrete_gaussian", ":params", + ":poly_matrix", ":util", "//psi/algorithm/spiral/arith:arith_params", "//psi/algorithm/spiral/arith:ntt", "@abseil-cpp//absl/strings", "@abseil-cpp//absl/types:span", - "@yacl//yacl/base:aligned_vector", "@yacl//yacl/base:exception", "@yacl//yacl/base:int128", "@yacl//yacl/crypto/rand", @@ -171,3 +181,125 @@ psi_cc_test( ":util", ], ) + +psi_cc_library( + name = "public_keys", + hdrs = ["public_keys.h"], + deps = [ + ":params", + ":poly_matrix", + "@yacl//yacl/base:int128", + ], +) + +psi_cc_library( + name = "spiral_client", + srcs = ["spiral_client.cc"], + hdrs = ["spiral_client.h"], + deps = [ + ":common", + ":discrete_gaussian", + ":gadget", + ":params", + ":poly_matrix", + ":poly_matrix_utils", + ":public_keys", + ":serialize", + "//psi/algorithm/pir_interface:kw_pir", + "//psi/algorithm/pir_interface:pir_db", + "@yacl//yacl/base:int128", + "@yacl//yacl/crypto/rand", + "@yacl//yacl/crypto/tools:prg", + "@yacl//yacl/utils:elapsed_timer", + "@yacl//yacl/utils:parallel", + ], +) + +psi_cc_test( + name = "spiral_client_test", + srcs = ["spiral_client_test.cc"], + deps = [ + ":params", + ":poly_matrix_utils", + ":public_keys", + ":serialize", + ":spiral_client", + ":util", + "@abseil-cpp//absl/types:span", + "@yacl//yacl/crypto/tools:prg", + ], +) + +psi_cc_library( + name = "spiral_server", + srcs = ["spiral_server.cc"], + hdrs = ["spiral_server.h"], + deps = [ + ":common", + ":discrete_gaussian", + ":gadget", + ":params", + ":poly_matrix", + ":poly_matrix_utils", + ":public_keys", + ":serialize", + ":spiral_client", + "//psi/algorithm/pir_interface:kw_pir", + "//psi/algorithm/pir_interface:pir_db", + "@yacl//yacl/base:int128", + "@yacl//yacl/crypto/rand", + "@yacl//yacl/crypto/tools:prg", + "@yacl//yacl/utils:elapsed_timer", + "@yacl//yacl/utils:parallel", + ], +) + +psi_cc_test( + name = "spiral_server_test", + srcs = ["spiral_server_test.cc"], + deps = [ + ":gadget", + ":params", + ":poly_matrix_utils", + ":public_keys", + ":spiral_client", + ":spiral_server", + ":util", + "@abseil-cpp//absl/types:span", + "@yacl//yacl/crypto/tools:prg", + ], +) + +psi_cc_test( + name = "spiral_pir_test", + srcs = ["spiral_pir_test.cc"], + deps = [ + ":gadget", + ":params", + ":poly_matrix_utils", + ":public_keys", + ":spiral_client", + ":spiral_server", + ":util", + "@abseil-cpp//absl/types:span", + "@yacl//yacl/crypto/tools:prg", + "@yacl//yacl/utils:elapsed_timer", + ], +) + +psi_cc_library( + name = "serialize", + srcs = ["serialize.cc"], + hdrs = ["serialize.h"], + deps = [ + ":common", + ":params", + ":poly_matrix", + ":public_keys", + ":serializable_cc_proto", + ":util", + "//psi/algorithm/spiral/arith:ntt_table", + "@abseil-cpp//absl/types:span", + "@yacl//yacl/base:buffer", + ], +) diff --git a/psi/algorithm/spiral/README.md b/psi/algorithm/spiral/README.md index 7ed82991..2b539143 100644 --- a/psi/algorithm/spiral/README.md +++ b/psi/algorithm/spiral/README.md @@ -1,4 +1,5 @@ +# SPIRAL This is a C++ implementation of [Spiral Fast, High Rate Single Server PIR via FHE Composition](https://eprint.iacr.org/2022/368). -We referred to the [Rust implementation](https://github.com/blyssprivacy/sdk/tree/main/lib/spiral-rs) corresponding to this paper. \ No newline at end of file +We referred to the [Rust implementation](https://github.com/blyssprivacy/sdk/tree/main/lib/spiral-rs) corresponding to this paper. diff --git a/psi/algorithm/spiral/arith/ntt.cc b/psi/algorithm/spiral/arith/ntt.cc index 9acb7952..eb2e693e 100644 --- a/psi/algorithm/spiral/arith/ntt.cc +++ b/psi/algorithm/spiral/arith/ntt.cc @@ -26,7 +26,6 @@ #include "absl/types/span.h" #include "spdlog/spdlog.h" -#include "yacl/base/aligned_vector.h" #include "yacl/base/exception.h" #include "yacl/utils/parallel.h" diff --git a/psi/algorithm/spiral/arith/ntt_table_test.cc b/psi/algorithm/spiral/arith/ntt_table_test.cc index 05fea79d..25dfd67e 100644 --- a/psi/algorithm/spiral/arith/ntt_table_test.cc +++ b/psi/algorithm/spiral/arith/ntt_table_test.cc @@ -20,7 +20,6 @@ #include <vector> #include "gtest/gtest.h" -#include "yacl/base/aligned_vector.h" #include "psi/algorithm/spiral/arith/ntt.h" #include "psi/algorithm/spiral/params.h" diff --git a/psi/algorithm/spiral/params.cc b/psi/algorithm/spiral/params.cc index ca5a9973..a62502b0 100644 --- a/psi/algorithm/spiral/params.cc +++ b/psi/algorithm/spiral/params.cc @@ -25,12 +25,11 @@ namespace psi::spiral { Params::Params(std::size_t poly_len, std::vector<std::uint64_t> moduli, double noise_width, PolyMatrixParams poly_matrix_params, - QueryParams query_params, std::size_t version) + QueryParams query_params) : poly_len_(poly_len), noise_width_(noise_width), poly_matrix_params_(std::move(poly_matrix_params)), - query_params_(std::move(query_params)), - version_(version) { + query_params_(std::move(query_params)) { YACL_ENFORCE(poly_matrix_params_.q2_bits_ >= kMinQ2Bits); poly_len_log2_ = arith::Log2(poly_len_); @@ -77,8 +76,7 @@ Params::Params(std::size_t poly_len, std::vector<std::uint64_t> moduli, Params Params::ParamsWithModuli(const Params& params, std::vector<uint64_t> moduli) { return Params(params.PolyLen(), std::move(moduli), params.noise_width_, - params.poly_matrix_params_, params.query_params_, - params.version_); + params.poly_matrix_params_, params.query_params_); } void Params::ComputeId() { @@ -104,7 +102,12 @@ std::size_t Params::ElementSizeOfPt(size_t element_byte_len) { void Params::UpdateByDatabaseInfo(const DatabaseMetaInfo& database_info) { // here, we only consider one row of raw data can be holded by one plaintext // in SpiralPIR - size_t element_byte_len = database_info.byte_size_per_row_; + + // size_t element_byte_len = database_info.byte_size_per_row_; + + // if the byte_size_per_row_ > MaxByteLenOfPt, we use the min + size_t element_byte_len = + std::min(database_info.byte_size_per_row_, MaxByteLenOfPt()); // the number of one plaintext can hold the rows in raw database size_t element_size_of_pt = ElementSizeOfPt(element_byte_len); @@ -179,8 +182,7 @@ std::uint64_t Params::CrtCompose(const std::vector<std::uint64_t>& a, ss << "t_conv: " << TConv() << ", t_exp_left: " << TExpLeft() << ", t_exp_right: " << TExpRight() << ", t_gsw: " << TGsw() << "\n"; - ss << "expand_query: " << (ExpandQuery() ? "true" : "false") - << ", v1: " << DbDim1() << ", v2: " << DbDim2(); + ss << "v1: " << DbDim1() << ", v2: " << DbDim2(); return ss.str(); } diff --git a/psi/algorithm/spiral/params.h b/psi/algorithm/spiral/params.h index 1d37401a..f18223a8 100644 --- a/psi/algorithm/spiral/params.h +++ b/psi/algorithm/spiral/params.h @@ -68,7 +68,6 @@ struct CrtParams { CrtParams() = default; - // 构造函数 CrtParams(std::size_t crt_count, std::uint64_t mod0_inv_mod1, std::uint64_t mod1_inv_mod0, std::vector<seal::Modulus> moduli, seal::Modulus modulus, std::uint64_t modulus_log2) @@ -119,9 +118,6 @@ struct PolyMatrixParams { }; struct QueryParams { - // default true - bool expand_queries_ = true; - // use the rng_pub related seed to compress the SpiralQuery size bool query_seed_compressed_ = true; @@ -135,34 +131,29 @@ struct QueryParams { // in our kernel level, we only process the case T = 1 std::size_t instances_ = 1; - // seem no usage? consider remove it - std::size_t db_item_size_ = 1; - QueryParams() = default; QueryParams(std::size_t db_dim_1, std::size_t db_dim_2, std::size_t instances, - std::size_t db_item_size, bool expand_queries = true, bool query_seed_compressed = true) - : expand_queries_(expand_queries), - query_seed_compressed_(query_seed_compressed), + : query_seed_compressed_(query_seed_compressed), db_dim1_(db_dim_1), db_dim2_(db_dim_2), - instances_(instances), - db_item_size_(db_item_size) {} + instances_(instances) {} }; class Params { public: Params(std::size_t poly_len, std::vector<std::uint64_t> moduli, double noise_width, PolyMatrixParams poly_matrix_params, - QueryParams query_params, std::size_t version); + QueryParams query_params); - void UpdateByDatabaseInfo(const DatabaseMetaInfo& database_info); + Params() = default; - [[nodiscard]] bool IsValid() const { - return G() <= poly_len_log2_ && DbDim1() <= kMaxDbDim && - DbDim2() <= kMaxDbDim; - } + Params(const Params& other) = default; + Params& operator=(const Params& other) = default; + + Params(Params&& other) = default; + Params& operator=(Params&& other) = default; static Params ParamsWithModuli(const Params& params, std::vector<uint64_t> moduli); @@ -171,6 +162,13 @@ class Params { bool operator!=(const Params& other) const { return !(*this == other); } + void UpdateByDatabaseInfo(const DatabaseMetaInfo& database_info); + + [[nodiscard]] bool IsValid() const { + return G() <= poly_len_log2_ && DbDim1() <= kMaxDbDim && + DbDim2() <= kMaxDbDim; + } + [[nodiscard]] const std::vector<std::uint64_t>& GetNttForwardTable( std::size_t i) const { return ntt_tables_[i][0]; @@ -245,10 +243,6 @@ class Params { return poly_matrix_params_.n_ * poly_matrix_params_.n_ * poly_len_; } - [[nodiscard]] bool ExpandQuery() const { - return query_params_.expand_queries_; - } - [[nodiscard]] size_t N() const { return poly_matrix_params_.n_; }; [[nodiscard]] size_t Q2Bits() const { return poly_matrix_params_.q2_bits_; }; @@ -301,7 +295,7 @@ class Params { std::uint64_t CrtCompose(const std::vector<std::uint64_t>& a, std::size_t idx) const; - /// other util methods + // other util methods [[nodiscard]] std::string ToString(); @@ -312,6 +306,19 @@ class Params { // the number of raw data rows that one Pt can hold std::size_t ElementSizeOfPt(size_t element_byte_len); + // one Pt can hold how many bytes + // in spiral, one Pt is Rp^{n*n} + std::size_t MaxByteLenOfPt() const { + size_t max_bits = poly_len_ * N() * N() * PtModulusBitLen(); + // floor + return max_bits / 8; + } + + // one Pt can hold how many bits + std::size_t MaxBitLenOfPt() const { + return poly_len_ * N() * N() * PtModulusBitLen(); + } + std::size_t PolyLen() const { return poly_len_; } std::size_t PolyLenLog2() const { return poly_len_log2_; } @@ -340,8 +347,6 @@ class Params { double NoiseWidth() const { return noise_width_; } - std::size_t Version() const { return version_; } - std::uint64_t Mod0InvMod1() const { return crt_params_.mod0_inv_mod1_; } std::uint64_t Mod1InvMod0() const { return crt_params_.mod1_inv_mod0_; } @@ -374,9 +379,6 @@ class Params { // Query related params QueryParams query_params_; - // seem no usage? consider remove it - std::size_t version_ = 0; - ParamsId id_ = 0; }; diff --git a/psi/algorithm/spiral/poly_matrix.cc b/psi/algorithm/spiral/poly_matrix.cc index 288ee0cf..4f657adf 100644 --- a/psi/algorithm/spiral/poly_matrix.cc +++ b/psi/algorithm/spiral/poly_matrix.cc @@ -31,6 +31,72 @@ namespace psi::spiral { +//-------PolyMatrixRaw + +PolyMatrixProto PolyMatrixRaw::ToProto() const { + PolyMatrixProto proto; + proto.set_rows(rows_); + proto.set_cols(cols_); + + proto.mutable_data()->Reserve(data_.size()); + proto.mutable_data()->Assign(data_.begin(), data_.end()); + return proto; +} + +PolyMatrixProto PolyMatrixRaw::ToProtoRng() const { + WEAK_ENFORCE(rows_ > 1); + + PolyMatrixProto proto; + proto.set_rows(rows_ - 1); + proto.set_cols(cols_); + // skip the first row + size_t offset = cols_ * poly_len_; + proto.mutable_data()->Reserve(data_.size() - offset); + proto.mutable_data()->Assign(data_.begin() + offset, data_.end()); + return proto; +} + +PolyMatrixRaw PolyMatrixRaw::FromProto(const PolyMatrixProto& proto, + const Params& params) { + size_t rows = proto.rows(); + size_t cols = proto.cols(); + + std::vector<uint64_t> data; + data.reserve(proto.data_size()); + for (const auto& value : proto.data()) { + data.push_back(value); + } + + YACL_ENFORCE_EQ(rows * cols * params.PolyLen(), data.size()); + + return PolyMatrixRaw(params.PolyLen(), rows, cols, std::move(data)); +} + +PolyMatrixRaw PolyMatrixRaw::FromProtoRng(const PolyMatrixProto& proto, + const Params& params, + yacl::crypto::Prg<uint64_t>& rng) { + size_t rows = proto.rows(); + size_t cols = proto.cols(); + + YACL_ENFORCE_EQ(rows * cols * params.PolyLen(), + static_cast<size_t>(proto.data_size())); + + std::vector<uint64_t> data; + size_t first_row_coeffs = cols * params.PolyLen(); + size_t rest_row_coeffs = proto.data_size(); + data.reserve(first_row_coeffs + rest_row_coeffs); + + // resconstruct the first row by rng + for (size_t i = 0; i < first_row_coeffs; ++i) { + data.push_back(params.Modulus() - (rng() % params.Modulus())); + } + // rest rows + for (const auto& value : proto.data()) { + data.push_back(value); + } + return PolyMatrixRaw(params.PolyLen(), rows + 1, cols, std::move(data)); +} + // PolyMatrixRaw void PolyMatrixRaw::CopyInto(const PolyMatrixRaw& p, size_t target_row, diff --git a/psi/algorithm/spiral/poly_matrix.h b/psi/algorithm/spiral/poly_matrix.h index 57beac4a..1314616e 100644 --- a/psi/algorithm/spiral/poly_matrix.h +++ b/psi/algorithm/spiral/poly_matrix.h @@ -22,6 +22,8 @@ #include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/serializable.pb.h" + namespace psi::spiral { // forward declaration @@ -145,6 +147,16 @@ class PolyMatrixRaw { PolyMatrixRaw operator-() = delete; + // seralize related methods + PolyMatrixProto ToProto() const; + PolyMatrixProto ToProtoRng() const; + + static PolyMatrixRaw FromProto(const PolyMatrixProto& proto, + const Params& params); + static PolyMatrixRaw FromProtoRng(const PolyMatrixProto& proto, + const Params& params, + yacl::crypto::Prg<uint64_t>& rng); + // static methods without params static PolyMatrixRaw Zero(size_t poly_len, size_t rows, size_t cols) { return PolyMatrixRaw(poly_len, rows, cols); diff --git a/psi/algorithm/spiral/poly_matrix_utils.cc b/psi/algorithm/spiral/poly_matrix_utils.cc index c4c41976..4e326afb 100644 --- a/psi/algorithm/spiral/poly_matrix_utils.cc +++ b/psi/algorithm/spiral/poly_matrix_utils.cc @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "psi/algorithm/spiral/poly_matrix_utils.h" + #ifdef __x86_64__ #include <immintrin.h> #elif defined(__aarch64__) @@ -25,6 +27,7 @@ #include "psi/algorithm/spiral/arith/arith_params.h" #include "psi/algorithm/spiral/arith/ntt.h" +#include "psi/algorithm/spiral/discrete_gaussian.h" #include "psi/algorithm/spiral/poly_matrix.h" #include "psi/algorithm/spiral/util.h" @@ -159,6 +162,36 @@ void ReducePoly(const Params& params, absl::Span<uint64_t> res) { } } +PolyMatrixRaw Noise(const Params& params, size_t rows, size_t cols, + const DiscreteGaussian& dg, + yacl::crypto::Prg<uint64_t>& prg) { + PolyMatrixRaw out = PolyMatrixRaw::Zero(params.PolyLen(), rows, cols); + dg.SampleMatrix(params, out, prg); + return out; +} + +void GenTernaryMatrix(const Params& params, PolyMatrixRaw& mat, size_t hamming, + yacl::crypto::Prg<uint64_t>& prg) { + auto modulus = params.Modulus(); + + uint128_t mt_seed; + prg.Fill( + absl::MakeSpan(reinterpret_cast<uint8_t*>(&mt_seed), sizeof(mt_seed))); + std::mt19937 rng(mt_seed); + // todo: change the style + for (size_t i = 0; i < mat.Rows(); ++i) { + for (size_t j = 0; j < mat.Cols(); ++j) { + auto poly = mat.Poly(i, j); + for (size_t k = 0; k < hamming; ++k) { + poly[k] = 1; + poly[k + hamming] = modulus - 1; + } + // shuffle + std::shuffle(poly.begin(), poly.end(), rng); + } + } +} + PolyMatrixNtt ShiftRowsByOne(const PolyMatrixNtt& in) { if (in.Rows() == 1) { return PolyMatrixNtt(in); diff --git a/psi/algorithm/spiral/poly_matrix_utils.h b/psi/algorithm/spiral/poly_matrix_utils.h index 6e77d9e8..5910c59a 100644 --- a/psi/algorithm/spiral/poly_matrix_utils.h +++ b/psi/algorithm/spiral/poly_matrix_utils.h @@ -20,7 +20,9 @@ #include "seal/modulus.h" #include "yacl/crypto/tools/prg.h" +#include "psi/algorithm/spiral/discrete_gaussian.h" #include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/poly_matrix.h" namespace psi::spiral { @@ -57,6 +59,13 @@ void ReducePoly(const Params& params, absl::Span<uint64_t> res); // matrix operator +PolyMatrixRaw Noise(const Params& params, size_t rows, size_t cols, + const DiscreteGaussian& dg, + yacl::crypto::Prg<uint64_t>& prg); + +void GenTernaryMatrix(const Params& params, PolyMatrixRaw& mat, size_t hamming, + yacl::crypto::Prg<uint64_t>& prg); + PolyMatrixNtt ShiftRowsByOne(const PolyMatrixNtt& in); PolyMatrixRaw Stack(const PolyMatrixRaw& a, const PolyMatrixRaw& b); diff --git a/psi/algorithm/spiral/public_keys.h b/psi/algorithm/spiral/public_keys.h new file mode 100644 index 00000000..22968135 --- /dev/null +++ b/psi/algorithm/spiral/public_keys.h @@ -0,0 +1,62 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <cstddef> +#include <optional> +#include <utility> +#include <vector> + +#include "yacl/base/int128.h" + +#include "psi/algorithm/spiral/poly_matrix.h" +// #include "psi/algorithm/spiral/serialize.h" + +namespace psi::spiral { + +// some public keys for server computation +struct PublicKeys { + // packing key in Page 20 + std::vector<PolyMatrixNtt> v_packing_; + + // Automorphism keys for first dimension's encoding in Query, Similar to + // GaolisKey in SealPIR + std::vector<PolyMatrixNtt> v_expansion_left_; + + // Automorphism keys for subsequent dimension's encoding in Query + std::vector<PolyMatrixNtt> v_expansion_right_; + + // conversion key for Regev to Gsw + std::vector<PolyMatrixNtt> v_conversion_; + + PublicKeys() = default; + + PublicKeys(std::vector<PolyMatrixNtt>&& v_packing, + std::vector<PolyMatrixNtt>&& v_expansion_left, + std::vector<PolyMatrixNtt>&& v_expansion_right, + std::vector<PolyMatrixNtt>&& v_conversion) + : v_packing_(std::move(v_packing)), + v_expansion_left_(std::move(v_expansion_left)), + v_expansion_right_(std::move(v_expansion_right)), + v_conversion_(std::move(v_conversion)) {} + + bool operator==(const PublicKeys& other) const { + return this->v_packing_ == other.v_packing_ && + this->v_expansion_left_ == other.v_expansion_left_ && + this->v_expansion_right_ == other.v_expansion_right_; + } +}; + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/serializable.proto b/psi/algorithm/spiral/serializable.proto new file mode 100644 index 00000000..fc9ab5d1 --- /dev/null +++ b/psi/algorithm/spiral/serializable.proto @@ -0,0 +1,44 @@ +// +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package psi.spiral; + +// for Raw and Ntt +message PolyMatrixProto { + uint64 rows = 1; + uint64 cols = 2; + repeated uint64 data = 3; +} + +message SpiralQueryProto { + PolyMatrixProto ct = 1; + bytes seed = 2; +} + +message PublicKeysProto { + repeated PolyMatrixProto v_packing = 1; + + repeated PolyMatrixProto v_expansion_left = 2; + + repeated PolyMatrixProto v_expansion_right = 3; + + repeated PolyMatrixProto v_conversion = 4; +} + +message SpiralResponseProto { + repeated PolyMatrixProto ct = 1; +} \ No newline at end of file diff --git a/psi/algorithm/spiral/serialize.cc b/psi/algorithm/spiral/serialize.cc new file mode 100644 index 00000000..db0c20af --- /dev/null +++ b/psi/algorithm/spiral/serialize.cc @@ -0,0 +1,224 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef __x86_64__ +#include <immintrin.h> +#elif defined(__aarch64__) +#include "sse2neon.h" +#endif + +#include <chrono> +#include <cstdint> +#include <iostream> +#include <string> +#include <vector> + +#include "absl/types/span.h" +#include "yacl/base/buffer.h" + +#include "psi/algorithm/spiral/common.h" +#include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/poly_matrix.h" +#include "psi/algorithm/spiral/public_keys.h" +// #include "psi/algorithm/spiral/spiral_client.h" +#include "psi/algorithm/spiral/util.h" + +#include "psi/algorithm/spiral/serializable.pb.h" + +namespace psi::spiral { + +yacl::Buffer SerializePolyMatrixRaw(const PolyMatrixRaw& poly_matrix) { + // 1. first construct proto object + PolyMatrixProto proto; + + proto.set_rows(poly_matrix.Rows()); + proto.set_cols(poly_matrix.Cols()); + + for (const auto& value : poly_matrix.Data()) { + proto.add_data(value); + } + // then convert to buffer + yacl::Buffer buffer(proto.ByteSizeLong()); + proto.SerializePartialToArray(buffer.data(), buffer.size()); + + return buffer; +} + +PolyMatrixRaw DeserializePolyMatrixRaw(const Params& params, + yacl::Buffer& buffer) { + // first convert buffer into proto object + PolyMatrixProto proto; + proto.ParseFromArray(buffer.data(), buffer.size()); + + // then convert proto object to Object + size_t rows = proto.rows(); + size_t cols = proto.cols(); + + std::vector<uint64_t> data; + data.reserve(proto.data_size()); + for (const auto& value : proto.data()) { + data.push_back(value); + } + + YACL_ENFORCE_EQ(rows * cols * params.PolyLen(), data.size()); + return PolyMatrixRaw(params.PolyLen(), rows, cols, std::move(data)); +} + +yacl::Buffer SerializePolyMatrixRawRng(const PolyMatrixRaw& poly_matrix, + const Params& params) { + // 1. first construct proto object + PolyMatrixProto proto; + + proto.set_rows(poly_matrix.Rows() - 1); + proto.set_cols(poly_matrix.Cols()); + + // skip the first row + size_t offset = poly_matrix.Cols() * params.PolyLen(); + + for (size_t i = offset; i < poly_matrix.Data().size(); ++i) { + proto.add_data(poly_matrix.Data()[i]); + } + // then convert to buffer + yacl::Buffer buffer(proto.ByteSizeLong()); + proto.SerializePartialToArray(buffer.data(), buffer.size()); + + return buffer; +} + +PolyMatrixRaw DeserializePolyMatrixRawRng(yacl::Buffer& buffer, + const Params& params, + yacl::crypto::Prg<uint64_t> rng) { + // first convert buffer into proto object + PolyMatrixProto proto; + proto.ParseFromArray(buffer.data(), buffer.size()); + + // then convert proto object to Object + size_t rows = proto.rows(); + size_t cols = proto.cols(); + + YACL_ENFORCE_EQ(rows * cols * params.PolyLen(), + static_cast<size_t>(proto.data_size())); + + std::vector<uint64_t> data; + size_t first_row_coeffs = cols * params.PolyLen(); + size_t rest_row_coeffs = proto.data_size(); + data.reserve(first_row_coeffs + rest_row_coeffs); + + // resconstruct the first row by rng + for (size_t i = 0; i < first_row_coeffs; ++i) { + data.push_back(params.Modulus() - (rng() % params.Modulus())); + } + // rest rows + for (const auto& value : proto.data()) { + data.push_back(value); + } + return PolyMatrixRaw(params.PolyLen(), rows + 1, cols, std::move(data)); +} + +yacl::Buffer SerializePublicKeys(const Params& params, const PublicKeys& pks) { + PublicKeysProto proto; + + for (auto& val : pks.v_packing_) { + auto val_raw = FromNtt(params, val); + *proto.add_v_packing() = val_raw.ToProto(); + } + + for (auto& val : pks.v_expansion_left_) { + auto val_raw = FromNtt(params, val); + *proto.add_v_expansion_left() = val_raw.ToProto(); + } + + for (auto& val : pks.v_expansion_right_) { + auto val_raw = FromNtt(params, val); + *proto.add_v_expansion_right() = val_raw.ToProto(); + } + + for (auto& val : pks.v_conversion_) { + auto val_raw = FromNtt(params, val); + *proto.add_v_conversion() = val_raw.ToProto(); + } + + yacl::Buffer buffer(proto.ByteSizeLong()); + proto.SerializePartialToArray(buffer.data(), buffer.size()); + + return buffer; +} + +yacl::Buffer SerializeResponse(const std::vector<PolyMatrixRaw>& responses) { + SpiralResponseProto proto; + + for (const auto& val : responses) { + *proto.add_ct() = val.ToProto(); + } + + yacl::Buffer buffer(proto.ByteSizeLong()); + proto.SerializePartialToArray(buffer.data(), buffer.size()); + + return buffer; +} +std::vector<PolyMatrixRaw> DeserializeResponse(const Params& params, + const yacl::Buffer& buffer) { + SpiralResponseProto proto; + proto.ParseFromArray(buffer.data(), buffer.size()); + + std::vector<PolyMatrixRaw> result; + result.reserve(proto.ct().size()); + for (const auto& val : proto.ct()) { + result.push_back(PolyMatrixRaw::FromProto(val, params)); + } + + return result; +} + +PublicKeys DeserializePublicKeys(const Params& params, yacl::Buffer& buffer) { + PublicKeysProto proto; + proto.ParseFromArray(buffer.data(), buffer.size()); + + PublicKeys pks; + for (const auto& val : proto.v_packing()) { + auto val_ntt = ToNtt(params, PolyMatrixRaw::FromProto(val, params)); + pks.v_packing_.push_back(val_ntt); + } + + if (proto.v_expansion_left_size() > 0) { + std::vector<PolyMatrixNtt> v_expansion_left; + for (const auto& val : proto.v_expansion_left()) { + auto val_ntt = ToNtt(params, PolyMatrixRaw::FromProto(val, params)); + v_expansion_left.push_back(val_ntt); + } + pks.v_expansion_left_ = std::move(v_expansion_left); + } + + if (proto.v_expansion_right_size() > 0) { + std::vector<PolyMatrixNtt> v_expansion_right; + for (const auto& val : proto.v_expansion_right()) { + auto val_ntt = ToNtt(params, PolyMatrixRaw::FromProto(val, params)); + + v_expansion_right.push_back(val_ntt); + } + pks.v_expansion_right_ = std::move(v_expansion_right); + } + + if (proto.v_conversion_size() > 0) { + std::vector<PolyMatrixNtt> v_conversion; + for (const auto& val : proto.v_conversion()) { + auto val_ntt = ToNtt(params, PolyMatrixRaw::FromProto(val, params)); + v_conversion.push_back(val_ntt); + } + pks.v_conversion_ = std::move(v_conversion); + } + return pks; +} + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/serialize.h b/psi/algorithm/spiral/serialize.h new file mode 100644 index 00000000..ca233097 --- /dev/null +++ b/psi/algorithm/spiral/serialize.h @@ -0,0 +1,58 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef __x86_64__ +#include <immintrin.h> +#elif defined(__aarch64__) +#include "sse2neon.h" +#endif + +#include <chrono> +#include <cstdint> +#include <iostream> +#include <string> +#include <vector> + +#include "yacl/base/buffer.h" + +#include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/poly_matrix.h" +#include "psi/algorithm/spiral/public_keys.h" +// #include "psi/algorithm/spiral/spiral_client.h" + +#include "psi/algorithm/spiral/serializable.pb.h" + +namespace psi::spiral { + +yacl::Buffer SerializePolyMatrixRaw(const PolyMatrixRaw& poly_matrix); + +PolyMatrixRaw DeserializePolyMatrixRaw(const Params& params, + yacl::Buffer& buffer); + +// the first row we use a seed to compress +yacl::Buffer SerializePolyMatrixRawRng(const PolyMatrixRaw& poly_matrix, + const Params& params); + +PolyMatrixRaw DeserializePolyMatrixRawRng(yacl::Buffer& buffer, + const Params& params, + yacl::crypto::Prg<uint64_t> rng); + +yacl::Buffer SerializeResponse(const std::vector<PolyMatrixRaw>& responses); +std::vector<PolyMatrixRaw> DeserializeResponse(const Params& params, + const yacl::Buffer& buffer); + +yacl::Buffer SerializePublicKeys(const Params& params, const PublicKeys& pks); +PublicKeys DeserializePublicKeys(const Params& params, yacl::Buffer& buffer); + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/spiral_client.cc b/psi/algorithm/spiral/spiral_client.cc new file mode 100644 index 00000000..36d6e5c2 --- /dev/null +++ b/psi/algorithm/spiral/spiral_client.cc @@ -0,0 +1,561 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/spiral/spiral_client.h" + +#include "spdlog/spdlog.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/utils/elapsed_timer.h" +#include "yacl/utils/parallel.h" + +#include "psi/algorithm/pir_interface/pir_db.h" +#include "psi/algorithm/spiral/arith/ntt.h" +#include "psi/algorithm/spiral/common.h" +#include "psi/algorithm/spiral/gadget.h" +#include "psi/algorithm/spiral/poly_matrix_utils.h" +#include "psi/algorithm/spiral/util.h" + +namespace psi::spiral { + +yacl::Buffer SpiralQuery::Serialize() { + SpiralQueryProto proto; + // only one possible + *proto.mutable_ct() = ct_.ToProto(); + proto.set_seed(reinterpret_cast<const uint8_t*>(&seed_), sizeof(uint128_t)); + + yacl::Buffer buffer(proto.ByteSizeLong()); + proto.SerializePartialToArray(buffer.data(), buffer.size()); + + return buffer; +} + +SpiralQuery SpiralQuery::Deserialize(const Params& params, + const yacl::Buffer& buffer) { + SpiralQueryProto proto; + proto.ParseFromArray(buffer.data(), buffer.size()); + + SpiralQuery query; + query.ct_ = PolyMatrixRaw::FromProto(proto.ct(), params); + + uint128_t seed{0}; + std::memcpy(&seed, proto.seed().data(), sizeof(uint128_t)); + query.seed_ = seed; + + return query; +} + +yacl::Buffer SpiralQuery::SerializeRng() { + SpiralQueryProto proto; + *proto.mutable_ct() = ct_.ToProtoRng(); + + proto.set_seed(reinterpret_cast<const uint8_t*>(&seed_), sizeof(uint128_t)); + + yacl::Buffer buffer(proto.ByteSizeLong()); + proto.SerializePartialToArray(buffer.data(), buffer.size()); + + return buffer; +} + +SpiralQuery SpiralQuery::DeserializeRng(const Params& params, + const yacl::Buffer& buffer) { + SpiralQueryProto proto; + proto.ParseFromArray(buffer.data(), buffer.size()); + + // first we construct seed and prg + uint128_t seed{0}; + std::memcpy(&seed, proto.seed().data(), sizeof(uint128_t)); + + yacl::crypto::Prg<uint64_t> rng(seed); + + SpiralQuery query; + query.seed_ = seed; + + query.ct_ = PolyMatrixRaw::FromProtoRng(proto.ct(), params, rng); + + return query; +} + +void SpiralClient::Init() { + // first init q2_params_ + q2_params_ = Params::ParamsWithModuli(params_, {kQ2Values[params_.Q2Bits()]}); + + auto [sk_gsw_rows, sk_gsw_cols] = params_.GetSkGswDims(); + auto [sk_regev_rows, sk_regev_cols] = params_.GetSkRegDims(); + + sk_gsw_ = PolyMatrixRaw::Zero(params_.PolyLen(), sk_gsw_rows, sk_gsw_cols); + + sk_reg_ = + PolyMatrixRaw::Zero(params_.PolyLen(), sk_regev_rows, sk_regev_cols); + + dg_ = DiscreteGaussian(params_.NoiseWidth()); + + sk_inited_ = false; +} + +PolyMatrixRaw SpiralClient::GetFreshGswPublicKey( + size_t m, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const { + size_t n = params_.N(); + + auto a = PolyMatrixRaw::RandomPrg(params_, 1, m, rng_pub); + auto a_ntt = ToNtt(params_, a); + auto e = Noise(params_, n, m, dg_, rng); + auto e_ntt = ToNtt(params_, e); + auto a_inv = Invert(params_, a); + auto sk_gsw_ntt = ToNtt(params_, sk_gsw_); + auto b_p = Multiply(params_, sk_gsw_ntt, a_ntt); + auto b = Add(params_, e_ntt, b_p); + auto b_raw = FromNtt(params_, b); + + return Stack(a_inv, b_raw); +} + +PolyMatrixNtt SpiralClient::GetRegevSample( + yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const { + auto a = PolyMatrixRaw::RandomPrg(params_, 1, 1, rng_pub); + auto a_ntt = ToNtt(params_, a); + auto a_inv = ToNtt(params_, Invert(params_, a)); + auto e = Noise(params_, 1, 1, dg_, rng); + + auto e_ntt = ToNtt(params_, e); + auto sk_reg_ntt = ToNtt(params_, sk_reg_); + auto b_p = Multiply(params_, sk_reg_ntt, a_ntt); + auto b = Add(params_, e_ntt, b_p); + auto p = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 2, 1); + p.CopyInto(a_inv, 0, 0); + p.CopyInto(b, 1, 0); + + return p; +} + +PolyMatrixNtt SpiralClient::GetFreshRegevPublicKey( + size_t m, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const { + auto p = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 2, m); + for (size_t i = 0; i < m; ++i) { + p.CopyInto(GetRegevSample(rng, rng_pub), 0, i); + } + return p; +} + +PolyMatrixNtt SpiralClient::EncryptMatrixGsw( + PolyMatrixNtt& ag, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const { + YACL_ENFORCE(sk_inited_, "Secret Key must be inited"); + auto mx = ag.Cols(); + auto p = GetFreshGswPublicKey(mx, rng, rng_pub); + auto p_ntt = ToNtt(params_, p); + + auto res = Add(params_, p_ntt, ag.PadTop(1)); + return res; +} + +PolyMatrixNtt SpiralClient::EncryptMatrixRegev( + PolyMatrixNtt& a, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const { + YACL_ENFORCE(sk_inited_, "Secret Key must be inited"); + auto m = a.Cols(); + auto p = GetFreshRegevPublicKey(m, rng, rng_pub); + return Add(params_, p, a.PadTop(1)); +} + +void SpiralClient::GenSecretKeys(yacl::crypto::Prg<uint64_t>& rng) { + GenTernaryMatrix(params_, sk_gsw_, kHammingWeight, rng); + GenTernaryMatrix(params_, sk_reg_, kHammingWeight, rng); + sk_gsw_full_ = MatrixWithIdentity(sk_gsw_); + sk_reg_full_ = MatrixWithIdentity(sk_reg_); + sk_inited_ = true; +} + +std::vector<PolyMatrixNtt> SpiralClient::GenExpansionParams( + size_t num_exp, size_t m_exp, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const { + auto g_exp = util::BuildGadget(params_, 1, m_exp); + auto g_exp_ntt = ToNtt(params_, g_exp); + + std::vector<PolyMatrixNtt> res; + for (size_t i = 0; i < num_exp; ++i) { + size_t t = (params_.PolyLen() / (1 << i)) + 1; + auto tau_sk_reg = Automorphism(params_, sk_reg_, t); + auto tau_sk_reg_ntt = ToNtt(params_, tau_sk_reg); + auto prod = Multiply(params_, tau_sk_reg_ntt, g_exp_ntt); + auto w_exp_i = EncryptMatrixRegev(prod, rng, rng_pub); + res.push_back(w_exp_i); + } + return res; +} + +PublicKeys SpiralClient::GenKeys(yacl::crypto::Prg<uint64_t>& rng) { + // gen sk + GenSecretKeys(rng); + + auto sk_reg_ntt = ToNtt(params_, sk_reg_); + auto sk_gsw_ntt = ToNtt(params_, sk_gsw_); + + PublicKeys pp; + uint128_t pub_seed = yacl::crypto::SecureRandU128(); + yacl::crypto::Prg<uint64_t> rng_pub(pub_seed); + + // params for packing + size_t t_conv = params_.TConv(); + auto gadget_conv = util::BuildGadget(params_, 1, t_conv); + auto gadget_conv_ntt = ToNtt(params_, gadget_conv); + + size_t n = params_.N(); + // only consider the version = 0 + size_t num_packing_mats = n; + + pp.v_packing_.reserve(num_packing_mats); + auto scaled = ScalarMultiply(params_, sk_reg_ntt, gadget_conv_ntt); + for (size_t i = 0; i < num_packing_mats; ++i) { + // Page-20, Packing Regev encodings, PackSetup + auto ag = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), n, t_conv); + ag.CopyInto(scaled, i, 0); + auto w = EncryptMatrixGsw(ag, rng, rng_pub); + pp.v_packing_.push_back(w); + } + + // we defaulta use QueryExpand = true + pp.v_expansion_left_ = + GenExpansionParams(params_.G(), params_.TExpLeft(), rng, rng_pub); + // we only using the version = 0, so pp.v_expansion_right_ must be inited + pp.v_expansion_right_ = GenExpansionParams(params_.StopRound() + 1, + params_.TExpRight(), rng, rng_pub); + // params for conversion + auto g_conv = util::BuildGadget(params_, 2, 2 * t_conv); + auto sk_reg_square_ntt = Multiply(params_, sk_reg_ntt, sk_reg_ntt); + // Page-14 (3.1) + pp.v_conversion_ = std::vector<PolyMatrixNtt>{PolyMatrixNtt::Zero( + params_.CrtCount(), params_.PolyLen(), 2, 2 * t_conv)}; + + for (size_t i = 0; i < 2 * t_conv; ++i) { + PolyMatrixNtt sigma; + if (i % 2 == 0) { + uint64_t val = g_conv.Poly(0, i)[0]; + auto val_ntt = + ToNtt(params_, PolyMatrixRaw::SingleValue(params_.PolyLen(), val)); + sigma = Multiply(params_, sk_reg_square_ntt, val_ntt); + } else { + uint64_t val = g_conv.Poly(1, i)[0]; + auto val_ntt = + ToNtt(params_, PolyMatrixRaw::SingleValue(params_.PolyLen(), val)); + sigma = Multiply(params_, sk_reg_ntt, val_ntt); + } + auto ct = EncryptMatrixRegev(sigma, rng, rng_pub); + pp.v_conversion_[0].CopyInto(ct, 0, i); + } + + return pp; +} + +SpiralQuery SpiralClient::GenQueryInternal(size_t pt_idx_target) const { + size_t further_dims = params_.DbDim2(); + size_t idx_dim0 = pt_idx_target / (1 << further_dims); + size_t idx_futher = pt_idx_target % (1 << further_dims); + uint64_t scale_k = params_.ScaleK(); + size_t t_gsw = params_.TGsw(); + size_t bits_per = util::GetBitsPer(params_, t_gsw); + + uint64_t modulus_cr0 = params_.BarrettCr0Modulus(); + uint64_t modulus_cr1 = params_.BarrettCr1Modulus(); + + yacl::crypto::Prg<uint64_t> rng(yacl::crypto::SecureRandU128()); + // a empty query + SpiralQuery query; + uint128_t query_seed; + rng.Fill(absl::MakeSpan(reinterpret_cast<uint8_t*>(&query_seed), + sizeof(query_seed))); + yacl::crypto::Prg<uint64_t> rng_pub(query_seed); + query.seed_ = query_seed; + + // We default to using QueryExpand technology + auto sigma = PolyMatrixRaw::Zero(params_.PolyLen(), 1, 1); + uint64_t inv_2_g_first = + arith::InvertUintMod(1 << params_.G(), params_.ModulusSeal()); + uint64_t inv_2_g_rest = arith::InvertUintMod(1 << (params_.StopRound() + 1), + params_.ModulusSeal()); + + if (params_.DbDim2() == 0) { + for (size_t i = 0; i < static_cast<size_t>(1 << params_.DbDim1()); ++i) { + if (i == idx_dim0) { + sigma.Data()[i] = scale_k; + } + } + for (size_t i = 0; i < params_.PolyLen(); ++i) { + sigma.Data()[i] = + arith::MultiplyUintMod(sigma.Data()[i], inv_2_g_first, + params_.Modulus(), modulus_cr0, modulus_cr1); + } + + } else { + for (size_t i = 0; i < static_cast<size_t>(1 << params_.DbDim1()); ++i) { + if (i == idx_dim0) { + sigma.Data()[2 * i] = scale_k; + } + } + + for (size_t l = 0; l < further_dims; ++l) { + uint64_t mask = 1ULL << l; + bool bit = (idx_futher & mask) == mask; + for (size_t k = 0; k < params_.TGsw(); ++k) { + uint64_t val = bit ? 1ULL << (bits_per * k) : 0; + size_t idx = l * params_.TGsw() + k; + sigma.Data()[2 * idx + 1] = val; + } + } + + for (size_t i = 0; i < (params_.PolyLen() >> 1); ++i) { + sigma.Data()[2 * i] = + arith::MultiplyUintMod(sigma.Data()[2 * i], inv_2_g_first, + params_.Modulus(), modulus_cr0, modulus_cr1); + + sigma.Data()[2 * i + 1] = + arith::MultiplyUintMod(sigma.Data()[2 * i + 1], inv_2_g_rest, + params_.Modulus(), modulus_cr0, modulus_cr1); + } + } + auto sigma_ntt = ToNtt(params_, sigma); + // when use ExpandQuery, the Query contains only one Regev Ciphertext + query.ct_ = FromNtt(params_, EncryptMatrixRegev(sigma_ntt, rng, rng_pub)); + + return query; +} + +std::vector<uint8_t> SpiralClient::DecodeResponse( + const std::vector<PolyMatrixRaw>& response, size_t raw_idx_target) const { + YACL_ENFORCE_EQ(response.size(), partition_num_); + + yacl::ElapsedTimer timer; + + std::vector<std::vector<uint8_t>> results; + results.reserve(partition_num_); + for (size_t i = 0; i < partition_num_; ++i) { + auto decode_result = DecodeResponseInternal(response[i]); + + // now we extract the data from our target row + YACL_ENFORCE_EQ(decode_result.Data().size(), params_.PtCoeffs()); + + auto bytes = util::ConvertCoeffsToBytes(decode_result.Data(), + params_.PtModulusBitLen()); + size_t offset = raw_idx_target % element_size_of_pt_; + + // note that the computation of element_byte_len + size_t element_byte_len = + std::min(params_.MaxByteLenOfPt(), database_info_.byte_size_per_row_); + std::vector<uint8_t> tmp(element_byte_len); + // just copy + std::memcpy(tmp.data(), bytes.data() + offset * element_byte_len, + sizeof(uint8_t) * element_byte_len); + // save + results.push_back(std::move(tmp)); + } + + auto final_result = pir_utils::RawDatabase::Combine( + results, database_info_.byte_size_per_row_); + return final_result; +} + +PolyMatrixRaw SpiralClient::DecodeResponseInternal( + const PolyMatrixRaw& response) const { + uint64_t p = params_.PtModulus(); + uint64_t q1 = 4 * p; + uint64_t q2 = kQ2Values[params_.Q2Bits()]; + size_t n = params_.N(); + size_t poly_len = params_.PolyLen(); + + auto sk_gsw_q2 = PolyMatrixRaw::Zero(q2_params_.PolyLen(), n, 1); + for (size_t i = 0; i < poly_len * n; ++i) { + sk_gsw_q2.Data()[i] = + arith::Recenter(sk_gsw_.Data()[i], params_.Modulus(), q2); + } + // for mul + auto sk_gsw_q2_ntt = + PolyMatrixNtt::Zero(q2_params_.CrtCount(), q2_params_.PolyLen(), n, 1); + ToNtt(q2_params_, sk_gsw_q2_ntt, sk_gsw_q2); + + auto result = PolyMatrixRaw::Zero(params_.PolyLen(), n, n); + + auto packed_ct = response; + // \hat c_1 + auto first_row = packed_ct.SubMatrix(0, 0, 1, packed_ct.Cols()); + // \hat c_2 + auto rest_rows = + packed_ct.SubMatrix(1, 0, packed_ct.Rows() - 1, packed_ct.Cols()); + // (1, n) + auto first_row_q2 = + PolyMatrixNtt::Zero(q2_params_.CrtCount(), q2_params_.PolyLen(), 1, n); + ToNtt(q2_params_, first_row_q2, first_row); + // \tilde s \hat c_1^T + auto sk_prod = + FromNtt(q2_params_, Multiply(q2_params_, sk_gsw_q2_ntt, first_row_q2)); + + auto q1_i64 = static_cast<int64_t>(q1); + auto q2_i64 = static_cast<int64_t>(q2); + int128_t p_i128 = yacl::MakeInt128(0, p); + + for (size_t i = 0; i < n * n * poly_len; ++i) { + WEAK_ENFORCE(i < sk_prod.Data().size()); + auto val_first = static_cast<int64_t>(sk_prod.Data()[i]); + + if (val_first >= q2_i64 / 2) { + val_first -= q2_i64; + } + WEAK_ENFORCE(i < rest_rows.Data().size()); + int64_t val_rest = static_cast<int64_t>(rest_rows.Data()[i]); + if (val_rest >= q1_i64 / 2) { + val_rest -= q1_i64; + } + + auto denominator = static_cast<int64_t>(q2 * (q1 / p)); + int64_t r = val_first * q1_i64; + r += (val_rest * q2_i64); + + // divide r by q2, rounding + int64_t sign = r >= 0 ? 1 : -1; + int64_t tmp = r + sign * (denominator / 2); + auto res = static_cast<int128_t>(tmp / denominator); + + // int64_t can directly compute with int128_t + int128_t middle = denominator / p_i128; + int128_t right = 2 * p_i128; + res = (res + middle + right) % p_i128; + + // get the low 64-bit + // WEAK_ENFORCE(idx < result.Data().size()); + result.Data()[i] = yacl::DecomposeInt128(res).second; + } + + return result; +} + +PolyMatrixRaw SpiralClient::DecodeResponseInternal( + const std::vector<PolyMatrixRaw>& response) const { + uint64_t p = params_.PtModulus(); + uint64_t q1 = 4 * p; + uint64_t q2 = kQ2Values[params_.Q2Bits()]; + size_t n = params_.N(); + size_t poly_len = params_.PolyLen(); + + auto sk_gsw_q2 = PolyMatrixRaw::Zero(q2_params_.PolyLen(), n, 1); + for (size_t i = 0; i < poly_len * n; ++i) { + sk_gsw_q2.Data()[i] = + arith::Recenter(sk_gsw_.Data()[i], params_.Modulus(), q2); + } + // for mul + auto sk_gsw_q2_ntt = + PolyMatrixNtt::Zero(q2_params_.CrtCount(), q2_params_.PolyLen(), n, 1); + ToNtt(q2_params_, sk_gsw_q2_ntt, sk_gsw_q2); + + auto result = + PolyMatrixRaw::Zero(params_.PolyLen(), params_.Instances() * n, n); + + for (size_t ins = 0; ins < params_.Instances(); ++ins) { + auto packed_ct = response[ins]; + // \hat c_1 + auto first_row = packed_ct.SubMatrix(0, 0, 1, packed_ct.Cols()); + // \hat c_2 + auto rest_rows = + packed_ct.SubMatrix(1, 0, packed_ct.Rows() - 1, packed_ct.Cols()); + // (1, n) + auto first_row_q2 = + PolyMatrixNtt::Zero(q2_params_.CrtCount(), q2_params_.PolyLen(), 1, n); + ToNtt(q2_params_, first_row_q2, first_row); + // \tilde s \hat c_1^T + auto sk_prod = + FromNtt(q2_params_, Multiply(q2_params_, sk_gsw_q2_ntt, first_row_q2)); + + auto q1_i64 = static_cast<int64_t>(q1); + auto q2_i64 = static_cast<int64_t>(q2); + int128_t p_i128 = yacl::MakeInt128(0, p); + + for (size_t i = 0; i < n * n * poly_len; ++i) { + WEAK_ENFORCE(i < sk_prod.Data().size()); + auto val_first = static_cast<int64_t>(sk_prod.Data()[i]); + + if (val_first >= q2_i64 / 2) { + val_first -= q2_i64; + } + WEAK_ENFORCE(i < rest_rows.Data().size()); + int64_t val_rest = static_cast<int64_t>(rest_rows.Data()[i]); + if (val_rest >= q1_i64 / 2) { + val_rest -= q1_i64; + } + + auto denominator = static_cast<int64_t>(q2 * (q1 / p)); + int64_t r = val_first * q1_i64; + r += (val_rest * q2_i64); + + // divide r by q2, rounding + int64_t sign = r >= 0 ? 1 : -1; + int64_t tmp = r + sign * (denominator / 2); + auto res = static_cast<int128_t>(tmp / denominator); + + // int64_t can directly compute with int128_t + int128_t middle = denominator / p_i128; + int128_t right = 2 * p_i128; + res = (res + middle + right) % p_i128; + size_t idx = ins * n * n * poly_len + i; + + // get the low 64-bit + WEAK_ENFORCE(idx < result.Data().size()); + result.Data()[idx] = yacl::DecomposeInt128(res).second; + } + } + + return result; +} + +// util methods +void ReorientRegCiphertexts(const Params& params, std::vector<uint64_t>& out, + const std::vector<PolyMatrixNtt>& v_reg) { + size_t poly_len = params.PolyLen(); + size_t crt_count = params.CrtCount(); + + WEAK_ENFORCE(crt_count == static_cast<size_t>(2)); + WEAK_ENFORCE(arith::Log2(params.Moduli(0)) <= static_cast<uint64_t>(32)); + + size_t num_reg_expanded = 1 << params.DbDim1(); + size_t ct_rows = v_reg[0].Rows(); + size_t ct_cols = v_reg[0].Cols(); + + WEAK_ENFORCE(ct_rows == static_cast<size_t>(2)); + WEAK_ENFORCE(ct_cols == static_cast<size_t>(1)); + + uint64_t moduli0 = params.Moduli(0); + uint64_t moduli1 = params.Moduli(1); + + // the improvment is about 15ms, compared the naive for-loop + yacl::parallel_for(0, num_reg_expanded, [&](size_t begin, size_t end) { + for (size_t j = begin; j < end; ++j) { + for (size_t r = 0; r < ct_rows; ++r) { + for (size_t m = 0; m < ct_cols; ++m) { + for (size_t z = 0; z < poly_len; ++z) { + size_t idx_in = r * (ct_cols * crt_count * poly_len) + + m * (crt_count * poly_len); + size_t idx_out = z * (num_reg_expanded * ct_cols * ct_rows) + + j * (ct_cols * ct_rows) + m * ct_rows + r; + + uint64_t val1 = v_reg[j].Data()[idx_in + z] % moduli0; + uint64_t val2 = v_reg[j].Data()[idx_in + poly_len + z] % moduli1; + out[idx_out] = val1 | (val2 << 32); + } + } + } + } + }); +} + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/spiral_client.h b/psi/algorithm/spiral/spiral_client.h new file mode 100644 index 00000000..b72fca83 --- /dev/null +++ b/psi/algorithm/spiral/spiral_client.h @@ -0,0 +1,206 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <cstddef> +#include <optional> +#include <utility> +#include <vector> + +#include "yacl/base/int128.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/crypto/tools/prg.h" + +#include "psi/algorithm/pir_interface/index_pir.h" +#include "psi/algorithm/spiral/discrete_gaussian.h" +#include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/poly_matrix.h" +#include "psi/algorithm/spiral/public_keys.h" +#include "psi/algorithm/spiral/serialize.h" + +#include "psi/algorithm/spiral/serializable.pb.h" + +namespace psi::spiral { + +struct SpiralQuery { + // When ExpandQuery = true, ct_ contains one Regev ciphertext + PolyMatrixRaw ct_; + + // we can use seed to compress Query + uint128_t seed_; + + SpiralQuery() = default; + + bool operator==(const SpiralQuery& other) const { + return this->ct_ == other.ct_ && this->seed_ == other.seed_; + } + + yacl::Buffer Serialize(); + yacl::Buffer SerializeRng(); + static SpiralQuery Deserialize(const Params& params, + const yacl::Buffer& buffer); + static SpiralQuery DeserializeRng(const Params& params, + const yacl::Buffer& buffer); +}; + +class SpiralClient : public psi::pir::IndexPirClient { + public: + explicit SpiralClient(Params params) : params_(std::move(params)) { Init(); } + + SpiralClient(Params params, DatabaseMetaInfo database_info) + : params_(std::move(params)), database_info_(database_info) { + Init(); + + size_t element_byte_len = + std::min(database_info_.byte_size_per_row_, params_.MaxByteLenOfPt()); + partition_num_ = + (database_info_.byte_size_per_row_ + params_.MaxByteLenOfPt() - 1) / + params_.MaxByteLenOfPt(); + + element_size_of_pt_ = params_.ElementSizeOfPt(element_byte_len); + } + + PublicKeys GenKeys(uint128_t seed) { + yacl::crypto::Prg<uint64_t> prg(seed); + return GenKeys(prg); + } + PublicKeys GenKeys() { return GenKeys(yacl::crypto::SecureRandU128()); } + + SpiralQuery GenQuery(size_t raw_idx_target) const { + size_t pt_idx_target = raw_idx_target / element_size_of_pt_; + return GenQueryInternal(pt_idx_target); + } + + yacl::Buffer GenPublicKeys() { + return SerializePublicKeys(params_, GenKeys()); + } + + std::vector<uint8_t> DecodeResponse( + const std::vector<PolyMatrixRaw>& response, size_t raw_idx_target) const; + + const PolyMatrixRaw& GetSkRegev() const { return sk_reg_; } + + const PolyMatrixRaw& GetSkGsw() const { return sk_gsw_; } + + const PolyMatrixRaw& GetSkRegevFull() const { return sk_reg_full_; } + + const PolyMatrixRaw& GetSkGswFull() const { return sk_gsw_full_; } + + bool GetSkInited() const { return sk_inited_; } + + const Params& GetParams() const { return params_; }; + + const Params& GetQ2Params() const { return q2_params_; } + + ~SpiralClient() override = default; + + yacl::Buffer GenerateIndexQuery(uint64_t raw_idx) const override { + auto query = GenQuery(raw_idx); + + return query.SerializeRng(); + } + + std::vector<uint8_t> DecodeIndexResponse(const yacl::Buffer& response_buffer, + uint64_t raw_idx) const override { + auto response = DeserializeResponse(params_, response_buffer); + + return DecodeResponse(response, raw_idx); + } + + protected: + SpiralQuery GenQueryInternal(size_t pt_idx_target) const; + + PolyMatrixRaw DecodeResponseInternal( + const std::vector<PolyMatrixRaw>& response) const; + + PolyMatrixRaw DecodeResponseInternal(const PolyMatrixRaw& response) const; + + PolyMatrixRaw GetFreshGswPublicKey( + size_t m, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const; + + PolyMatrixNtt GetRegevSample(yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const; + + PolyMatrixNtt GetFreshRegevPublicKey( + size_t m, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const; + PolyMatrixNtt DecryptMatrixRegev(const PolyMatrixNtt& a) const { + auto sk_reg_full_ntt = ToNtt(GetParams(), sk_reg_full_); + return Multiply(GetParams(), sk_reg_full_ntt, a); + } + + PolyMatrixNtt DecryptMatrixGsw(const PolyMatrixNtt& a) const { + auto sk_gsw_full_ntt = ToNtt(GetParams(), sk_gsw_full_); + return Multiply(GetParams(), sk_gsw_full_ntt, a); + } + + PolyMatrixNtt EncryptMatrixGsw(PolyMatrixNtt& ag, + yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const; + + PolyMatrixNtt EncryptMatrixRegev(PolyMatrixNtt& a, + yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const; + + private: + void Init(); + // core implementation + void GenSecretKeys(yacl::crypto::Prg<uint64_t>& rng); + + void GenSecretKeys(uint128_t seed) { + yacl::crypto::Prg<uint64_t> prg(seed); + GenSecretKeys(prg); + } + + void GenSecretKeys() { GenSecretKeys(yacl::crypto::SecureRandU128()); } + + PublicKeys GenKeys(yacl::crypto::Prg<uint64_t>& rng); + + std::vector<PolyMatrixNtt> GenExpansionParams( + size_t num_exp, size_t m_exp, yacl::crypto::Prg<uint64_t>& rng, + yacl::crypto::Prg<uint64_t>& rng_pub) const; + + // Params + Params params_; + + // just for decode, the given moduli is q2 + Params q2_params_; + + PolyMatrixRaw sk_gsw_; + + PolyMatrixRaw sk_reg_; + + PolyMatrixRaw sk_gsw_full_; + + PolyMatrixRaw sk_reg_full_; + + DiscreteGaussian dg_; + + bool sk_inited_ = false; + + DatabaseMetaInfo database_info_; + + // element size per Regev plaintext, R_p^{n*n} + size_t element_size_of_pt_ = 0; + + size_t partition_num_ = 1; +}; + +// util methods +void ReorientRegCiphertexts(const Params& params, std::vector<uint64_t>& out, + const std::vector<PolyMatrixNtt>& v_reg); + +} // namespace psi::spiral diff --git a/psi/algorithm/spiral/spiral_client_test.cc b/psi/algorithm/spiral/spiral_client_test.cc new file mode 100644 index 00000000..18f2c43f --- /dev/null +++ b/psi/algorithm/spiral/spiral_client_test.cc @@ -0,0 +1,161 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/spiral/spiral_client.h" + +#include <optional> + +#include "absl/types/span.h" +#include "gtest/gtest.h" +#include "spdlog/spdlog.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/crypto/tools/prg.h" + +#include "psi/algorithm/spiral/poly_matrix_utils.h" +#include "psi/algorithm/spiral/public_keys.h" +#include "psi/algorithm/spiral/serialize.h" +#include "psi/algorithm/spiral/util.h" + +namespace psi::spiral { + +namespace { +class SpiralClientDerive : public SpiralClient { + public: + using SpiralClient::DecodeResponseInternal; + using SpiralClient::DecryptMatrixGsw; + using SpiralClient::DecryptMatrixRegev; + using SpiralClient::EncryptMatrixGsw; + using SpiralClient::EncryptMatrixRegev; + using SpiralClient::GenQueryInternal; + using SpiralClient::GetFreshGswPublicKey; + using SpiralClient::GetFreshRegevPublicKey; + using SpiralClient::GetRegevSample; + + explicit SpiralClientDerive(Params params, DatabaseMetaInfo database_info) + : SpiralClient(std::move(params), std::move(database_info)) {} + + explicit SpiralClientDerive(Params params) + : SpiralClient(std::move(params)) {} +}; +constexpr size_t kMaxLoop{1}; + +} // namespace + +TEST(Client, QuerySerialize) { + // get a SpiralParams + auto params = util::GetPerformanceImproveParam(); + auto params2 = util::GetPerformanceImproveParam(); + + // new client + SpiralClientDerive client(std::move(params2)); + client.GenKeys(); + + // gen random target_idx + std::random_device rd; + std::mt19937_64 rng(rd()); + + for (size_t i = 0; i < kMaxLoop; ++i) { + auto query = client.GenQueryInternal(rng() % params.NumItems()); + + SPDLOG_DEBUG("query seed: {}", query.seed_); + + auto buffer = query.Serialize(); + + SPDLOG_INFO("query buffer size: {} bytes, {} kb", buffer.size(), + buffer.size() / 1024); + + auto query2 = SpiralQuery::Deserialize(params, buffer); + + ASSERT_EQ(query, query2); + } +} + +TEST(Client, PolyMatrixRawRngSerialize) { + // get a SpiralParams + auto params = util::GetPerformanceImproveParam(); + auto params2 = util::GetPerformanceImproveParam(); + + // new client + SpiralClientDerive client(std::move(params2)); + client.GenKeys(); + + // gen random target_idx + std::random_device rd; + std::mt19937_64 rng(rd()); + + for (size_t i = 0; i < kMaxLoop; ++i) { + auto query = client.GenQueryInternal(rng() % params.NumItems()); + + // serialize ct + auto& ct = query.ct_; + yacl::Buffer buffer = SerializePolyMatrixRawRng(ct, params); + + SPDLOG_DEBUG("use seed compress, buffer size {} kb", buffer.size() / 1024); + + auto seed = query.seed_; + yacl::crypto::Prg<uint64_t> rng(seed); + + auto ct2 = DeserializePolyMatrixRawRng(buffer, params, rng); + + ASSERT_EQ(ct, ct2); + } +} + +TEST(Client, QueryRngSerialize) { + // get a SpiralParams + auto params = util::GetPerformanceImproveParam(); + auto params2 = util::GetPerformanceImproveParam(); + + // new client + SpiralClientDerive client(std::move(params2)); + client.GenKeys(); + + // gen random target_idx + std::random_device rd; + std::mt19937_64 rng(rd()); + + for (size_t i = 0; i < kMaxLoop; ++i) { + auto query = client.GenQueryInternal(rng() % params.NumItems()); + + SPDLOG_DEBUG("query seed: {}", query.seed_); + + auto buffer = query.SerializeRng(); + + SPDLOG_INFO("use seed compress, query buffer size: {} bytes, {} kb", + buffer.size(), buffer.size() / 1024); + + auto query2 = SpiralQuery::DeserializeRng(params, buffer); + + ASSERT_EQ(query, query2); + } +} + +TEST(Client, PublicParamsSerialize) { + // get a SpiralParams + auto params = util::GetPerformanceImproveParam(); + auto params2 = util::GetPerformanceImproveParam(); + // new client + SpiralClientDerive client(std::move(params2)); + for (size_t i = 0; i < kMaxLoop; ++i) { + auto pp = client.GenKeys(); + auto buffer = SerializePublicKeys(params, pp); + + SPDLOG_DEBUG("public params buffer size: {} kb", buffer.size() / 1024); + auto pp2 = DeserializePublicKeys(params, buffer); + + ASSERT_EQ(pp, pp2); + } +} + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/spiral_pir_test.cc b/psi/algorithm/spiral/spiral_pir_test.cc new file mode 100644 index 00000000..edf0a44b --- /dev/null +++ b/psi/algorithm/spiral/spiral_pir_test.cc @@ -0,0 +1,176 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <random> + +#include "absl/types/span.h" +#include "gtest/gtest.h" +#include "spdlog/spdlog.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/crypto/tools/prg.h" +#include "yacl/utils/elapsed_timer.h" + +#include "psi/algorithm/pir_interface/pir_db.h" +#include "psi/algorithm/spiral/gadget.h" +#include "psi/algorithm/spiral/poly_matrix_utils.h" +#include "psi/algorithm/spiral/public_keys.h" +#include "psi/algorithm/spiral/spiral_client.h" +#include "psi/algorithm/spiral/spiral_server.h" +#include "psi/algorithm/spiral/util.h" + +namespace psi::spiral { + +namespace { + +struct TestParams { + size_t database_rows_ = 0; + size_t database_row_byte_ = 0; + bool serialized_ = false; +}; + +[[maybe_unused]] std::vector<std::vector<uint8_t>> GenRandomDatabase( + size_t rows, size_t lens) { + yacl::crypto::Prg<uint8_t> prg; + std::vector<std::vector<uint8_t>> database; + for (size_t i = 0; i < rows; ++i) { + std::vector<uint8_t> row(lens); + prg.Fill(absl::MakeSpan(row)); + database.push_back(std::move(row)); + } + return database; +} + +} // namespace + +class SpiralPirTest : public testing::TestWithParam<TestParams> {}; + +TEST_P(SpiralPirTest, Works) { + // get a test params + auto test_param = GetParam(); + auto database_rows = test_param.database_rows_; + auto row_byte = test_param.database_row_byte_; + auto serialized = test_param.serialized_; + DatabaseMetaInfo database_info(database_rows, row_byte); + + SPDLOG_INFO("database rows: {}, row bytes: {}", database_rows, row_byte); + + yacl::ElapsedTimer timer; + + // Gen database + SPDLOG_INFO("GenRandomDatabase, this will take much time"); + // auto raw_database = GenRandomDatabase(database_rows, row_byte); + pir_utils::RawDatabase raw_database = + pir_utils::RawDatabase::Random(database_rows, row_byte); + SPDLOG_INFO("GenRandomDatabase, time cost: {} ms", timer.CountMs()); + + // get a SpiralParams + auto spiral_params = util::GetDefaultParam(); + spiral_params.UpdateByDatabaseInfo(database_info); + + SPDLOG_INFO("MaxByteLenofPt: {}, MaxBitLenOfPt: {}", + spiral_params.MaxByteLenOfPt(), spiral_params.MaxBitLenOfPt()); + + Params params_client(spiral_params); + Params params_server(spiral_params); + + SPDLOG_INFO("Spiral Params: \n{}", spiral_params.ToString()); + + // new client + SpiralClient client(std::move(params_client), database_info); + + // new Server + SpiralServer server(std::move(params_server), database_info); + + // set database + timer.Restart(); + server.SetDatabase(raw_database); + SPDLOG_INFO("Server SetDatabase, time cost: {} ms", timer.CountMs()); + + // gen random target_idx + std::random_device rd; + std::mt19937_64 rng(rd()); + size_t raw_idx_target = rng() % database_rows; + std::vector<uint8_t> correct_row(raw_database.At(raw_idx_target)); + + yacl::ElapsedTimer timer2; + + // query and response + if (!serialized) { + auto pp = client.GenKeys(); + SPDLOG_INFO("Do query without serialized"); + + // set public paramter + server.SetPublicKeys(std::move(pp)); + + // now generate Query + timer2.Restart(); + timer.Restart(); + auto query = client.GenQuery(raw_idx_target); + SPDLOG_INFO("Client GenQuery, time cost: {} ms", timer.CountMs()); + + // server handle query + timer.Restart(); + auto responses = server.ProcessQuery(query); + SPDLOG_INFO("Server ProcessQuery, time cost: {} ms", timer.CountMs()); + + timer.Restart(); + auto decode = client.DecodeResponse(responses, raw_idx_target); + SPDLOG_INFO("Client DecodeResponse, time cost: {} ms", timer.CountMs()); + + // verify + EXPECT_EQ(correct_row, decode); + + } else { + SPDLOG_INFO("Do query with serialized"); + + timer.Restart(); + auto pp_buffer = client.GenPublicKeys(); + SPDLOG_INFO("public params gen time cost {} ms", timer.CountMs()); + SPDLOG_INFO("public params serialize size {} kb", pp_buffer.size() / 1024); + + server.SetPublicKeys(pp_buffer); + + timer2.Restart(); + timer.Restart(); + auto query_buffer = client.GenerateIndexQuery(raw_idx_target); + + SPDLOG_INFO("Client GenQuery, time cost: {} ms", timer.CountMs()); + SPDLOG_INFO("query serialize size {} kb", query_buffer.size() / 1024); + + timer.Restart(); + auto response_buffer = server.GenerateIndexResponse(query_buffer); + SPDLOG_INFO("Server ProcessQuery, time cost: {} ms", timer.CountMs()); + SPDLOG_INFO("response serialize size {} kb", response_buffer.size() / 1024); + + // client decode + timer.Restart(); + auto decode = client.DecodeIndexResponse(response_buffer, raw_idx_target); + SPDLOG_INFO("Client DecodeResponse, time cost: {} ms", timer.CountMs()); + + // verify + EXPECT_EQ(correct_row, decode); + } + + SPDLOG_INFO("database rows: {}, row bytes: {}", database_rows, row_byte); + SPDLOG_INFO("One time query ,total time: {} ms", timer2.CountMs()); +} + +INSTANTIATE_TEST_SUITE_P(Works_Instances, SpiralPirTest, + testing::Values(TestParams{1000000, 256}, + TestParams{100000, 256, true}, + // large value + TestParams{10000, 8193, true}, + TestParams{1000, 8192 * 10, true})); + +} // namespace psi::spiral diff --git a/psi/algorithm/spiral/spiral_server.cc b/psi/algorithm/spiral/spiral_server.cc new file mode 100644 index 00000000..fe1fb962 --- /dev/null +++ b/psi/algorithm/spiral/spiral_server.cc @@ -0,0 +1,736 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/spiral/spiral_server.h" + +#include <algorithm> + +#include "spdlog/spdlog.h" +#include "yacl/utils/elapsed_timer.h" +#include "yacl/utils/parallel.h" + +#include "psi/algorithm/spiral/arith/arith_params.h" +#include "psi/algorithm/spiral/arith/ntt.h" +#include "psi/algorithm/spiral/common.h" +#include "psi/algorithm/spiral/gadget.h" +#include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/poly_matrix_utils.h" +#include "psi/algorithm/spiral/util.h" + +namespace psi::spiral { +std::vector<uint64_t> SpiralServer::ReorientRawDb( + const std::vector<std::vector<uint8_t>>& raw_database) { + // first, we convert raw_database into plaintexts in SpiralPIR, just R_q^{n*n} + std::vector<uint8_t> combined_bytes; + for (const auto& raw : raw_database) { + combined_bytes.insert(combined_bytes.end(), raw.begin(), raw.end()); + } + + YACL_ENFORCE_EQ(raw_database.size(), database_info_.rows_); + YACL_ENFORCE_LE(raw_database[0].size(), params_.MaxByteLenOfPt()); + + // here, we only consider one row of raw data can be holded by one plaintext + // in SpiralPIR + size_t element_byte_len = + std::min(database_info_.byte_size_per_row_, params_.MaxByteLenOfPt()); + // the number of one plaintext can hold the rows in raw database + size_t element_size_of_pt = params_.ElementSizeOfPt(element_byte_len); + // we can conmpute how many plaintexts can be used to hold the whole raw + // database + size_t plaintext_size = + arith::UintNum(raw_database.size(), element_size_of_pt); + // now we convert raw data to plaintext + // the total plaintext size + size_t prod = 1 << (params_.DbDim1() + params_.DbDim2()); + // one Plaintext can hold how many bytes + size_t byte_size_of_pt = element_size_of_pt * element_byte_len; + // the total bytes of database + size_t total_byte_size = database_info_.rows_ * element_byte_len; + // (one plaintext can hold the number of rows) * (one pt provided the coeff + // nums for one row) + size_t used_coeff_size = + element_size_of_pt * + arith::UintNum(8 * element_byte_len, params_.PtModulusBitLen()); + + YACL_ENFORCE_LE(used_coeff_size, + params_.N() * params_.N() * params_.PolyLen()); + + size_t offset = 0; + + std::vector<std::vector<uint64_t>> coeff_vec; + + for (size_t i = 0; i < plaintext_size; ++i) { + size_t process_byte_size = 0; + if (total_byte_size <= offset) { + break; + } else if (total_byte_size < offset + byte_size_of_pt) { + process_byte_size = total_byte_size - offset; + } else { + process_byte_size = byte_size_of_pt; + } + YACL_ENFORCE(process_byte_size % element_byte_len == 0); + + auto coeffs = util::ConvertBytesToCoeffs(params_.PtModulusBitLen(), offset, + process_byte_size, combined_bytes); + YACL_ENFORCE_LE(coeffs.size(), used_coeff_size); + offset += process_byte_size; + + // padding coeffs + // we need the coeffs length will be n^2 * len + while (coeffs.size() < params_.PtCoeffs()) { + coeffs.push_back(1ULL); + } + coeff_vec.push_back(std::move(coeffs)); + } + // + size_t cur_plaintext_size = coeff_vec.size(); + YACL_ENFORCE(cur_plaintext_size <= plaintext_size); + // now padding the size to prod + while (cur_plaintext_size < prod) { + std::vector<uint64_t> coeffs(params_.PtCoeffs(), 1ULL); + coeff_vec.push_back(std::move(coeffs)); + ++cur_plaintext_size; + } + + // finally, we obtain a coeff_vec, which means plaintexts + // we need to reorient it + auto reorient_db = ReorientDatabase(params_, coeff_vec); + + return reorient_db; +} + +void SpiralServer::SetDatabase(const pir_utils::RawDatabase& raw_database) { + size_t partition_byte_len = params_.MaxByteLenOfPt(); + // one Pt can hold one row data + // do not need to partition + if (partition_byte_len >= raw_database.RowByteLen()) { + // reoriented_dbs_.push_back(ReorientRawDb(raw_database.Db())); + reoriented_dbs_ = ReorientRawDb(raw_database.Db()); + single_db_size_ = reoriented_dbs_.size(); + database_seted_ = true; + partition_num_ = 1; + return; + } + // now we need to Partition the raw database + partition_num_ = + (raw_database.RowByteLen() + partition_byte_len - 1) / partition_byte_len; + auto sub_dbs = raw_database.Partition(partition_byte_len); + + // now we handle each sub db + // reoriented_dbs_.resize(partition_num_); + for (size_t j = 0; j < partition_num_; ++j) { + std::vector<uint64_t> tmp = ReorientRawDb(sub_dbs[j].Db()); + + if (j == 0) { + reoriented_dbs_.reserve(tmp.size() * partition_num_); + single_db_size_ = tmp.size(); + } + YACL_ENFORCE_EQ(single_db_size_, tmp.size()); + + reoriented_dbs_.insert(reoriented_dbs_.end(), tmp.begin(), tmp.end()); + + // reoriented_dbs_[j] = std::move(ReorientRawDb(sub_dbs[j].Db())); + } + + database_seted_ = true; +} + +void SpiralServer::CoefficientExpansion( + std::vector<PolyMatrixNtt>& v, size_t g, size_t stop_round, + const std::vector<PolyMatrixNtt>& v_w_left, + const std::vector<PolyMatrixNtt>& v_w_right, + const std::vector<PolyMatrixNtt>& v_neg1, + size_t max_btis_to_gen_right) const { + size_t poly_len = params_.PolyLen(); + + size_t t_exp_left = params_.TExpLeft(); + size_t t_exp_right = params_.TExpRight(); + + for (size_t i = 0; i < g; ++i) { + size_t num_in = static_cast<size_t>(1) << i; + size_t t = (poly_len / (1 << i)) + 1; + + const auto& neg1 = v_neg1[i]; + + // closure + auto action_expand = [&](size_t j, PolyMatrixNtt& fj) { + bool cond1 = stop_round > 0 && i > stop_round && (j % 2) == 1; + bool cond2 = stop_round > 0 && i == stop_round && (j % 2 == 1) && + ((j / 2) >= max_btis_to_gen_right); + + if (cond1 || cond2) { + return; + } + auto ct = PolyMatrixRaw::Zero(params_.PolyLen(), 2, 1); + auto ct_auto = PolyMatrixRaw::Zero(params_.PolyLen(), 2, 1); + auto ct_auto1 = PolyMatrixRaw::Zero(params_.PolyLen(), 1, 1); + auto ct_auto1_ntt = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 1, 1); + auto w_times_g_inv_ct = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 2, 1); + + auto g_inv_ct_left = + PolyMatrixRaw::Zero(params_.PolyLen(), t_exp_left, 1); + auto g_inv_ct_left_ntt = PolyMatrixNtt::Zero( + params_.CrtCount(), params_.PolyLen(), t_exp_left, 1); + auto g_inv_ct_right = + PolyMatrixRaw::Zero(params_.PolyLen(), t_exp_right, 1); + auto g_inv_ct_right_ntt = PolyMatrixNtt::Zero( + params_.CrtCount(), params_.PolyLen(), t_exp_right, 1); + + const PolyMatrixNtt* w_p{}; + PolyMatrixRaw* gi_ct_p{}; + PolyMatrixNtt* gi_ct_ntt_p{}; + if ((i != 0) && (j % 2 == 0)) { + WEAK_ENFORCE(i < v_w_left.size()); + + w_p = &v_w_left[i]; + gi_ct_p = &g_inv_ct_left; + gi_ct_ntt_p = &g_inv_ct_left_ntt; + } else { + WEAK_ENFORCE(i < v_w_right.size()); + + w_p = &v_w_right[i]; + gi_ct_p = &g_inv_ct_right; + gi_ct_ntt_p = &g_inv_ct_right_ntt; + } + + auto& w = *w_p; + auto& gi_ct = *gi_ct_p; + auto& gi_ct_ntt = *gi_ct_ntt_p; + + FromNtt(params_, ct, fj); + Automorphism(params_, ct_auto, ct, t); + + util::GadgetInvertRdim(params_, gi_ct, ct_auto, 1); + ToNttNoReduce(params_, gi_ct_ntt, gi_ct); + // copy ct_auto to ct_auto1 + std::memcpy(ct_auto1.Data().data(), + ct_auto.Data().data() + ct_auto.PolyStartIndex(1, 0), + ct_auto1.NumWords() * sizeof(uint64_t)); + + ToNtt(params_, ct_auto1_ntt, ct_auto1); + Multiply(params_, w_times_g_inv_ct, w, gi_ct_ntt); + + size_t idx = 0; + for (size_t row_idx = 0; row_idx < 2; ++row_idx) { + for (size_t n = 0; n < params_.CrtCount(); ++n) { + for (size_t z = 0; z < poly_len; ++z) { + uint64_t sum = fj.Data()[idx] + w_times_g_inv_ct.Data()[idx] + + static_cast<uint64_t>(row_idx) * + ct_auto1_ntt.Data()[n * poly_len + z]; + + fj.Data()[idx] = arith::BarrettCoeffU64(params_, sum, n); + + idx += 1; + } + } + } + }; // lambda action_expand end + + // a big improve for performance + yacl::parallel_for(0, num_in, [&](size_t begin, size_t end) { + for (size_t j = begin; j < end; ++j) { + ScalarMultiply(params_, v[j + num_in], neg1, v[j]); + action_expand(j, v[j]); + action_expand(j, v[j + num_in]); + } + }); + } +} + +void SpiralServer::FoldCiphertexts( + std::vector<PolyMatrixRaw>& v_cts, + const std::vector<PolyMatrixNtt>& v_folding, + const std::vector<PolyMatrixNtt>& v_folding_neg) const { + if (v_cts.size() == 1) { + return; + } + size_t further_dims = arith::Log2(v_cts.size()); + size_t ell = v_folding[0].Cols() >> 1; + + size_t num_per = v_cts.size(); + for (size_t cur_dim = 0; cur_dim < further_dims; ++cur_dim) { + num_per = num_per / 2; + + // a big improve for performance + yacl::parallel_for(0, num_per, [&](size_t begin, size_t end) { + for (size_t i = begin; i < end; ++i) { + auto g_inv_c = PolyMatrixRaw::Zero(params_.PolyLen(), 2 * ell, 1); + auto g_inv_c_ntt = PolyMatrixNtt::Zero(params_.CrtCount(), + params_.PolyLen(), 2 * ell, 1); + auto prod = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 2, 1); + auto sum = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 2, 1); + + util::GadgetInvert(params_, g_inv_c, v_cts[i]); + ToNtt(params_, g_inv_c_ntt, g_inv_c); + Multiply(params_, prod, v_folding_neg[further_dims - 1 - cur_dim], + g_inv_c_ntt); + + util::GadgetInvert(params_, g_inv_c, v_cts[num_per + i]); + ToNtt(params_, g_inv_c_ntt, g_inv_c); + Multiply(params_, sum, v_folding[further_dims - 1 - cur_dim], + g_inv_c_ntt); + AddInto(params_, sum, prod); + FromNtt(params_, v_cts[i], sum); + } + }); + } +} + +std::vector<PolyMatrixNtt> SpiralServer::GetVFoldingNeg( + std::vector<PolyMatrixNtt>& v_folding) const { + auto gadget = util::BuildGadget(params_, 2, 2 * params_.TGsw()); + auto gadget_ntt = ToNtt(params_, gadget); + + std::vector<PolyMatrixNtt> v_folding_neg; + v_folding_neg.reserve(params_.DbDim2()); + + for (size_t i = 0; i < params_.DbDim2(); ++i) { + // -C + auto ct_gsw_inv = + PolyMatrixRaw::Zero(params_.PolyLen(), 2, 2 * params_.TGsw()); + Invert(params_, ct_gsw_inv, FromNtt(params_, v_folding[i])); + // G_{n+1, z} - C + auto ct_gsw_neg = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), + 2, 2 * params_.TGsw()); + Add(params_, ct_gsw_neg, gadget_ntt, ToNtt(params_, ct_gsw_inv)); + v_folding_neg.push_back(std::move(ct_gsw_neg)); + } + return v_folding_neg; +} + +PolyMatrixNtt SpiralServer::Pack(const std::vector<PolyMatrixRaw>& v_ct, + const std::vector<PolyMatrixNtt>& v_w) const { + WEAK_ENFORCE(v_ct.size() >= params_.N() * params_.N()); + WEAK_ENFORCE(v_w.size() == params_.N()); + WEAK_ENFORCE(v_ct[0].Rows() == static_cast<size_t>(2)); + WEAK_ENFORCE(v_ct[0].Cols() == static_cast<size_t>(1)); + WEAK_ENFORCE(v_w[0].Rows() == static_cast<size_t>(params_.N() + 1)); + WEAK_ENFORCE(v_w[0].Cols() == static_cast<size_t>(params_.TConv())); + + auto result = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), + params_.N() + 1, params_.N()); + auto g_inv = PolyMatrixRaw::Zero(params_.PolyLen(), params_.TConv(), 1); + auto g_inv_ntt = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), + params_.TConv(), 1); + + auto prod = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), + params_.N() + 1, 1); + + auto ct1 = PolyMatrixRaw::Zero(params_.PolyLen(), 1, 1); + auto ct2 = PolyMatrixRaw::Zero(params_.PolyLen(), 1, 1); + auto ct2_ntt = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 1, 1); + + for (size_t j = 0; j < params_.N(); ++j) { + // each one row + auto v_int = PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), + params_.N() + 1, 1); + + for (size_t i = 0; i < params_.N(); ++i) { + const auto& w = v_w[i]; + const auto& ct = v_ct[i * params_.N() + j]; + // copy to ct1 + std::memcpy(ct1.Data().data(), ct.Data().data(), + sizeof(uint64_t) * ct.NumWords()); + // copy to ct2 + std::memcpy(ct2.Data().data(), ct.Data().data() + ct.PolyStartIndex(1, 0), + sizeof(uint64_t) * ct.NumWords()); + // ntt + ToNtt(params_, ct2_ntt, ct2); + util::GadgetInvert(params_, g_inv, ct1); + ToNtt(params_, g_inv_ntt, g_inv); + Multiply(params_, prod, w, g_inv_ntt); + AddIntoAt(params_, v_int, ct2_ntt, i + 1, 0); + AddInto(params_, v_int, prod); + } + result.CopyInto(v_int, 0, j); + } + + return result; +} + +std::vector<PolyMatrixRaw> SpiralServer::ProcessQuery( + const SpiralQuery& query) const { + YACL_ENFORCE(database_seted_, + "Before ProcessQuery, database must be processed"); + + size_t dim0 = 1 << params_.DbDim1(); + size_t num_per = 1 << params_.DbDim2(); + size_t db_slice_sz = dim0 * num_per * params_.PolyLen(); + + const auto& v_packing = pks_.v_packing_; + + std::vector<uint64_t> v_reg_reoriented; + std::vector<PolyMatrixNtt> v_folding; + + SPDLOG_INFO("Server begin to Expand Query"); + yacl::ElapsedTimer timer; + + // We default to using QueryExpand technology + std::tie(v_reg_reoriented, v_folding) = ExpandQuery(query); + + SPDLOG_INFO("Server end to Expand Query, time cost: {} ms", timer.CountMs()); + timer.Restart(); + + auto v_folding_neg = GetVFoldingNeg(v_folding); + size_t n_power = params_.N() * params_.N(); + std::vector<PolyMatrixRaw> v_packed_ct; + v_packed_ct.reserve(partition_num_); + + // init only once + std::vector<PolyMatrixNtt> intermediate; + std::vector<PolyMatrixRaw> intermediate_raw; + for (size_t i = 0; i < num_per; ++i) { + intermediate.emplace_back(params_.CrtCount(), params_.PolyLen(), 2, 1); + intermediate_raw.emplace_back(params_.PolyLen(), 2, 1); + } + + // when use yacl::parallel_for, there is no improve + for (size_t partiton_idx = 0; partiton_idx < partition_num_; ++partiton_idx) { + std::vector<PolyMatrixRaw> v_ct; + for (size_t trial = 0; trial < n_power; ++trial) { + // the instances is 1, so the ins = 0 + // so we can remove the ins + size_t idx = trial * db_slice_sz; + MultiplyRegByDatabase(intermediate, v_reg_reoriented, dim0, num_per, idx, + partiton_idx); + // ntt to raw + for (size_t i = 0; i < intermediate.size(); ++i) { + FromNtt(params_, intermediate_raw[i], intermediate[i]); + } + // fold + FoldCiphertexts(intermediate_raw, v_folding, v_folding_neg); + // need deep-copy + v_ct.emplace_back(intermediate_raw[0]); + } + auto packed_ct = Pack(v_ct, v_packing); + v_packed_ct.push_back(FromNtt(params_, packed_ct)); + } + + // modulus switching + uint64_t q1 = 4 * params_.PtModulus(); + uint64_t q2 = kQ2Values[params_.Q2Bits()]; + for (auto& ct : v_packed_ct) { + ct.Rescale(0, 1, params_.Modulus(), q2); + ct.Rescale(1, ct.Rows(), params_.Modulus(), q1); + } + + SPDLOG_INFO( + "Server end to do dot-product between query and database, time cost: {} " + "ms", + timer.CountMs()); + + return v_packed_ct; +} + +void SpiralServer::RegevToGsw(std::vector<PolyMatrixNtt>& v_gsw, + const std::vector<PolyMatrixNtt>& v_inp, + const PolyMatrixNtt& v, size_t idx_factor, + size_t idx_offset) const { + WEAK_ENFORCE(v.Rows() == static_cast<size_t>(2)); + WEAK_ENFORCE(v.Cols() == static_cast<size_t>(2 * params_.TConv())); + + // a big improve for performance + yacl::parallel_for(0, v_gsw.size(), [&](size_t begin, size_t end) { + for (size_t i = begin; i < end; ++i) { + auto& ct = v_gsw[i]; + + auto ginv_c_inp = + PolyMatrixRaw::Zero(params_.PolyLen(), 2 * params_.TConv(), 1); + auto ginv_c_inp_ntt = PolyMatrixNtt::Zero( + params_.CrtCount(), params_.PolyLen(), 2 * params_.TConv(), 1); + + auto tmp_ct_raw = PolyMatrixRaw::Zero(params_.PolyLen(), 2, 1); + auto tmp_ct_ntt = + PolyMatrixNtt::Zero(params_.CrtCount(), params_.PolyLen(), 2, 1); + + for (size_t j = 0; j < params_.TGsw(); ++j) { + size_t idx_ct = i * params_.TGsw() + j; + size_t idx_inp = idx_factor * idx_ct + idx_offset; + + ct.CopyInto(v_inp[idx_inp], 0, 2 * j + 1); + FromNtt(params_, tmp_ct_raw, v_inp[idx_inp]); + util::GadgetInvert(params_, ginv_c_inp, tmp_ct_raw); + + ToNtt(params_, ginv_c_inp_ntt, ginv_c_inp); + Multiply(params_, tmp_ct_ntt, v, ginv_c_inp_ntt); + ct.CopyInto(tmp_ct_ntt, 0, 2 * j); + } + } + }); +} + +std::pair<std::vector<uint64_t>, std::vector<PolyMatrixNtt>> +SpiralServer::ExpandQuery(const SpiralQuery& query) const { + size_t dim0 = 1 << params_.DbDim1(); + size_t further_dims = params_.DbDim2(); + size_t num_bits_to_gen = params_.TGsw() * further_dims + dim0; + size_t g = arith::Log2Ceil(num_bits_to_gen); + + size_t right_expanded = params_.TGsw() * further_dims; + size_t stop_round = arith::Log2Ceil(right_expanded); + + std::vector<PolyMatrixNtt> v; + v.reserve(static_cast<size_t>(1) << g); + for (size_t i = 0; i < static_cast<size_t>(1) << g; ++i) { + v.emplace_back(params_.CrtCount(), params_.PolyLen(), 2, 1); + } + + auto query_ct_ntt = ToNtt(params_, query.ct_); + v[0].CopyInto(query_ct_ntt, 0, 0); + + const PolyMatrixNtt& v_conversion = pks_.v_conversion_[0]; + const std::vector<PolyMatrixNtt>& v_w_left = pks_.v_expansion_left_; + const std::vector<PolyMatrixNtt>& v_w_right = pks_.v_expansion_right_; + + auto v_neg1 = GetVneg1(params_); + + std::vector<PolyMatrixNtt> v_reg_inp; + v_reg_inp.reserve(dim0); + std::vector<PolyMatrixNtt> v_gsw_inp; + v_gsw_inp.reserve(right_expanded); + + yacl::ElapsedTimer timer; + + if (further_dims > 0) { + CoefficientExpansion(v, g, stop_round, v_w_left, v_w_right, v_neg1, + params_.TGsw() * params_.DbDim2()); + + for (size_t i = 0; i < dim0; ++i) { + // deep copy + v_reg_inp.push_back(std::move(v[2 * i])); + } + for (size_t i = 0; i < right_expanded; ++i) { + v_gsw_inp.push_back(std::move(v[2 * i + 1])); + } + } else { + CoefficientExpansion(v, g, 0, v_w_left, v_w_right, v_neg1, 0); + for (size_t i = 0; i < dim0; ++i) { + v_reg_inp.emplace_back(v[i]); + } + } + + SPDLOG_INFO("Server finished CoefficientExpansion, time: {} ms", + timer.CountMs()); + timer.Restart(); + + size_t v_reg_sz = dim0 * 2 * params_.PolyLen(); + std::vector<uint64_t> v_reg_reoriented(v_reg_sz); + ReorientRegCiphertexts(params_, v_reg_reoriented, v_reg_inp); + + SPDLOG_INFO("Server finished ReorientRegCiphertexts, time: {} ms", + timer.CountMs()); + timer.Restart(); + + std::vector<PolyMatrixNtt> v_folding; + for (size_t i = 0; i < params_.DbDim2(); ++i) { + v_folding.emplace_back(params_.CrtCount(), params_.PolyLen(), 2, + 2 * params_.TGsw()); + } + RegevToGsw(v_folding, v_gsw_inp, v_conversion, 1, 0); + SPDLOG_INFO("Server finished RegevToGsw, time: {} ms", timer.CountMs()); + + return std::make_pair(v_reg_reoriented, v_folding); +} + +void SpiralServer::MultiplyRegByDatabase(std::vector<PolyMatrixNtt>& out, + std::vector<uint64_t>& v_first_dim, + size_t dim0, size_t num_per, + size_t cur_db_idx, + size_t partiiton_idx) const { + size_t ct_rows = 2; + size_t ct_cols = 1; + size_t pt_rows = 1; + size_t pt_cols = 1; + + yacl::parallel_for(0, params_.PolyLen(), [&](size_t begin, size_t end) { + for (size_t z = begin; z < end; ++z) { + size_t idx_a_base = z * (ct_cols * dim0 * ct_rows); + size_t idx_b_base = z * (num_per * pt_cols * dim0 * pt_rows); + + for (size_t i = 0; i < num_per; ++i) { + for (size_t c = 0; c < pt_cols; ++c) { + uint128_t sums_out_n0_0 = 0; + uint128_t sums_out_n0_1 = 0; + uint128_t sums_out_n1_0 = 0; + uint128_t sums_out_n1_1 = 0; + + for (size_t jm = 0; jm < dim0 * pt_rows; ++jm) { + uint64_t b = reoriented_dbs_[partiiton_idx * single_db_size_ + + cur_db_idx + idx_b_base]; + idx_b_base += 1; + + uint64_t v_a0 = v_first_dim[idx_a_base + jm * ct_rows]; + uint64_t v_a1 = v_first_dim[idx_a_base + jm * ct_rows + 1]; + + uint64_t b_lo = b & 0x00000000FFFFFFFFULL; + uint64_t b_hi = b >> 32; + + uint64_t v_a0_lo = v_a0 & 0x00000000FFFFFFFFULL; + uint64_t v_a0_hi = v_a0 >> 32; + + uint64_t v_a1_lo = v_a1 & 0x00000000FFFFFFFFULL; + uint64_t v_a1_hi = v_a1 >> 32; + // d0 n0 + sums_out_n0_0 += (static_cast<uint128_t>(v_a0_lo * b_lo)); + sums_out_n0_1 += (static_cast<uint128_t>(v_a1_lo * b_lo)); + // do n1 + sums_out_n1_0 += (static_cast<uint128_t>(v_a0_hi * b_hi)); + sums_out_n1_1 += (static_cast<uint128_t>(v_a1_hi * b_hi)); + } + // output n0 + size_t crt_count = params_.CrtCount(); + size_t poly_len = params_.PolyLen(); + + size_t n = 0; + size_t idx_c = c * (crt_count * poly_len) + n * poly_len + z; + out[i].Data()[idx_c] = arith::BarrettReductionU128Raw( + sums_out_n0_0, params_.BarrettCr0(0), params_.BarrettCr1(0), + params_.Moduli(0)); + // update idx + idx_c += (pt_cols * crt_count * poly_len); + out[i].Data()[idx_c] = arith::BarrettReductionU128Raw( + sums_out_n0_1, params_.BarrettCr0(0), params_.BarrettCr1(0), + params_.Moduli(0)); + // output n1 + n = 1; + // reset idx + idx_c = c * (crt_count * poly_len) + n * poly_len + z; + out[i].Data()[idx_c] = arith::BarrettReductionU128Raw( + sums_out_n1_0, params_.BarrettCr0(1), params_.BarrettCr1(1), + params_.Moduli(1)); + idx_c += (pt_cols * crt_count * poly_len); + out[i].Data()[idx_c] = arith::BarrettReductionU128Raw( + sums_out_n1_1, params_.BarrettCr0(1), params_.BarrettCr1(1), + params_.Moduli(1)); + } + } + } + }); +} + +// util methods +std::vector<PolyMatrixNtt> GetVneg1(const Params& params) { + std::vector<PolyMatrixNtt> v_neg1; + v_neg1.reserve(params.PolyLenLog2()); + for (size_t j = 0; j < params.PolyLenLog2(); ++j) { + auto idx = params.PolyLen() - (static_cast<size_t>(1) << j); + auto ng1 = PolyMatrixRaw::Zero(params.PolyLen(), 1, 1); + ng1.Data()[idx] = 1ULL; + v_neg1.push_back(ToNtt(params, Invert(params, ng1))); + } + return v_neg1; +} + +std::pair<PolyMatrixRaw, std::vector<uint64_t>> GenRandomDbAndGetItem( + const Params& params, size_t item_idx) { + yacl::crypto::Prg<uint64_t> rng(yacl::crypto::SecureRandU128()); + size_t instances = params.Instances(); + size_t trials = params.N() * params.N(); + size_t dim0 = 1 << params.DbDim1(); + size_t num_per = 1 << params.DbDim2(); + size_t num_items = dim0 * num_per; + + size_t db_size_words = instances * trials * num_items * params.PolyLen(); + // a large matrix, the right item + auto item = + PolyMatrixRaw::Zero(params.PolyLen(), instances * params.N(), params.N()); + std::vector<uint64_t> v(db_size_words); + + for (size_t ins = 0; ins < instances; ++ins) { + for (size_t trial = 0; trial < trials; ++trial) { + for (size_t i = 0; i < num_items; ++i) { + size_t ii = i % num_per; + size_t j = i / num_per; + // a random item + auto db_item = PolyMatrixRaw::RandomPrg(params, 1, 1, rng); + db_item.ReduceMod(params.PtModulus()); + if (i == item_idx) { + item.CopyInto(db_item, ins * params.N() + trial / params.N(), + trial % params.N()); + } + + for (size_t z = 0; z < params.PolyLen(); ++z) { + db_item.Data()[z] = arith::RecenertMod( + db_item.Data()[z], params.PtModulus(), params.Modulus()); + } + // auto db_item_ntt = db_item.Ntt(); + auto db_item_ntt = ToNtt(params, db_item); + for (size_t z = 0; z < params.PolyLen(); ++z) { + size_t idx_dst = util::CalcIndex( + {ins, trial, z, ii, j}, + {instances, trials, params.PolyLen(), num_per, dim0}); + v[idx_dst] = + db_item_ntt.Data()[z] | + (db_item_ntt.Data()[params.PolyLen() + z] << kPackedOffset2); + } + } + } + } + + return std::make_pair(item, v); +} + +std::vector<uint64_t> ReorientDatabase( + const Params& params, std::vector<std::vector<uint64_t>>& database) { + size_t instances = params.Instances(); + YACL_ENFORCE_EQ(instances, static_cast<size_t>(1)); + + size_t trials = params.N() * params.N(); + size_t dim0 = 1 << params.DbDim1(); + size_t num_per = 1 << params.DbDim2(); + size_t num_items = dim0 * num_per; + + size_t db_size_words = instances * trials * num_items * params.PolyLen(); + + std::vector<uint64_t> v(db_size_words); + + for (size_t ins = 0; ins < instances; ++ins) { + yacl::parallel_for(0, trials, [&](size_t begin, size_t end) { + for (size_t trial = begin; trial < end; ++trial) { + for (size_t i = 0; i < num_items; ++i) { + size_t ii = i % num_per; + size_t j = i / num_per; + + auto db_item = PolyMatrixRaw::Zero(params.PolyLen(), 1, 1); + size_t start_idx = trial * params.PolyLen(); + std::memcpy(db_item.Data().data(), database[i].data() + start_idx, + params.PolyLen() * sizeof(uint64_t)); + + for (size_t z = 0; z < params.PolyLen(); ++z) { + db_item.Data()[z] = arith::RecenertMod( + db_item.Data()[z], params.PtModulus(), params.Modulus()); + } + // auto db_item_ntt = db_item.Ntt(); + auto db_item_ntt = ToNtt(params, db_item); + for (size_t z = 0; z < params.PolyLen(); ++z) { + size_t idx_dst = util::CalcIndex( + {ins, trial, z, ii, j}, + {instances, trials, params.PolyLen(), num_per, dim0}); + v[idx_dst] = + db_item_ntt.Data()[z] | + (db_item_ntt.Data()[params.PolyLen() + z] << kPackedOffset2); + } + } + } + }); + } + return v; +} + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/spiral_server.h b/psi/algorithm/spiral/spiral_server.h new file mode 100644 index 00000000..09a9ce17 --- /dev/null +++ b/psi/algorithm/spiral/spiral_server.h @@ -0,0 +1,147 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <cstddef> +#include <utility> +#include <vector> + +#include "psi/algorithm/pir_interface/index_pir.h" +#include "psi/algorithm/pir_interface/pir_db.h" +#include "psi/algorithm/spiral/params.h" +#include "psi/algorithm/spiral/poly_matrix.h" +#include "psi/algorithm/spiral/poly_matrix_utils.h" +#include "psi/algorithm/spiral/public_keys.h" +#include "psi/algorithm/spiral/serialize.h" +#include "psi/algorithm/spiral/spiral_client.h" + +namespace psi::spiral { + +class SpiralServer : psi::pir::IndexPirServer { + public: + SpiralServer() = default; + + explicit SpiralServer(Params params, std::vector<uint64_t> reoriented_db) + : params_(std::move(params)), + single_db_size_(reoriented_db.size()), + reoriented_dbs_(std::move(reoriented_db)) { + database_seted_ = true; + } + + explicit SpiralServer(Params params, std::vector<uint64_t> reoriented_db, + DatabaseMetaInfo database_info) + : params_(std::move(params)), + single_db_size_(reoriented_db.size()), + reoriented_dbs_(std::move(reoriented_db)), + database_info_(database_info) { + database_seted_ = true; + } + + explicit SpiralServer(Params params, DatabaseMetaInfo database_info) + : params_(std::move(params)), database_info_(database_info) {} + + // convert raw database to the specific format required by SpiralPIR + // now we support value of any length + void SetDatabase(const pir_utils::RawDatabase& raw_database) override; + + void SetDatabase(std::vector<std::vector<uint8_t>> raw_database) { + pir_utils::RawDatabase raw_db(std::move(raw_database)); + SetDatabase(raw_db); + } + + void SetPublicKeys(PublicKeys pks) { pks_ = std::move(pks); } + + void SetPublicKeys(yacl::Buffer& pks_buffer) { + pks_ = DeserializePublicKeys(params_, pks_buffer); + } + + std::vector<PolyMatrixRaw> ProcessQuery(const SpiralQuery& query) const; + + const Params& GetParams() const { return params_; } + + virtual yacl::Buffer GenerateIndexResponse( + const yacl::Buffer& query_buffer) const override { + auto query = SpiralQuery::DeserializeRng(params_, query_buffer); + + auto response = ProcessQuery(query); + + return SerializeResponse(response); + } + + protected: + std::vector<uint64_t> ReorientRawDb( + const std::vector<std::vector<uint8_t>>& raw_database); + + PolyMatrixNtt Pack(const std::vector<PolyMatrixRaw>& v_ct, + const std::vector<PolyMatrixNtt>& v_w) const; + + void CoefficientExpansion(std::vector<PolyMatrixNtt>& v, size_t g, + size_t stop_round, + const std::vector<PolyMatrixNtt>& v_w_left, + const std::vector<PolyMatrixNtt>& v_w_right, + const std::vector<PolyMatrixNtt>& v_neg1, + size_t max_btis_to_gen_right) const; + + std::pair<std::vector<uint64_t>, std::vector<PolyMatrixNtt>> ExpandQuery( + const SpiralQuery& query) const; + + void RegevToGsw(std::vector<PolyMatrixNtt>& v_gsw, + const std::vector<PolyMatrixNtt>& v_inp, + const PolyMatrixNtt& v, size_t idx_factor, + size_t idx_offset) const; + + void FoldCiphertexts(std::vector<PolyMatrixRaw>& v_cts, + const std::vector<PolyMatrixNtt>& v_folding, + const std::vector<PolyMatrixNtt>& v_folding_neg) const; + + void MultiplyRegByDatabase(std::vector<PolyMatrixNtt>& out, + std::vector<uint64_t>& v_first_dim, size_t dim0, + size_t num_per, size_t cur_db_idx = 0, + size_t partition_idx = 0) const; + + std::vector<PolyMatrixNtt> GetVFoldingNeg( + std::vector<PolyMatrixNtt>& v_folding) const; + + private: + Params params_; + + PublicKeys pks_; + + // single reoriented_db's length + size_t single_db_size_ = 0; + + // contains partition_num_ reoriented_db + std::vector<uint64_t> reoriented_dbs_; + + size_t partition_num_ = 1; + + DatabaseMetaInfo database_info_; + + bool database_seted_ = false; +}; + +// util method +std::vector<PolyMatrixNtt> GetVneg1(const Params& params); + +// just for test +std::pair<PolyMatrixRaw, std::vector<uint64_t>> GenRandomDbAndGetItem( + const Params& params, size_t item_idx); + +// database is a 2^{v1 + v2} rows matrix, each row is R_p^{n * n} +// reorient the database format for Spiral requireed +std::vector<uint64_t> ReorientDatabase( + const Params& params, std::vector<std::vector<uint64_t>>& database); + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/spiral_server_test.cc b/psi/algorithm/spiral/spiral_server_test.cc new file mode 100644 index 00000000..1bc9c60d --- /dev/null +++ b/psi/algorithm/spiral/spiral_server_test.cc @@ -0,0 +1,406 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "psi/algorithm/spiral/spiral_server.h" + +#include <chrono> +#include <limits> +#include <optional> + +#include "absl/types/span.h" +#include "gtest/gtest.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/crypto/tools/prg.h" + +#include "psi/algorithm/spiral/gadget.h" +#include "psi/algorithm/spiral/poly_matrix_utils.h" +#include "psi/algorithm/spiral/public_keys.h" +#include "psi/algorithm/spiral/spiral_client.h" +#include "psi/algorithm/spiral/util.h" + +namespace psi::spiral { + +namespace { +class SpiralServerDerive : public SpiralServer { + public: + using SpiralServer::CoefficientExpansion; + using SpiralServer::ExpandQuery; + using SpiralServer::FoldCiphertexts; + using SpiralServer::GetVFoldingNeg; + using SpiralServer::MultiplyRegByDatabase; + using SpiralServer::RegevToGsw; + + explicit SpiralServerDerive(Params params, + std::vector<uint64_t> reoriented_db) + : psi::spiral::SpiralServer(std::move(params), std::move(reoriented_db)) { + } + + explicit SpiralServerDerive(Params params, + std::vector<uint64_t> reoriented_db, + DatabaseMetaInfo database_info) + : SpiralServer(std::move(params), std::move(reoriented_db), + std::move(database_info)) {} + + explicit SpiralServerDerive(Params params, DatabaseMetaInfo database_info) + : SpiralServer(std::move(params), std::move(database_info)) {} +}; + +class SpiralClientDerive : public SpiralClient { + public: + using SpiralClient::GenQueryInternal; + + using SpiralClient::DecodeResponseInternal; + + using SpiralClient::DecryptMatrixRegev; + + using SpiralClient::DecryptMatrixGsw; + + using SpiralClient::EncryptMatrixGsw; + + using SpiralClient::EncryptMatrixRegev; + + explicit SpiralClientDerive(Params params, DatabaseMetaInfo database_info) + : SpiralClient(std::move(params), std::move(database_info)) {} + + explicit SpiralClientDerive(Params params) + : SpiralClient(std::move(params)) {} +}; + +[[maybe_unused]] constexpr size_t kMaxLoop{1}; + +[[maybe_unused]] uint64_t DecGsw(const Params& params, const PolyMatrixNtt& ct, + SpiralClientDerive& client) { + auto dec = FromNtt(params, client.DecryptMatrixRegev(ct)); + + size_t idx = 2 * (params.TGsw() - 1) * params.PolyLen() + params.PolyLen(); + int64_t val = static_cast<int64_t>(dec.Data()[idx]); + + if (val >= static_cast<int64_t>(params.Modulus() >> 1)) { + val -= static_cast<int64_t>(params.Modulus()); + } + if (std::abs(val) < static_cast<int64_t>(1 << 10)) { + return 0; + } else { + return 1; + } +} + +[[maybe_unused]] uint64_t DecRegev(const Params& params, + const PolyMatrixNtt& ct, + SpiralClientDerive& client, + uint64_t scale_k) { + auto dec = FromNtt(params, client.DecryptMatrixRegev(ct)); + + int64_t val = static_cast<int64_t>(dec.Data()[0]); + + if (val >= static_cast<int64_t>(params.Modulus() >> 1)) { + val -= static_cast<int64_t>(params.Modulus()); + } + auto val_rounded = static_cast<int64_t>( + std::round(static_cast<double>(val) / static_cast<double>(scale_k))); + SPDLOG_DEBUG("dec.data[0]: {}, val: {}, val_rounded: {}", dec.Data()[0], val, + val_rounded); + + if (val_rounded == 0) { + return 0; + + } else { + return 1; + } +} + +void FullProtocolIsCorrect(Params&& params, Params&& params_client, + Params&& params_server) { + yacl::crypto::Prg<uint64_t> prg; + size_t target_idx = prg() % (1 << (params.DbDim1() + params.DbDim2())); + + // new client + SpiralClientDerive client(std::move(params_client)); + auto pks = client.GenKeys(); + + // genquery + auto query = client.GenQueryInternal(target_idx); + // random database + auto [correct_item, db] = GenRandomDbAndGetItem(params, target_idx); + + // new server + SpiralServer server(std::move(params_server), db); + server.SetPublicKeys(std::move(pks)); + + // gen response + auto response = server.ProcessQuery(query); + + // decode + auto result = client.DecodeResponseInternal(response); + + // verify + EXPECT_EQ(correct_item.Data(), result.Data()); +} + +} // namespace + +TEST(FullProtocol, FastExpansionTestingParam) { + auto params = util::GetFastExpansionTestingParam(); + auto params1 = util::GetFastExpansionTestingParam(); + auto params2 = util::GetFastExpansionTestingParam(); + + SPDLOG_DEBUG("params: {}", params.ToString()); + + FullProtocolIsCorrect(std::move(params), std::move(params1), + std::move(params2)); +} + +TEST(SpiralServer, MultiplyRegByDatabase) { + auto params = util::GetFastExpansionTestingParam(); + auto params_client = util::GetFastExpansionTestingParam(); + auto params_server = util::GetFastExpansionTestingParam(); + + yacl::crypto::Prg<uint64_t> rng(yacl::crypto::SecureRandU128()); + yacl::crypto::Prg<uint64_t> rng_pub; + + size_t dim0 = 1 << params.DbDim1(); + size_t num_per = 1 << params.DbDim2(); + uint64_t scale_k = params.ScaleK(); + + size_t target_idx = rng() % (dim0 * num_per); + size_t target_idx_dim0 = target_idx / num_per; + size_t target_idx_num_per = target_idx % num_per; + // new client + SpiralClientDerive client(std::move(params_client)); + auto pp = client.GenKeys(); + // random db + auto [corr_item, db] = GenRandomDbAndGetItem(params, target_idx); + + // query ciphertext + std::vector<PolyMatrixNtt> v_reg; + for (size_t i = 0; i < dim0; ++i) { + uint64_t val = (i == target_idx_dim0) ? scale_k : 0ULL; + auto sigma = + ToNtt(params, PolyMatrixRaw::SingleValue(params.PolyLen(), val)); + v_reg.push_back(client.EncryptMatrixRegev(sigma, rng, rng_pub)); + } + + size_t v_reg_sz = dim0 * 2 * params.PolyLen(); + std::vector<uint64_t> v_reg_reoriented(v_reg_sz); + ReorientRegCiphertexts(params, v_reg_reoriented, v_reg); + + std::vector<PolyMatrixNtt> out; + out.reserve(num_per); + for (size_t i = 0; i < num_per; ++i) { + out.push_back( + PolyMatrixNtt::Zero(params.CrtCount(), params.PolyLen(), 2, 1)); + } + SpiralServerDerive server(std::move(params_server), std::move(db)); + server.SetPublicKeys(std::move(pp)); + // now mul + server.MultiplyRegByDatabase(out, v_reg_reoriented, dim0, num_per); + // decrypt + auto dec = + FromNtt(params, client.DecryptMatrixRegev(out[target_idx_num_per])); + + auto dec_rescaled = PolyMatrixRaw::Zero(params.PolyLen(), 1, 1); + for (size_t z = 0; z < params.PolyLen(); ++z) { + dec_rescaled.Data()[z] = + arith::Rescale(dec.Data()[z], params.Modulus(), params.PtModulus()); + } + // veryfiy + for (size_t z = 0; z < params.PolyLen(); ++z) { + ASSERT_EQ(dec_rescaled.Data()[z], corr_item.Data()[z]); + } +} + +TEST(SpiralServer, CoefficientExpansion) { + auto params = util::GetFastExpansionTestingParam(); + auto params_client = util::GetFastExpansionTestingParam(); + auto params_server = util::GetFastExpansionTestingParam(); + + auto v_neg1 = GetVneg1(params); + + yacl::crypto::Prg<uint64_t> rng; + yacl::crypto::Prg<uint64_t> rng_pub; + + SpiralClientDerive client(std::move(params_client)); + auto pp = client.GenKeys(); + + std::vector<PolyMatrixNtt> v(1 << (params.DbDim1() + 1)); + for (size_t i = 0; i < v.size(); ++i) { + v[i] = PolyMatrixNtt::Zero(params.CrtCount(), params.PolyLen(), 2, 1); + } + uint64_t scale_k = params.ScaleK(); + + // random idx + size_t idx_target = rng() % v.size(); + PolyMatrixRaw sigma = PolyMatrixRaw::Zero(params.PolyLen(), 1, 1); + sigma.Data()[idx_target] = scale_k; + auto sigma_ntt = ToNtt(params, sigma); + // one ciphertext + v[0] = client.EncryptMatrixRegev(sigma_ntt, rng, rng_pub); + + YACL_ENFORCE(pp.v_expansion_left_.size() > 0); + YACL_ENFORCE(pp.v_expansion_right_.size() > 0); + + auto v_w_left = pp.v_expansion_left_; + auto v_w_right = pp.v_expansion_right_; + + // init server + std::vector<uint64_t> db; + SpiralServerDerive server(std::move(params_server), std::move(db)); + server.SetPublicKeys(std::move(pp)); + // expand to mutli ciphertext + server.CoefficientExpansion(v, params.G(), params.StopRound(), v_w_left, + v_w_right, v_neg1, + params.TGsw() * params.DbDim2()); + + for (size_t i = 0; i < v.size(); ++i) { + if (i == idx_target) { + auto decrypt = DecRegev(params, v[i], client, scale_k); + ASSERT_EQ(1, decrypt); + } else { + auto decrypt = DecRegev(params, v[i], client, scale_k); + ASSERT_EQ(0, decrypt) << "i: " << i << ", decrypted v[i] error \n"; + } + } +} + +TEST(SpiralServer, RegevToGsw) { + auto params = util::GetFastExpansionTestingParam(); + auto params_client = util::GetFastExpansionTestingParam(); + auto params_server = util::GetFastExpansionTestingParam(); + + yacl::crypto::Prg<uint64_t> rng(yacl::crypto::SecureRandU128()); + yacl::crypto::Prg<uint64_t> rng_pub; + + // new client + SpiralClientDerive client(std::move(params_client)); + auto pp = client.GenKeys(); + + // function + auto enc_constant = [&](uint64_t val) { + auto sigma = PolyMatrixRaw::Zero(params.PolyLen(), 1, 1); + sigma.Data()[0] = val; + auto sigma_ntt = ToNtt(params, sigma); + return client.EncryptMatrixRegev(sigma_ntt, rng, rng_pub); + }; + + auto& v = pp.v_conversion_[0]; + auto bits_per = util::GetBitsPer(params, params.TGsw()); + + std::vector<PolyMatrixNtt> v_inp_1; + std::vector<PolyMatrixNtt> v_inp_0; + + for (size_t i = 0; i < params.TGsw(); ++i) { + uint64_t val = 1ULL << (bits_per * i); + v_inp_1.emplace_back(enc_constant(val)); + v_inp_0.emplace_back(enc_constant(0ULL)); + } + + std::vector<PolyMatrixNtt> v_gsw; + v_gsw.emplace_back(PolyMatrixNtt::Zero(params.CrtCount(), params.PolyLen(), 2, + 2 * params.TGsw())); + + // new Server + std::vector<uint64_t> db; + SpiralServerDerive server(std::move(params_server), std::move(db)); + server.SetPublicKeys(std::move(pp)); + // regev to gsw + server.RegevToGsw(v_gsw, v_inp_1, v, 1, 0); + EXPECT_EQ(1, DecGsw(params, v_gsw[0], client)); + + server.RegevToGsw(v_gsw, v_inp_0, v, 1, 0); + EXPECT_EQ(0, DecGsw(params, v_gsw[0], client)); +} + +TEST(SpiralServer, FoldCiphertexts) { + auto params = util::GetFastExpansionTestingParam(); + auto params_client = util::GetFastExpansionTestingParam(); + auto params_server = util::GetFastExpansionTestingParam(); + + yacl::crypto::Prg<uint64_t> rng(yacl::crypto::SecureRandU128()); + yacl::crypto::Prg<uint64_t> rng_pub; + + size_t dim0 = 1 << params.DbDim1(); + size_t num_per = 1 << params.DbDim2(); + uint64_t scale_k = params.ScaleK(); + + size_t targrt_idx = rng() % (dim0 * num_per); + size_t target_idx_num_per = targrt_idx % num_per; + // new client + SpiralClientDerive client(std::move(params_client)); + auto pp = client.GenKeys(); + auto query = client.GenQueryInternal(targrt_idx); + + std::vector<PolyMatrixNtt> v_reg; + for (size_t i = 0; i < num_per; ++i) { + uint64_t val = (i == target_idx_num_per) ? scale_k : 0ULL; + auto sigma = + ToNtt(params, PolyMatrixRaw::SingleValue(params.PolyLen(), val)); + v_reg.push_back(client.EncryptMatrixRegev(sigma, rng, rng_pub)); + } + + std::vector<PolyMatrixRaw> v_regev_raw; + for (auto& v_reg : v_reg) { + v_regev_raw.push_back(FromNtt(params, v_reg)); + } + size_t bits_per = util::GetBitsPer(params, params.TGsw()); + std::vector<PolyMatrixNtt> v_folding; + + auto sk_regev_ntt = ToNtt(params, client.GetSkRegev()); + for (size_t i = 0; i < params.DbDim2(); ++i) { + uint64_t bit = static_cast<uint64_t>(target_idx_num_per & (1ULL << i)) >> i; + + auto ct_gsw = PolyMatrixNtt::Zero(params.CrtCount(), params.PolyLen(), 2, + 2 * params.TGsw()); + + for (size_t j = 0; j < params.TGsw(); ++j) { + uint64_t value = (1ULL << (bits_per * j)) * bit; + + auto sigma = PolyMatrixRaw::SingleValue(params.PolyLen(), value); + auto sigma_ntt = ToNtt(params, sigma); + auto ct = client.EncryptMatrixRegev(sigma_ntt, rng, rng_pub); + ct_gsw.CopyInto(ct, 0, 2 * j + 1); + auto prod = Multiply(params, sk_regev_ntt, sigma_ntt); + auto ct1 = client.EncryptMatrixRegev(prod, rng, rng_pub); + ct_gsw.CopyInto(ct1, 0, 2 * j); + } + v_folding.push_back(ct_gsw); + } + + auto gadget_ntt = + ToNtt(params, util::BuildGadget(params, 2, 2 * params.TGsw())); + + std::vector<PolyMatrixNtt> v_folding_neg; + auto ct_gsw_inv = PolyMatrixRaw::Zero(params.PolyLen(), 2, 2 * params.TGsw()); + + for (size_t i = 0; i < params.DbDim2(); ++i) { + Invert(params, ct_gsw_inv, FromNtt(params, v_folding[i])); + + auto ct_gsw_neg = PolyMatrixNtt::Zero(params.CrtCount(), params.PolyLen(), + 2, 2 * params.TGsw()); + Add(params, ct_gsw_neg, gadget_ntt, ToNtt(params, ct_gsw_inv)); + + v_folding_neg.push_back(ct_gsw_neg); + } + + // new Server + std::vector<uint64_t> db; + SpiralServerDerive server(std::move(params_server), std::move(db)); + server.SetPublicKeys(std::move(pp)); + // now folding + server.FoldCiphertexts(v_regev_raw, v_folding, v_folding_neg); + + ASSERT_EQ(1, + DecRegev(params, ToNtt(params, v_regev_raw[0]), client, scale_k)); +} + +} // namespace psi::spiral \ No newline at end of file diff --git a/psi/algorithm/spiral/util.cc b/psi/algorithm/spiral/util.cc index fea34ee2..49c590ab 100644 --- a/psi/algorithm/spiral/util.cc +++ b/psi/algorithm/spiral/util.cc @@ -25,11 +25,10 @@ Params GetLargerParam() { double noise_width{6.4}; PolyMatrixParams poly_matrix_params(2, 256, 22, 3, 5, 5, 7); - QueryParams query_params(9, 6, 4, 32768); - std::size_t version{0}; + QueryParams query_params(9, 6, 4); + return Params(poly_len, std::move(moduli), noise_width, - std::move(poly_matrix_params), std::move(query_params), - version); + std::move(poly_matrix_params), std::move(query_params)); } Params GetTestParam() { @@ -38,11 +37,10 @@ Params GetTestParam() { double noise_width{6.4}; PolyMatrixParams poly_matrix_params(2, 256, 20, 4, 8, 56, 8); - QueryParams query_params(9, 6, 1, 2048); - std::size_t version{0}; + QueryParams query_params(9, 6, 1); + return Params(poly_len, std::move(moduli), noise_width, - std::move(poly_matrix_params), std::move(query_params), - version); + std::move(poly_matrix_params), std::move(query_params)); } Params GetPerformanceImproveParam() { @@ -51,28 +49,37 @@ Params GetPerformanceImproveParam() { double noise_width{6.4}; - PolyMatrixParams poly_matrix_params(2, 256, 21, 4, 8, 8, 8); - QueryParams query_params(9, 6, 1, 2048); - std::size_t version{0}; + PolyMatrixParams poly_matrix_params(2, 256, 21, 4, 8, 8, 4); + QueryParams query_params(9, 6, 1); + return Params(poly_len, std::move(moduli), noise_width, - std::move(poly_matrix_params), std::move(query_params), - version); + std::move(poly_matrix_params), std::move(query_params)); } -Params GetFastExpansionTestingParam() { +Params GetDefaultParam() { std::size_t poly_len{2048}; std::vector<std::uint64_t> moduli{268369921, 249561089}; + double noise_width{6.4}; - PolyMatrixParams poly_matrix_params(2, 256, 20, 4, 8, 8, 8); + PolyMatrixParams poly_matrix_params(2, 256, 21, 4, 8, 8, 6); + QueryParams query_params(9, 6, 1); + + return Params(poly_len, std::move(moduli), noise_width, + std::move(poly_matrix_params), std::move(query_params)); +} + +Params GetFastExpansionTestingParam() { + std::size_t poly_len{2048}; + std::vector<std::uint64_t> moduli{268369921, 249561089}; + double noise_width{6.4}; - QueryParams query_params(6, 2, 1, 8192); + PolyMatrixParams poly_matrix_params(2, 256, 20, 4, 8, 8, 6); - std::size_t version{0}; + QueryParams query_params(6, 2, 1); return Params(poly_len, std::move(moduli), noise_width, - std::move(poly_matrix_params), std::move(query_params), - version); + std::move(poly_matrix_params), std::move(query_params)); } std::size_t CalcIndex(const std::vector<std::size_t>& indices, diff --git a/psi/algorithm/spiral/util.h b/psi/algorithm/spiral/util.h index 2213cd00..34583dc4 100644 --- a/psi/algorithm/spiral/util.h +++ b/psi/algorithm/spiral/util.h @@ -25,8 +25,11 @@ Params GetFastExpansionTestingParam(); Params GetTestParam(); +// this params has the best performance, but has smallest noise budget Params GetPerformanceImproveParam(); +Params GetDefaultParam(); + Params GetLargerParam(); // calc multi-dimension position in 1-deimension's position diff --git a/psi/apps/pir/apis/BUILD.bazel b/psi/apps/pir/apis/BUILD.bazel new file mode 100644 index 00000000..2c957cdc --- /dev/null +++ b/psi/apps/pir/apis/BUILD.bazel @@ -0,0 +1,53 @@ +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@rules_proto//proto:defs.bzl", "proto_library") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "common_proto", + srcs = ["common.proto"], +) + +cc_proto_library( + name = "common_cc_proto", + deps = [":common_proto"], +) + +proto_library( + name = "client_service_proto", + srcs = ["client_service.proto"], + deps = [ + ":common_proto", + ], +) + +cc_proto_library( + name = "client_service_cc_proto", + deps = [":client_service_proto"], +) + +proto_library( + name = "server_service_proto", + srcs = ["server_service.proto"], + deps = [ + ":common_proto", + ], +) + +cc_proto_library( + name = "server_service_cc_proto", + deps = [":server_service_proto"], +) diff --git a/psi/apps/pir/apis/client_service.proto b/psi/apps/pir/apis/client_service.proto new file mode 100644 index 00000000..76b2cff7 --- /dev/null +++ b/psi/apps/pir/apis/client_service.proto @@ -0,0 +1,65 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +import "psi/apps/pir/apis/common.proto"; + +package pir; + +option cc_generic_services = true; + +message Table { + repeated Column columns = 1; +} + +message Column { + string name = 1; + DataType type = 2; + Array data = 3; +} + +message Array { + repeated bool bs = 1; + repeated int32 i32s = 2; + repeated int64 i64s = 3; + repeated double doubles = 4; + repeated string ss = 5; +} + +// User -> Pir client, used when client is in service mode. +service PirClientService { + rpc Query(QueryRequest) returns (QueryResponse); +} + +message QueryRequest { + Header header = 1; + RequestInfo info = 2; + + reserved 3 to 9; + + Table table = 10; +} + +message QueryResponse { + Header header = 1; + Status status = 2; + + reserved 3 to 9; + + repeated uint64 query_indexes = 10; + repeated bool is_matched = 11; + Table table = 12; +} \ No newline at end of file diff --git a/psi/apps/pir/apis/common.proto b/psi/apps/pir/apis/common.proto new file mode 100644 index 00000000..90bb73cb --- /dev/null +++ b/psi/apps/pir/apis/common.proto @@ -0,0 +1,67 @@ +// +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +syntax = "proto3"; + +package pir; + +option cc_generic_services = true; + +enum ErrorCode { + // Placeholder for proto3 default value, do not use it + UNKNOWN = 0; + + // 001-099 for general code + + OK = 1; + UNEXPECTED_ERROR = 2; + INVALID_ARGUMENT = 3; + NETWORK_ERROR = 4; + // Some requested entity (e.g., file or directory) was not found. + NOT_FOUND = 5; + NOT_IMPLEMENTED = 6; + LOGIC_ERROR = 7; + SERIALIZE_FAILED = 8; + DESERIALIZE_FAILED = 9; + IO_ERROR = 10; + NOT_READY = 11; +} + +message Header { + map<string, string> data = 1; +} + +message Status { + ErrorCode err_code = 1; + string msg = 2; +} + +message RequestInfo { + string client_id = 1; + string server_id = 2; +} + +enum DataType { + SCALAR_TYPE_UNKNOWN = 0; + SCALAR_TYPE_INT32 = 1; + SCALAR_TYPE_INT64 = 2; + SCALAR_TYPE_DOUBLE = 3; + SCALAR_TYPE_STRING = 4; + SCALAR_TYPE_BOOL = 5; +} \ No newline at end of file diff --git a/psi/apps/pir/apis/server_service.proto b/psi/apps/pir/apis/server_service.proto new file mode 100644 index 00000000..44ed285b --- /dev/null +++ b/psi/apps/pir/apis/server_service.proto @@ -0,0 +1,46 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +import "psi/apps/pir/apis/common.proto"; + +package pir; + +option cc_generic_services = true; + +// Pir client -> [Pir server] +service PirServerService { + rpc Query(QueryRequest) returns (QueryResponse); +} + +message QueryRequest { + Header header = 1; + RequestInfo info = 2; + + reserved 3 to 9; + + string step = 10; + repeated bytes query = 11; +} + +message QueryResponse { + Header header = 1; + Status status = 2; + + reserved 3 to 9; + + repeated bytes reply = 10; +} \ No newline at end of file diff --git a/psi/apps/pir_client/BUILD.bazel b/psi/apps/pir/client_service/BUILD.bazel similarity index 100% rename from psi/apps/pir_client/BUILD.bazel rename to psi/apps/pir/client_service/BUILD.bazel diff --git a/psi/apps/pir/config/BUILD.bazel b/psi/apps/pir/config/BUILD.bazel new file mode 100644 index 00000000..31818379 --- /dev/null +++ b/psi/apps/pir/config/BUILD.bazel @@ -0,0 +1,32 @@ +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@rules_proto//proto:defs.bzl", "proto_library") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "pir_proto", + srcs = ["pir.proto"], + deps = [ + "//psi/apps/pir/apis:common_proto", + ], +) + +cc_proto_library( + name = "pir_cc_proto", + deps = [ + ":pir_proto", + ], +) diff --git a/psi/apps/pir/config/pir.proto b/psi/apps/pir/config/pir.proto new file mode 100644 index 00000000..58c8365d --- /dev/null +++ b/psi/apps/pir/config/pir.proto @@ -0,0 +1,173 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +import "psi/apps/pir/apis/common.proto"; + +package pir; + +enum PirBackend { + BACKEND_UNKNOWN = 0; + BACKEND_APSI = 1; + BACKEND_SEAL_PIR = 2; + BACKEND_KW_SEAL_PIR = 3; +} + +message AlgorithmConfig { + PirBackend backend_type = 1; + uint64 ind_degree = 2; + uint64 max_batch_query_size = 3; +} + +message Schema { + repeated Field keys = 1; + repeated Field values = 2; +} + +message Field { + string name = 1; + DataType type = 2; +} + +message TlSConfig { + // Certificate file path + string certificate_path = 1; + + // Private key file path + string private_key_path = 2; + + // The trusted CA file to verify the peer's certificate + // If empty, use the system default CA files + string ca_file_path = 3; +} + +message MetricsConfig { + uint32 port = 1; +} + +message DataProxyLinkConfig { + string data_proxy_addr = 1; + + TlSConfig tls_config = 2; +} + +enum TableFileType { + FILE_TYPE_UNKNOWN = 0; + FILE_TYPE_CSV = 1; +} + +message LocalTableConfig { + TableFileType file_type = 1; + string file_name = 2; +} + +message DPDownLoadConfig { + DataProxyLinkConfig link_config = 1; + + string domaindata_id = 2; + + // specific the partition column and value, such as "dmdt=20240520" + string partition_spec = 3; +} + +message DPUploadConfig { + DataProxyLinkConfig link_config = 1; + + string domaindata_id = 2; + + string relative_uri = 3; + + string datasource_id = 4; +} + +message InputTabelConfig { + Schema schema = 1; + + oneof read_option { + DPDownLoadConfig dp_config = 4; + LocalTableConfig file_config = 5; + } +} + +message DBSaveConfig { + // path to save the db file, MUST be specified + string local_db_path = 1; + + // if domaindata_id is not emptys, will upload db_file to dp + DPUploadConfig db_upload_dst = 2; +} + +message PirPreprocessTaskConfig { + InputTabelConfig input = 1; + + DBSaveConfig db_save_config = 2; + + AlgorithmConfig algorithm_config = 3; +} + +message LocalDBConfig { + string db_path = 1; +} + +message DBLoadConfig { + oneof load_config { + LocalDBConfig local_db_config = 1; + DPDownLoadConfig dp_down_load_config = 2; + } +} + +message PirServerConfig { + string id = 1; + + string host = 2; + + uint32 server_port = 3; + + TlSConfig tls_config = 4; + + uint32 num_threads = 5; + + oneof data_config { + InputTabelConfig table_config = 6; + + DBLoadConfig db_load_config = 7; + } + + MetricsConfig metrics_config = 8; + + AlgorithmConfig algorithm_config = 9; +} + +message PirClientConfig { + string id = 1; + string host = 2; + uint32 port = 3; + + string server_id = 4; + string server_address = 5; + + MetricsConfig metrics_config = 6; + + TlSConfig tls_config = 7; + + // if set to true, the response table will include the keys in the query table + // if not set or false, the response table will not include the keys in the + // query table + bool response_include_keys = 8; + + // for check + AlgorithmConfig algorithm_config = 9; +} diff --git a/psi/apps/pir_server/BUILD.bazel b/psi/apps/pir/server_service/BUILD.bazel similarity index 100% rename from psi/apps/pir_server/BUILD.bazel rename to psi/apps/pir/server_service/BUILD.bazel diff --git a/psi/apps/psi_launcher/BUILD.bazel b/psi/apps/psi_launcher/BUILD.bazel index c506cdde..5ea937ba 100644 --- a/psi/apps/psi_launcher/BUILD.bazel +++ b/psi/apps/psi_launcher/BUILD.bazel @@ -41,6 +41,7 @@ psi_cc_library( ":factory", "//psi:trace_categories", "//psi/legacy:bucket_psi", + "//psi/proto:pir_cc_proto", "//psi/wrapper/apsi/cli:entry", "@boost.algorithm//:boost.algorithm", ], diff --git a/psi/apps/psi_launcher/launch.cc b/psi/apps/psi_launcher/launch.cc index 556c8e1b..6c5a7c33 100644 --- a/psi/apps/psi_launcher/launch.cc +++ b/psi/apps/psi_launcher/launch.cc @@ -184,6 +184,9 @@ PirResultReport RunPir(const ApsiReceiverConfig& apsi_receiver_config, apsi_receiver_config.experimental_enable_bucketize(); options.experimental_bucket_cnt = apsi_receiver_config.experimental_bucket_cnt(); + options.query_batch_size = apsi_receiver_config.query_batch_size() + ? apsi_receiver_config.query_batch_size() + : 1; int* match_cnt = new int(0); diff --git a/psi/apps/psi_launcher/main.cc b/psi/apps/psi_launcher/main.cc index cf713245..f0ba5214 100644 --- a/psi/apps/psi_launcher/main.cc +++ b/psi/apps/psi_launcher/main.cc @@ -25,7 +25,6 @@ #include "psi/version.h" #include "psi/proto/entry.pb.h" -#include "psi/proto/pir.pb.h" #include "psi/proto/psi.pb.h" #include "psi/proto/psi_v2.pb.h" diff --git a/psi/prelude.h b/psi/prelude.h index 332bba76..38ea6d0d 100644 --- a/psi/prelude.h +++ b/psi/prelude.h @@ -16,7 +16,6 @@ #include "fmt/ostream.h" -#include "psi/proto/pir.pb.h" #include "psi/proto/psi.pb.h" #include "psi/proto/psi_v2.pb.h" diff --git a/psi/proto/entry.proto b/psi/proto/entry.proto index 75c37d4a..8ce92fc1 100644 --- a/psi/proto/entry.proto +++ b/psi/proto/entry.proto @@ -16,8 +16,8 @@ syntax = "proto3"; import "psi/proto/psi.proto"; -import "psi/proto/pir.proto"; import "psi/proto/psi_v2.proto"; +import "psi/proto/pir.proto"; import "yacl/link/link.proto"; package psi; diff --git a/psi/proto/pir.proto b/psi/proto/pir.proto index fb3b8873..488ea34e 100644 --- a/psi/proto/pir.proto +++ b/psi/proto/pir.proto @@ -14,9 +14,6 @@ // limitations under the License. // -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - syntax = "proto3"; package psi; @@ -123,9 +120,12 @@ message ApsiReceiverConfig { // Must be same as sender config. uint32 experimental_bucket_cnt = 9; + + // The number of query in a batch. default 1. + uint32 query_batch_size = 10; } // The report of pir task. message PirResultReport { int64 match_cnt = 1; -} +} \ No newline at end of file diff --git a/psi/proto/psi.proto b/psi/proto/psi.proto index e2a6904f..028dbb03 100644 --- a/psi/proto/psi.proto +++ b/psi/proto/psi.proto @@ -18,9 +18,11 @@ syntax = "proto3"; package psi; -// **Deprecation notice** -// This enum is scheduled for removal in a future release. -// Use psi.v2.ProtocolConfig instead. +// ``` +// Deprecation notice. +// This enum is scheduled for removal in a future release. +// Use psi.v2.ProtocolConfig instead. +// ``` // // The algorithm type of psi. enum PsiType { @@ -28,11 +30,15 @@ enum PsiType { INVALID_PSI_TYPE = 0; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // DDH based PSI ECDH_PSI_2PC = 1; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // Efficient Batched Oblivious PRF with Applications to Private Set // Intersection https://eprint.iacr.org/2016/799.pdf KKRT_PSI_2PC = 2; @@ -49,23 +55,33 @@ enum PsiType { // Notice: two-party intersection leak KKRT_PSI_NPC = 6; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // ecdh-oprf 2-party Unbalanced-PSI Generate CACHE. ECDH_OPRF_UB_PSI_2PC_GEN_CACHE = 7; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // ecdh-oprf 2-party Unbalanced-PSI transfer CACHE. ECDH_OPRF_UB_PSI_2PC_TRANSFER_CACHE = 8; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // ecdh-oprf 2-party Unbalanced-PSI offline phase. ECDH_OPRF_UB_PSI_2PC_OFFLINE = 9; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // ecdh-oprf 2-party Unbalanced-PSI online phase. ECDH_OPRF_UB_PSI_2PC_ONLINE = 10; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // ecdh-oprf 2-party Unbalanced-PSI with shuffling online phase. // large set party get intersection result ECDH_OPRF_UB_PSI_2PC_SHUFFLE_ONLINE = 11; @@ -74,7 +90,9 @@ enum PsiType { // bases on ECDH-PSI, and provides: Differentially private PSI results. DP_PSI_2PC = 12; - // **NOTICED**: No longer supported + // ``` + // NOTICED: No longer supported + // ``` // Blazing Fast PSI https://eprint.iacr.org/2022/320.pdf // two mode: fast mode or low communication mode RR22_FAST_PSI_2PC = 13; @@ -106,9 +124,10 @@ enum CurveType { // CURVE_RISTRETTO255 = 5; } -// **Deprecation notice** -// This message is scheduled for removal in a future release. -// +// ``` +// Deprecation notice. +// This message is scheduled for removal in a future release. +// ``` // The input parameters of psi. message InputParams { // The path of input csv file. @@ -119,9 +138,10 @@ message InputParams { bool precheck = 3; } -// **Deprecation notice**. -// This message is scheduled for removal in a future release. -// +// ``` +// Deprecation notice. +// This message is scheduled for removal in a future release. +// ``` // The output parameters of psi. message OutputParams { // The path of output csv file. @@ -151,9 +171,11 @@ message DpPsiParams { double epsilon = 2; } -// **Deprecation notice**. -// This message is scheduled for removal in a future release. -// Use psi.v2.PsiConfig instead. +// ``` +// Deprecation notice. +// This message is scheduled for removal in a future release. +// Use psi.v2.PsiConfig instead. +// ``` // // The Bucket-psi configuration. // @@ -210,8 +232,10 @@ message BucketPsiConfig { DpPsiParams dppsi_params = 10; } -// **Deprecation notice**. -// This message is scheduled for removal in a future release. +// ``` +// Deprecation notice. +// This message is scheduled for removal in a future release. +// ``` // // The In-memory psi configuration. // diff --git a/psi/utils/BUILD.bazel b/psi/utils/BUILD.bazel index b231f545..5f63f1cb 100644 --- a/psi/utils/BUILD.bazel +++ b/psi/utils/BUILD.bazel @@ -67,6 +67,7 @@ psi_cc_library( hdrs = ["pb_helper.h"], deps = [ ":io", + "@protobuf", "@yacl//yacl/base:exception", ], ) diff --git a/psi/wrapper/apsi/README.md b/psi/wrapper/apsi/README.md index f8ba397e..5eb1f397 100644 --- a/psi/wrapper/apsi/README.md +++ b/psi/wrapper/apsi/README.md @@ -1,7 +1,13 @@ -**Note**: This feature is currently in the early development stage and the API is not stable. Please expect changes as we continue to evolve. +# NOTE -### Future Development -We plan to enhance this project by adding Server and Client components. These will be introduced in future updates as we refine the architecture and finalize the API. +This feature is currently in the early development stage and the API is not stable. Please expect changes as we continue to evolve. -### Stay Tuned -We appreciate your interest and patience as we work to deliver a robust and reliable solution. Please keep an eye on this repository for upcoming changes and improvements. +## Future Development + +We plan to enhance this project by adding Server and Client components. +These will be introduced in future updates as we refine the architecture and finalize the API. + +## Stay Tuned + +We appreciate your interest and patience as we work to deliver a robust and reliable solution. +Please keep an eye on this repository for upcoming changes and improvements. diff --git a/psi/wrapper/apsi/api/BUILD.bazel b/psi/wrapper/apsi/api/BUILD.bazel index b45b8fcc..1cfd617b 100644 --- a/psi/wrapper/apsi/api/BUILD.bazel +++ b/psi/wrapper/apsi/api/BUILD.bazel @@ -86,7 +86,6 @@ psi_cc_test( deps = [ ":receiver_c_wrapper", ":sender_c_wrapper", - "@boost.uuid//:boost.uuid", ], ) @@ -101,7 +100,6 @@ psi_cc_test( deps = [ ":receiver", ":sender", - "@boost.uuid//:boost.uuid", ], ) @@ -116,6 +114,5 @@ psi_cc_test( deps = [ ":receiver", ":sender", - "@boost.uuid//:boost.uuid", ], ) diff --git a/psi/wrapper/apsi/api/api_test.cc b/psi/wrapper/apsi/api/api_test.cc index 0c04d841..479f815b 100644 --- a/psi/wrapper/apsi/api/api_test.cc +++ b/psi/wrapper/apsi/api/api_test.cc @@ -18,13 +18,11 @@ #include <iostream> #include <string> -#include "boost/uuid/uuid.hpp" -#include "boost/uuid/uuid_generators.hpp" -#include "boost/uuid/uuid_io.hpp" #include "fmt/format.h" #include "gtest/gtest.h" #include "spdlog/spdlog.h" +#include "psi/utils/random_str.h" #include "psi/wrapper/apsi/api/receiver.h" #include "psi/wrapper/apsi/api/sender.h" #include "psi/wrapper/apsi/sender.h" @@ -49,8 +47,7 @@ TEST(ApiTest, Works) { bool compress = false; std::string receiver_query_file = "examples/pir/apsi/data/query.csv"; - boost::uuids::random_generator uuid_generator; - auto uuid_str = boost::uuids::to_string(uuid_generator()); + auto uuid_str = GetRandomString(); std::filesystem::path tmp_folder{std::filesystem::temp_directory_path() / uuid_str}; diff --git a/psi/wrapper/apsi/api/api_test_label.cc b/psi/wrapper/apsi/api/api_test_label.cc index 987c1e57..1f65e8c2 100644 --- a/psi/wrapper/apsi/api/api_test_label.cc +++ b/psi/wrapper/apsi/api/api_test_label.cc @@ -17,13 +17,11 @@ #include <iostream> #include <string> -#include "boost/uuid/uuid.hpp" -#include "boost/uuid/uuid_generators.hpp" -#include "boost/uuid/uuid_io.hpp" #include "fmt/format.h" #include "gtest/gtest.h" #include "spdlog/spdlog.h" +#include "psi/utils/random_str.h" #include "psi/wrapper/apsi/api/receiver.h" #include "psi/wrapper/apsi/api/sender.h" #include "psi/wrapper/apsi/sender.h" @@ -60,8 +58,7 @@ TEST(ApiTest, Works) { std::filesystem::path tmp_dir = std::filesystem::temp_directory_path(); - boost::uuids::random_generator uuid_generator; - auto uuid_str = boost::uuids::to_string(uuid_generator()); + auto uuid_str = GetRandomString(); std::string receiver_output_file = tmp_dir / fmt::format("result_{}.csv", uuid_str); diff --git a/psi/wrapper/apsi/api/wrapper_test.cc b/psi/wrapper/apsi/api/wrapper_test.cc index 5bfcf36d..44ccfb1c 100644 --- a/psi/wrapper/apsi/api/wrapper_test.cc +++ b/psi/wrapper/apsi/api/wrapper_test.cc @@ -18,13 +18,11 @@ #include <iostream> #include <string> -#include "boost/uuid/uuid.hpp" -#include "boost/uuid/uuid_generators.hpp" -#include "boost/uuid/uuid_io.hpp" #include "fmt/format.h" #include "gtest/gtest.h" #include "spdlog/spdlog.h" +#include "psi/utils/random_str.h" #include "psi/wrapper/apsi/api/receiver_c_wrapper.h" #include "psi/wrapper/apsi/api/sender_c_wrapper.h" #include "psi/wrapper/apsi/utils/csv_reader.h" @@ -48,8 +46,7 @@ TEST(ApiTest, Works) { bool compress = false; std::string receiver_query_file = "examples/pir/apsi/data/query.csv"; - boost::uuids::random_generator uuid_generator; - auto uuid_str = boost::uuids::to_string(uuid_generator()); + auto uuid_str = GetRandomString(); std::filesystem::path tmp_folder{std::filesystem::temp_directory_path() / uuid_str}; diff --git a/psi/wrapper/apsi/cli/BUILD.bazel b/psi/wrapper/apsi/cli/BUILD.bazel index a09f277f..f060d7b4 100644 --- a/psi/wrapper/apsi/cli/BUILD.bazel +++ b/psi/wrapper/apsi/cli/BUILD.bazel @@ -45,7 +45,6 @@ psi_cc_library( deps = [ ":common_utils", ":sender_dispatcher", - "//psi/proto:pir_cc_proto", "//psi/utils:resource_manager", "//psi/wrapper/apsi:receiver", "//psi/wrapper/apsi:sender", diff --git a/psi/wrapper/apsi/cli/entry.h b/psi/wrapper/apsi/cli/entry.h index cc0b2ff1..bbc4a9ee 100644 --- a/psi/wrapper/apsi/cli/entry.h +++ b/psi/wrapper/apsi/cli/entry.h @@ -50,7 +50,8 @@ struct ReceiverOptions { // experimental bucketize bool experimental_enable_bucketize = false; - size_t experimental_bucket_cnt; + size_t experimental_bucket_cnt = 10; + size_t query_batch_size = 1; }; struct SenderOptions { @@ -88,7 +89,7 @@ struct SenderOptions { size_t experimental_bucket_cnt; std::string experimental_bucket_folder; int experimental_db_generating_process_num = 8; - int experimental_bucket_group_cnt = 1024; + int experimental_bucket_group_cnt = 512; }; int RunReceiver(const ReceiverOptions& options, diff --git a/psi/wrapper/apsi/utils/group_db.cc b/psi/wrapper/apsi/utils/group_db.cc index 91e44715..050a5661 100644 --- a/psi/wrapper/apsi/utils/group_db.cc +++ b/psi/wrapper/apsi/utils/group_db.cc @@ -17,20 +17,17 @@ #include <apsi/psi_params.h> #include <fcntl.h> #include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> -#include <condition_variable> #include <csignal> #include <cstddef> #include <filesystem> #include <fstream> -#include <future> -#include <memory> -#include <mutex> #include <string> -#include <unordered_map> #include <utility> #include "arrow/array.h" @@ -38,9 +35,9 @@ #include "google/protobuf/util/json_util.h" #include "sender_db.h" #include "spdlog/spdlog.h" +#include "sys/sem.h" #include "yacl/base/exception.h" -#include "psi/wrapper/apsi/utils/common.h" #include "psi/wrapper/apsi/utils/csv_reader.h" namespace psi::apsi_wrapper { @@ -51,34 +48,103 @@ constexpr const char* kGroupLabel = "value"; constexpr const char* kGroupKey = "key"; constexpr const char* kGroupBucketId = "bucket_id"; -template <typename F, typename... Args> -pid_t StartProcess(F&& f, Args&&... args) { - auto pid = fork(); - switch (pid) { - case -1: - SPDLOG_ERROR("fork failed"); +union semun { + int val; + struct semid_ds* buf; + unsigned short int* array; + struct seminfo* __buf; +}; + +class GroupDBGenerator { + public: + GroupDBGenerator() { + semid_ = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR | IPC_CREAT); + if (semid_ == -1) { + SPDLOG_ERROR("failed to create semaphore"); exit(1); - case 0: - try { - auto res = f(std::forward<Args&&>(args)...); + } + semun semctl_arg; + semctl_arg.val = 0; + int ret = semctl(semid_, 0, SETVAL, semctl_arg); + if (ret == -1) { + SPDLOG_ERROR("failed to set semaphore value to 0, errno: {} , str: {}", + errno, strerror(errno)); + exit(1); + } + } + + template <typename F, typename... Args> + void Execute(F&& f, Args&&... args) { + auto pid = fork(); + switch (pid) { + case -1: + SPDLOG_ERROR("fork failed"); + exit(1); + case 0: { + int res = 0; + try { + res = std::forward<F>(f)(std::forward<Args&&>(args)...); + } catch (const std::exception& e) { + SPDLOG_ERROR("subprocess {} failed, error: {}", getpid(), e.what()); + res = 1; + } catch (...) { + SPDLOG_ERROR("subprocess {} failed, unknown error", getpid()); + res = 1; + } + + SPDLOG_INFO("subprocess {} is finished.", getpid()); + + sembuf sem; + sem.sem_num = 0; + sem.sem_op = 1; + sem.sem_flg = 0; + if (semop(semid_, &sem, 1) == -1) { + SPDLOG_ERROR("failed to increase semaphore"); + exit(1); + } if (res == 0) { exit(0); } exit(1); - } catch (const std::exception& ex) { - SPDLOG_ERROR("process failed: {}", ex.what()); - exit(1); } - default: - return pid; + default: + SPDLOG_INFO("start subprocess {}.", pid); + childs_.push_back(pid); + break; + } } -} -std::string PidFileName(pid_t pid) { - return std::filesystem::temp_directory_path() / - fmt::format("apsi_process_{}", pid); -} + void WaitToFinish() { + int child_num = childs_.size(); + sembuf sem; + sem.sem_num = 0; + sem.sem_op = -1 * child_num; + sem.sem_flg = 0; + if (semop(semid_, &sem, 1) == -1) { + SPDLOG_ERROR("failed to increase semaphore"); + exit(1); + } + + for (auto pid : childs_) { + kill(pid, SIGKILL); + int status; + waitpid(pid, &status, 0); + SPDLOG_INFO("subprocess {} is reaped.", pid); + } + childs_.clear(); + + semun dummy; + if (semctl(semid_, 1, IPC_RMID, dummy) == -1) { + SPDLOG_ERROR("failed to remove semaphore"); + exit(1); + } + } + + private: + int semid_ = -1; + std::vector<pid_t> childs_; +}; } // namespace @@ -90,7 +156,7 @@ void ProcessGroupParallel(size_t process_num, GroupDB& group_db) { SPDLOG_INFO("{} process will be started", process_num); - std::vector<pid_t> pids; + GroupDBGenerator generator; // TODO: brpc has some issue with fork, the children process will not exit due // to some lock issues, one solution may be IPC, child process tell parent it @@ -107,42 +173,13 @@ void ProcessGroupParallel(size_t process_num, GroupDB& group_db) { for (size_t i = beg; i != end; ++i) { group_db.GenerateGroup(i); } - std::ofstream pid_flag_file(PidFileName(getpid())); - if (!pid_flag_file.good()) { - return 1; - } return 0; }; - pids.push_back(StartProcess(func)); + generator.Execute(func); } - int status; - bool process_error = false; - for (auto& pid : pids) { - SPDLOG_INFO("wait for process {}", pid); - while (!std::filesystem::exists(PidFileName(pid))) { - // check process exists - if (kill(pid, 0) == 0) { - sleep(1); - } else { - SPDLOG_INFO("subprocess {} is done.", pid); - break; - } - } - - if (!std::filesystem::exists(PidFileName(pid))) { - SPDLOG_ERROR("subprocess {} job is not accomplished.", pid); - process_error = true; - } else { - // normal exit is not necessary - kill(pid, SIGKILL); - waitpid(pid, &status, 0); - SPDLOG_INFO("subprocess {} is reaped.", pid); - std::filesystem::remove(PidFileName(pid)); - } - } - YACL_ENFORCE(!process_error, "multi_process failed"); + generator.WaitToFinish(); } void GenerateGroupBucketDB(GroupDB& group_db, size_t process_num) { @@ -356,7 +393,6 @@ void GroupDBItem::Generate() { bucket_dbs_.push_back(bucket_db); } - // future.get(); flush_proc(); std::ofstream meta_ofs(meta_filename_); diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..28cf77c3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,27 @@ +[tool.black] +skip-string-normalization = true + +[tool.isort] +profile = "black" + +[tool.rstcheck] +report_level = "ERROR" +ignore_directives = [ + "include", + "mermaid", + "autoclass", + "automodule", + "autofunction", +] +ignore_languages = [ + "cpp" +] +ignore_roles = [ + "psi_code_host" +] + +reportMissingImports = true +reportMissingTypeStubs = false + +pythonVersion = "3.10" +pythonPlatform = "Linux"