Merge pull request #3 from gaussian-dev/fix-jay

Add JS package
This commit is contained in:
Janmajayamall
2024-01-19 20:52:28 +05:30
committed by GitHub
14 changed files with 2509 additions and 186 deletions

2
.gitignore vendored
View File

@@ -1 +1 @@
/target
/target

617
Cargo.lock generated
View File

@@ -2,12 +2,27 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "aligned-vec"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
[[package]]
name = "anyhow"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "autocfg"
version = "1.1.0"
@@ -17,21 +32,46 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bfv"
version = "0.1.0"
source = "git+https://github.com/Janmajayamall/bfv?branch=pk#34090532ce04ee6c143753edab11f902c057837c"
source = "git+https://github.com/Janmajayamall/bfv.git?branch=wasm#55181279cf5701d9706a92cb87f345573e8f9af4"
dependencies = [
"concrete-ntt",
"crypto-bigint",
"itertools",
"getrandom",
"itertools 0.10.5",
"ndarray",
"num-bigint",
"num-bigint-dig",
"num-traits",
"prost",
"prost-build",
"prost-wkt",
"prost-wkt-build",
"prost-wkt-types",
"rand",
"rand_chacha",
"seq-macro",
"serde",
"traits",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "bumpalo"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytemuck"
version = "1.14.0"
@@ -44,12 +84,28 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"num-traits",
"serde",
]
[[package]]
name = "concrete-ntt"
version = "0.1.1"
@@ -60,6 +116,16 @@ dependencies = [
"pulp",
]
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]]
name = "crypto-bigint"
version = "0.4.9"
@@ -77,16 +143,92 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "getrandom"
version = "0.2.11"
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "erased-serde"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55d05712b2d8d88102bc9868020c9e5c7a1f5527c452b9b97450a1d006140ba7"
dependencies = [
"serde",
]
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "fixedbitset"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "getrandom"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys",
]
[[package]]
name = "indexmap"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "inventory"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8573b2b1fb643a372c73b23f4da5f888677feef3305146d68a539250a9bccc7"
[[package]]
name = "itertools"
version = "0.10.5"
@@ -96,6 +238,30 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -107,9 +273,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.151"
version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "libm"
@@ -117,6 +283,18 @@ version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "matrixmultiply"
version = "0.3.8"
@@ -127,15 +305,32 @@ dependencies = [
"rawpointer",
]
[[package]]
name = "memchr"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "mp-psi"
version = "0.1.0"
dependencies = [
"bfv",
"itertools",
"console_error_panic_hook",
"itertools 0.10.5",
"rand",
"serde",
"serde-wasm-bindgen",
"traits",
"wasm-bindgen",
]
[[package]]
name = "multimap"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]]
name = "ndarray"
version = "0.15.6"
@@ -217,6 +412,22 @@ dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "petgraph"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@@ -224,14 +435,124 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.70"
name = "prettyplease"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "prost"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-build"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2"
dependencies = [
"bytes",
"heck",
"itertools 0.11.0",
"log",
"multimap",
"once_cell",
"petgraph",
"prettyplease",
"prost",
"prost-types",
"regex",
"syn",
"tempfile",
"which",
]
[[package]]
name = "prost-derive"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
dependencies = [
"anyhow",
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "prost-types"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e"
dependencies = [
"prost",
]
[[package]]
name = "prost-wkt"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d8ef9c3f0f1dab910d2b7e2c24a8e4322e122eba6d7a1921eeebcebbc046c40"
dependencies = [
"chrono",
"inventory",
"prost",
"serde",
"serde_derive",
"serde_json",
"typetag",
]
[[package]]
name = "prost-wkt-build"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b31cae9a54ca84fee1504740a82eebf2479532905e106f63ca0c3bc8d780321"
dependencies = [
"heck",
"prost",
"prost-build",
"prost-types",
"quote",
]
[[package]]
name = "prost-wkt-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435be4a8704091b4c5fb1d79799de7f2dbff53af05edf29385237f8cf7ab37ee"
dependencies = [
"chrono",
"prost",
"prost-build",
"prost-types",
"prost-wkt",
"prost-wkt-build",
"regex",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "pulp"
version = "0.11.11"
@@ -243,9 +564,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -286,6 +607,63 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustix"
version = "0.38.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
dependencies = [
"bitflags 2.4.2",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "seq-macro"
version = "0.3.5"
@@ -294,18 +672,29 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
[[package]]
name = "serde"
version = "1.0.193"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.193"
name = "serde-wasm-bindgen"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde_derive"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
@@ -313,10 +702,21 @@ dependencies = [
]
[[package]]
name = "smallvec"
version = "1.11.2"
name = "serde_json"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"
[[package]]
name = "spin"
@@ -332,19 +732,56 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "2.0.40"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall",
"rustix",
"windows-sys",
]
[[package]]
name = "traits"
version = "0.1.0"
source = "git+https://github.com/Janmajayamall/bfv?branch=pk#34090532ce04ee6c143753edab11f902c057837c"
source = "git+https://github.com/Janmajayamall/bfv.git?branch=wasm#55181279cf5701d9706a92cb87f345573e8f9af4"
[[package]]
name = "typetag"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43148481c7b66502c48f35b8eef38b6ccdc7a9f04bd4cc294226d901ccc9bc7"
dependencies = [
"erased-serde",
"inventory",
"once_cell",
"serde",
"typetag-impl",
]
[[package]]
name = "typetag-impl"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291db8a81af4840c10d636e047cac67664e343be44e24dfdbd1492df9a5d3390"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
@@ -357,3 +794,135 @@ name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"

View File

@@ -5,7 +5,28 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
bfv = {git = "https://github.com/Janmajayamall/bfv", branch = "pk"}
bfv = {git = "https://github.com/Janmajayamall/bfv.git", features=["serialize", "std"], branch = "wasm"}
traits = {git = "https://github.com/Janmajayamall/bfv.git", branch = "wasm"}
rand = "0.8.5"
itertools = "0.10.5"
wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Gaussian
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1 +1,22 @@
Multi-party PSI using Multi-party BFV
# MP-PSI
The library contains the following components:
- `src`: Rust library for multi-party PSI using BFV
- `pkg`: JS-TS-WASM package
### Build
The rust library is used to build the JS-TS-WASM package using `wasm-pack` [guide](https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_Wasm)
```bash
wasm-pack build --target nodejs
```
### Test
To test the rust library, run:
```bash
cargo test
```

37
pkg/README.md Normal file
View File

@@ -0,0 +1,37 @@
# MP-PSI
The package contains the APIs to build a multi party private set intersection application.
PSI stands for Private Set Intersection. It allows two parties to compute the intersection of their sets without revealing anything else about their sets.
[BFV](https://inferati.azureedge.net/docs/inferati-fhe-bfv.pdf) is a fully homomorphic encryption scheme. It allows to perform addition and multiplication on encrypted data. The PSI protocol made available in this library uses the BFV scheme to perform the encryption of the sets, compute the intersection and decrypt the result. In particular, the multiparty protocol is based on the paper [Mouchet, Christian, et al. "Multiparty homomorphic encryption from ring-learning-with-errors."](https://eprint.iacr.org/2020/304.pdf).
### Install
Install the `mp-psi` package with npm:
```bash
npm i mp-psi
```
or yarn:
```bash
yarn add mp-psi
```
### Usage
```js
import { state0_bindgen, state1_bindgen, state2_bindgen, state3_bindgen, state4_bindgen } from "mp-psi";
const state0 = state0_bindgen();
const bit_vector_a = [1, 0, 1, 0, 1, 0, 1, 0, 1, 1];
const state1 = state1_bindgen(state0.message_a_to_b, bit_vector_a);
const bit_vector_b = [1, 1, 1, 1, 1, 0, 1, 0, 0, 0];
const state2 = state2_bindgen(state0.private_output_a, state0.public_output_a, state1.message_b_to_a, bit_vector_b);
const state3 = state3_bindgen(state1.private_output_b, state1.public_output_b, state2.message_a_to_b);
const psi_output_a = state4_bindgen(state2.public_output_a, state3.message_b_to_a);
const psi_output_b = state3.psi_output;
```

33
pkg/mp_psi.d.ts vendored Normal file
View File

@@ -0,0 +1,33 @@
/* tslint:disable */
/* eslint-disable */
/**
* @returns {any}
*/
export function state0_bindgen(): any;
/**
* @param {any} message_a_to_b
* @param {Uint32Array} bit_vector
* @returns {any}
*/
export function state1_bindgen(message_a_to_b: any, bit_vector: Uint32Array): any;
/**
* @param {any} private_output_a_state0
* @param {any} public_output_a_state0
* @param {any} message_b_to_a
* @param {Uint32Array} bit_vector
* @returns {any}
*/
export function state2_bindgen(private_output_a_state0: any, public_output_a_state0: any, message_b_to_a: any, bit_vector: Uint32Array): any;
/**
* @param {any} private_output_b_state1
* @param {any} public_output_b_state1
* @param {any} message_a_to_b
* @returns {any}
*/
export function state3_bindgen(private_output_b_state1: any, public_output_b_state1: any, message_a_to_b: any): any;
/**
* @param {any} public_output_a_state2
* @param {any} message_b_to_a
* @returns {Uint32Array}
*/
export function state4_bindgen(public_output_a_state2: any, message_b_to_a: any): Uint32Array;

588
pkg/mp_psi.js Normal file
View File

@@ -0,0 +1,588 @@
let imports = {};
imports['__wbindgen_placeholder__'] = module.exports;
let wasm;
const { TextEncoder, TextDecoder } = require(`util`);
const heap = new Array(128).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 132) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachedFloat64Memory0 = null;
function getFloat64Memory0() {
if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {
cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer);
}
return cachedFloat64Memory0;
}
let cachedInt32Memory0 = null;
function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}
let WASM_VECTOR_LEN = 0;
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
let cachedTextEncoder = new TextEncoder('utf-8');
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length, 1) >>> 0;
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len, 1) >>> 0;
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function debugString(val) {
// primitive types
const type = typeof val;
if (type == 'number' || type == 'boolean' || val == null) {
return `${val}`;
}
if (type == 'string') {
return `"${val}"`;
}
if (type == 'symbol') {
const description = val.description;
if (description == null) {
return 'Symbol';
} else {
return `Symbol(${description})`;
}
}
if (type == 'function') {
const name = val.name;
if (typeof name == 'string' && name.length > 0) {
return `Function(${name})`;
} else {
return 'Function';
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = '[';
if (length > 0) {
debug += debugString(val[0]);
}
for(let i = 1; i < length; i++) {
debug += ', ' + debugString(val[i]);
}
debug += ']';
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == 'Object') {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return 'Object(' + JSON.stringify(val) + ')';
} catch (_) {
return 'Object';
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
/**
* @returns {any}
*/
module.exports.state0_bindgen = function() {
const ret = wasm.state0_bindgen();
return takeObject(ret);
};
let cachedUint32Memory0 = null;
function getUint32Memory0() {
if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) {
cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer);
}
return cachedUint32Memory0;
}
function passArray32ToWasm0(arg, malloc) {
const ptr = malloc(arg.length * 4, 4) >>> 0;
getUint32Memory0().set(arg, ptr / 4);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
/**
* @param {any} message_a_to_b
* @param {Uint32Array} bit_vector
* @returns {any}
*/
module.exports.state1_bindgen = function(message_a_to_b, bit_vector) {
const ptr0 = passArray32ToWasm0(bit_vector, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.state1_bindgen(addHeapObject(message_a_to_b), ptr0, len0);
return takeObject(ret);
};
/**
* @param {any} private_output_a_state0
* @param {any} public_output_a_state0
* @param {any} message_b_to_a
* @param {Uint32Array} bit_vector
* @returns {any}
*/
module.exports.state2_bindgen = function(private_output_a_state0, public_output_a_state0, message_b_to_a, bit_vector) {
const ptr0 = passArray32ToWasm0(bit_vector, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.state2_bindgen(addHeapObject(private_output_a_state0), addHeapObject(public_output_a_state0), addHeapObject(message_b_to_a), ptr0, len0);
return takeObject(ret);
};
/**
* @param {any} private_output_b_state1
* @param {any} public_output_b_state1
* @param {any} message_a_to_b
* @returns {any}
*/
module.exports.state3_bindgen = function(private_output_b_state1, public_output_b_state1, message_a_to_b) {
const ret = wasm.state3_bindgen(addHeapObject(private_output_b_state1), addHeapObject(public_output_b_state1), addHeapObject(message_a_to_b));
return takeObject(ret);
};
function getArrayU32FromWasm0(ptr, len) {
ptr = ptr >>> 0;
return getUint32Memory0().subarray(ptr / 4, ptr / 4 + len);
}
/**
* @param {any} public_output_a_state2
* @param {any} message_b_to_a
* @returns {Uint32Array}
*/
module.exports.state4_bindgen = function(public_output_a_state2, message_b_to_a) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.state4_bindgen(retptr, addHeapObject(public_output_a_state2), addHeapObject(message_b_to_a));
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU32FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 4, 4);
return v1;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
};
function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
module.exports.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
module.exports.__wbindgen_is_object = function(arg0) {
const val = getObject(arg0);
const ret = typeof(val) === 'object' && val !== null;
return ret;
};
module.exports.__wbindgen_is_undefined = function(arg0) {
const ret = getObject(arg0) === undefined;
return ret;
};
module.exports.__wbindgen_in = function(arg0, arg1) {
const ret = getObject(arg0) in getObject(arg1);
return ret;
};
module.exports.__wbindgen_object_clone_ref = function(arg0) {
const ret = getObject(arg0);
return addHeapObject(ret);
};
module.exports.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
const ret = getObject(arg0) == getObject(arg1);
return ret;
};
module.exports.__wbindgen_boolean_get = function(arg0) {
const v = getObject(arg0);
const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
return ret;
};
module.exports.__wbindgen_number_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'number' ? obj : undefined;
getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret;
getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
};
module.exports.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
module.exports.__wbindgen_error_new = function(arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
module.exports.__wbindgen_number_new = function(arg0) {
const ret = arg0;
return addHeapObject(ret);
};
module.exports.__wbindgen_string_new = function(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
module.exports.__wbg_getwithrefkey_15c62c2b8546208d = function(arg0, arg1) {
const ret = getObject(arg0)[getObject(arg1)];
return addHeapObject(ret);
};
module.exports.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) {
getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
};
module.exports.__wbg_crypto_d05b68a3572bb8ca = function(arg0) {
const ret = getObject(arg0).crypto;
return addHeapObject(ret);
};
module.exports.__wbg_process_b02b3570280d0366 = function(arg0) {
const ret = getObject(arg0).process;
return addHeapObject(ret);
};
module.exports.__wbg_versions_c1cb42213cedf0f5 = function(arg0) {
const ret = getObject(arg0).versions;
return addHeapObject(ret);
};
module.exports.__wbg_node_43b1089f407e4ec2 = function(arg0) {
const ret = getObject(arg0).node;
return addHeapObject(ret);
};
module.exports.__wbindgen_is_string = function(arg0) {
const ret = typeof(getObject(arg0)) === 'string';
return ret;
};
module.exports.__wbg_require_9a7e0f667ead4995 = function() { return handleError(function () {
const ret = module.require;
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_msCrypto_10fc94afee92bd76 = function(arg0) {
const ret = getObject(arg0).msCrypto;
return addHeapObject(ret);
};
module.exports.__wbg_randomFillSync_b70ccbdf4926a99d = function() { return handleError(function (arg0, arg1) {
getObject(arg0).randomFillSync(takeObject(arg1));
}, arguments) };
module.exports.__wbg_getRandomValues_7e42b4fb8779dc6d = function() { return handleError(function (arg0, arg1) {
getObject(arg0).getRandomValues(getObject(arg1));
}, arguments) };
module.exports.__wbg_get_c43534c00f382c8a = function(arg0, arg1) {
const ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
};
module.exports.__wbg_length_d99b680fd68bf71b = function(arg0) {
const ret = getObject(arg0).length;
return ret;
};
module.exports.__wbg_new_34c624469fb1d4fd = function() {
const ret = new Array();
return addHeapObject(ret);
};
module.exports.__wbindgen_is_function = function(arg0) {
const ret = typeof(getObject(arg0)) === 'function';
return ret;
};
module.exports.__wbg_newnoargs_5859b6d41c6fe9f7 = function(arg0, arg1) {
const ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
module.exports.__wbg_next_1938cf110c9491d4 = function(arg0) {
const ret = getObject(arg0).next;
return addHeapObject(ret);
};
module.exports.__wbg_next_267398d0e0761bf9 = function() { return handleError(function (arg0) {
const ret = getObject(arg0).next();
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_done_506b44765ba84b9c = function(arg0) {
const ret = getObject(arg0).done;
return ret;
};
module.exports.__wbg_value_31485d8770eb06ab = function(arg0) {
const ret = getObject(arg0).value;
return addHeapObject(ret);
};
module.exports.__wbg_iterator_364187e1ee96b750 = function() {
const ret = Symbol.iterator;
return addHeapObject(ret);
};
module.exports.__wbg_get_5027b32da70f39b1 = function() { return handleError(function (arg0, arg1) {
const ret = Reflect.get(getObject(arg0), getObject(arg1));
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_call_a79f1973a4f07d5e = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_new_87d841e70661f6e9 = function() {
const ret = new Object();
return addHeapObject(ret);
};
module.exports.__wbg_self_086b5302bcafb962 = function() { return handleError(function () {
const ret = self.self;
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_window_132fa5d7546f1de5 = function() { return handleError(function () {
const ret = window.window;
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_globalThis_e5f801a37ad7d07b = function() { return handleError(function () {
const ret = globalThis.globalThis;
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_global_f9a61fce4af6b7c1 = function() { return handleError(function () {
const ret = global.global;
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_set_379b27f1d5f1bf9c = function(arg0, arg1, arg2) {
getObject(arg0)[arg1 >>> 0] = takeObject(arg2);
};
module.exports.__wbg_isArray_fbd24d447869b527 = function(arg0) {
const ret = Array.isArray(getObject(arg0));
return ret;
};
module.exports.__wbg_instanceof_ArrayBuffer_f4521cec1b99ee35 = function(arg0) {
let result;
try {
result = getObject(arg0) instanceof ArrayBuffer;
} catch (_) {
result = false;
}
const ret = result;
return ret;
};
module.exports.__wbg_call_f6a2bc58c19c53c6 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
module.exports.__wbg_isSafeInteger_d8c89788832a17bf = function(arg0) {
const ret = Number.isSafeInteger(getObject(arg0));
return ret;
};
module.exports.__wbg_buffer_5d1b598a01b41a42 = function(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
module.exports.__wbg_newwithbyteoffsetandlength_d695c7957788f922 = function(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
module.exports.__wbg_new_ace717933ad7117f = function(arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
module.exports.__wbg_set_74906aa30864df5a = function(arg0, arg1, arg2) {
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
};
module.exports.__wbg_length_f0764416ba5bb237 = function(arg0) {
const ret = getObject(arg0).length;
return ret;
};
module.exports.__wbg_instanceof_Uint8Array_4f5cffed7df34b2f = function(arg0) {
let result;
try {
result = getObject(arg0) instanceof Uint8Array;
} catch (_) {
result = false;
}
const ret = result;
return ret;
};
module.exports.__wbg_newwithlength_728575f3bba9959b = function(arg0) {
const ret = new Uint8Array(arg0 >>> 0);
return addHeapObject(ret);
};
module.exports.__wbg_subarray_7f7a652672800851 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
module.exports.__wbindgen_debug_string = function(arg0, arg1) {
const ret = debugString(getObject(arg1));
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
module.exports.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
module.exports.__wbindgen_memory = function() {
const ret = wasm.memory;
return addHeapObject(ret);
};
const path = require('path').join(__dirname, 'mp_psi_bg.wasm');
const bytes = require('fs').readFileSync(path);
const wasmModule = new WebAssembly.Module(bytes);
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
wasm = wasmInstance.exports;
module.exports.__wasm = wasm;

585
pkg/mp_psi_bg.js Normal file
View File

@@ -0,0 +1,585 @@
let wasm;
export function __wbg_set_wasm(val) {
wasm = val;
}
const heap = new Array(128).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 132) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachedFloat64Memory0 = null;
function getFloat64Memory0() {
if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {
cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer);
}
return cachedFloat64Memory0;
}
let cachedInt32Memory0 = null;
function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}
let WASM_VECTOR_LEN = 0;
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
const lTextEncoder = typeof TextEncoder === 'undefined' ? (0, module.require)('util').TextEncoder : TextEncoder;
let cachedTextEncoder = new lTextEncoder('utf-8');
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length, 1) >>> 0;
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len, 1) >>> 0;
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
const lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;
let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function debugString(val) {
// primitive types
const type = typeof val;
if (type == 'number' || type == 'boolean' || val == null) {
return `${val}`;
}
if (type == 'string') {
return `"${val}"`;
}
if (type == 'symbol') {
const description = val.description;
if (description == null) {
return 'Symbol';
} else {
return `Symbol(${description})`;
}
}
if (type == 'function') {
const name = val.name;
if (typeof name == 'string' && name.length > 0) {
return `Function(${name})`;
} else {
return 'Function';
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = '[';
if (length > 0) {
debug += debugString(val[0]);
}
for(let i = 1; i < length; i++) {
debug += ', ' + debugString(val[i]);
}
debug += ']';
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == 'Object') {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return 'Object(' + JSON.stringify(val) + ')';
} catch (_) {
return 'Object';
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
/**
* @returns {any}
*/
export function state0_bindgen() {
const ret = wasm.state0_bindgen();
return takeObject(ret);
}
let cachedUint32Memory0 = null;
function getUint32Memory0() {
if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) {
cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer);
}
return cachedUint32Memory0;
}
function passArray32ToWasm0(arg, malloc) {
const ptr = malloc(arg.length * 4, 4) >>> 0;
getUint32Memory0().set(arg, ptr / 4);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
/**
* @param {any} message_a_to_b
* @param {Uint32Array} bit_vector
* @returns {any}
*/
export function state1_bindgen(message_a_to_b, bit_vector) {
const ptr0 = passArray32ToWasm0(bit_vector, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.state1_bindgen(addHeapObject(message_a_to_b), ptr0, len0);
return takeObject(ret);
}
/**
* @param {any} private_output_a_state0
* @param {any} public_output_a_state0
* @param {any} message_b_to_a
* @param {Uint32Array} bit_vector
* @returns {any}
*/
export function state2_bindgen(private_output_a_state0, public_output_a_state0, message_b_to_a, bit_vector) {
const ptr0 = passArray32ToWasm0(bit_vector, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.state2_bindgen(addHeapObject(private_output_a_state0), addHeapObject(public_output_a_state0), addHeapObject(message_b_to_a), ptr0, len0);
return takeObject(ret);
}
/**
* @param {any} private_output_b_state1
* @param {any} public_output_b_state1
* @param {any} message_a_to_b
* @returns {any}
*/
export function state3_bindgen(private_output_b_state1, public_output_b_state1, message_a_to_b) {
const ret = wasm.state3_bindgen(addHeapObject(private_output_b_state1), addHeapObject(public_output_b_state1), addHeapObject(message_a_to_b));
return takeObject(ret);
}
function getArrayU32FromWasm0(ptr, len) {
ptr = ptr >>> 0;
return getUint32Memory0().subarray(ptr / 4, ptr / 4 + len);
}
/**
* @param {any} public_output_a_state2
* @param {any} message_b_to_a
* @returns {Uint32Array}
*/
export function state4_bindgen(public_output_a_state2, message_b_to_a) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.state4_bindgen(retptr, addHeapObject(public_output_a_state2), addHeapObject(message_b_to_a));
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU32FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 4, 4);
return v1;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
export function __wbindgen_object_drop_ref(arg0) {
takeObject(arg0);
};
export function __wbindgen_is_object(arg0) {
const val = getObject(arg0);
const ret = typeof(val) === 'object' && val !== null;
return ret;
};
export function __wbindgen_is_undefined(arg0) {
const ret = getObject(arg0) === undefined;
return ret;
};
export function __wbindgen_in(arg0, arg1) {
const ret = getObject(arg0) in getObject(arg1);
return ret;
};
export function __wbindgen_object_clone_ref(arg0) {
const ret = getObject(arg0);
return addHeapObject(ret);
};
export function __wbindgen_jsval_loose_eq(arg0, arg1) {
const ret = getObject(arg0) == getObject(arg1);
return ret;
};
export function __wbindgen_boolean_get(arg0) {
const v = getObject(arg0);
const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
return ret;
};
export function __wbindgen_number_get(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'number' ? obj : undefined;
getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret;
getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
};
export function __wbindgen_string_get(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
export function __wbindgen_error_new(arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
export function __wbindgen_number_new(arg0) {
const ret = arg0;
return addHeapObject(ret);
};
export function __wbindgen_string_new(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
export function __wbg_getwithrefkey_15c62c2b8546208d(arg0, arg1) {
const ret = getObject(arg0)[getObject(arg1)];
return addHeapObject(ret);
};
export function __wbg_set_20cbc34131e76824(arg0, arg1, arg2) {
getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
};
export function __wbg_crypto_d05b68a3572bb8ca(arg0) {
const ret = getObject(arg0).crypto;
return addHeapObject(ret);
};
export function __wbg_process_b02b3570280d0366(arg0) {
const ret = getObject(arg0).process;
return addHeapObject(ret);
};
export function __wbg_versions_c1cb42213cedf0f5(arg0) {
const ret = getObject(arg0).versions;
return addHeapObject(ret);
};
export function __wbg_node_43b1089f407e4ec2(arg0) {
const ret = getObject(arg0).node;
return addHeapObject(ret);
};
export function __wbindgen_is_string(arg0) {
const ret = typeof(getObject(arg0)) === 'string';
return ret;
};
export function __wbg_require_9a7e0f667ead4995() { return handleError(function () {
const ret = module.require;
return addHeapObject(ret);
}, arguments) };
export function __wbg_msCrypto_10fc94afee92bd76(arg0) {
const ret = getObject(arg0).msCrypto;
return addHeapObject(ret);
};
export function __wbg_randomFillSync_b70ccbdf4926a99d() { return handleError(function (arg0, arg1) {
getObject(arg0).randomFillSync(takeObject(arg1));
}, arguments) };
export function __wbg_getRandomValues_7e42b4fb8779dc6d() { return handleError(function (arg0, arg1) {
getObject(arg0).getRandomValues(getObject(arg1));
}, arguments) };
export function __wbg_get_c43534c00f382c8a(arg0, arg1) {
const ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
};
export function __wbg_length_d99b680fd68bf71b(arg0) {
const ret = getObject(arg0).length;
return ret;
};
export function __wbg_new_34c624469fb1d4fd() {
const ret = new Array();
return addHeapObject(ret);
};
export function __wbindgen_is_function(arg0) {
const ret = typeof(getObject(arg0)) === 'function';
return ret;
};
export function __wbg_newnoargs_5859b6d41c6fe9f7(arg0, arg1) {
const ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
export function __wbg_next_1938cf110c9491d4(arg0) {
const ret = getObject(arg0).next;
return addHeapObject(ret);
};
export function __wbg_next_267398d0e0761bf9() { return handleError(function (arg0) {
const ret = getObject(arg0).next();
return addHeapObject(ret);
}, arguments) };
export function __wbg_done_506b44765ba84b9c(arg0) {
const ret = getObject(arg0).done;
return ret;
};
export function __wbg_value_31485d8770eb06ab(arg0) {
const ret = getObject(arg0).value;
return addHeapObject(ret);
};
export function __wbg_iterator_364187e1ee96b750() {
const ret = Symbol.iterator;
return addHeapObject(ret);
};
export function __wbg_get_5027b32da70f39b1() { return handleError(function (arg0, arg1) {
const ret = Reflect.get(getObject(arg0), getObject(arg1));
return addHeapObject(ret);
}, arguments) };
export function __wbg_call_a79f1973a4f07d5e() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
}, arguments) };
export function __wbg_new_87d841e70661f6e9() {
const ret = new Object();
return addHeapObject(ret);
};
export function __wbg_self_086b5302bcafb962() { return handleError(function () {
const ret = self.self;
return addHeapObject(ret);
}, arguments) };
export function __wbg_window_132fa5d7546f1de5() { return handleError(function () {
const ret = window.window;
return addHeapObject(ret);
}, arguments) };
export function __wbg_globalThis_e5f801a37ad7d07b() { return handleError(function () {
const ret = globalThis.globalThis;
return addHeapObject(ret);
}, arguments) };
export function __wbg_global_f9a61fce4af6b7c1() { return handleError(function () {
const ret = global.global;
return addHeapObject(ret);
}, arguments) };
export function __wbg_set_379b27f1d5f1bf9c(arg0, arg1, arg2) {
getObject(arg0)[arg1 >>> 0] = takeObject(arg2);
};
export function __wbg_isArray_fbd24d447869b527(arg0) {
const ret = Array.isArray(getObject(arg0));
return ret;
};
export function __wbg_instanceof_ArrayBuffer_f4521cec1b99ee35(arg0) {
let result;
try {
result = getObject(arg0) instanceof ArrayBuffer;
} catch (_) {
result = false;
}
const ret = result;
return ret;
};
export function __wbg_call_f6a2bc58c19c53c6() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
export function __wbg_isSafeInteger_d8c89788832a17bf(arg0) {
const ret = Number.isSafeInteger(getObject(arg0));
return ret;
};
export function __wbg_buffer_5d1b598a01b41a42(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
export function __wbg_newwithbyteoffsetandlength_d695c7957788f922(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
export function __wbg_new_ace717933ad7117f(arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
export function __wbg_set_74906aa30864df5a(arg0, arg1, arg2) {
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
};
export function __wbg_length_f0764416ba5bb237(arg0) {
const ret = getObject(arg0).length;
return ret;
};
export function __wbg_instanceof_Uint8Array_4f5cffed7df34b2f(arg0) {
let result;
try {
result = getObject(arg0) instanceof Uint8Array;
} catch (_) {
result = false;
}
const ret = result;
return ret;
};
export function __wbg_newwithlength_728575f3bba9959b(arg0) {
const ret = new Uint8Array(arg0 >>> 0);
return addHeapObject(ret);
};
export function __wbg_subarray_7f7a652672800851(arg0, arg1, arg2) {
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
export function __wbindgen_debug_string(arg0, arg1) {
const ret = debugString(getObject(arg1));
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
export function __wbindgen_throw(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
export function __wbindgen_memory() {
const ret = wasm.memory;
return addHeapObject(ret);
};

BIN
pkg/mp_psi_bg.wasm Normal file

Binary file not shown.

13
pkg/mp_psi_bg.wasm.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function state0_bindgen(): number;
export function state1_bindgen(a: number, b: number, c: number): number;
export function state2_bindgen(a: number, b: number, c: number, d: number, e: number): number;
export function state3_bindgen(a: number, b: number, c: number): number;
export function state4_bindgen(a: number, b: number, c: number): void;
export function __wbindgen_malloc(a: number, b: number): number;
export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function __wbindgen_free(a: number, b: number, c: number): void;
export function __wbindgen_exn_store(a: number): void;

11
pkg/package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "mp-psi",
"version": "0.1.6",
"files": [
"mp_psi_bg.wasm",
"mp_psi.js",
"mp_psi.d.ts"
],
"main": "mp_psi.js",
"types": "mp_psi.d.ts"
}

582
src/lib.rs Normal file
View File

@@ -0,0 +1,582 @@
use bfv::{
BfvParameters, CiphertextProto, CollectiveDecryption, CollectiveDecryptionShare,
CollectiveDecryptionShareProto, CollectivePublicKeyGenerator, CollectivePublicKeyShareProto,
CollectiveRlkAggTrimmedShare1Proto, CollectiveRlkGenerator, CollectiveRlkShare1Proto,
CollectiveRlkShare2Proto, Encoding, EvaluationKey, Evaluator, Plaintext, SecretKey,
SecretKeyProto,
};
use rand::thread_rng;
use serde::{Deserialize, Serialize};
use traits::{
TryDecodingWithParameters, TryEncodingWithParameters, TryFromWithLevelledParameters,
TryFromWithParameters,
};
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
static CRS_PK: [u8; 32] = [0u8; 32];
static CRS_RLK: [u8; 32] = [0u8; 32];
fn params() -> BfvParameters {
let mut params = BfvParameters::new(&[30, 30], 65537, 1 << 11);
params.enable_hybrid_key_switching(&[30]);
params.enable_pke();
params
}
fn convert_to_proto<T, U>(value: &T, parameters: &T::Parameters) -> U
where
T: TryFromWithParameters<Value = U, Parameters = BfvParameters>,
U: TryFromWithParameters<Value = T, Parameters = BfvParameters>,
{
U::try_from_with_parameters(value, parameters)
}
fn convert_from_proto<T, U>(proto: &U, parameters: &U::Parameters) -> T
where
U: TryFromWithParameters<Value = T, Parameters = BfvParameters>,
T: TryFromWithParameters<Value = U, Parameters = BfvParameters>,
{
T::try_from_with_parameters(proto, parameters)
}
#[derive(Serialize, Deserialize)]
struct PrivateOutputAPostState0 {
s_pk_a: SecretKeyProto,
s_rlk_a: SecretKeyProto,
}
#[derive(Serialize, Deserialize)]
struct PublicOutputAPostState0 {
share_pk_a: CollectivePublicKeyShareProto,
share_rlk_a_round1: CollectiveRlkShare1Proto,
}
#[derive(Serialize, Deserialize)]
struct MessageAToBPostState0 {
share_pk_a: CollectivePublicKeyShareProto,
share_rlk_a_round1: CollectiveRlkShare1Proto,
}
#[derive(Serialize, Deserialize)]
struct OutputState0 {
private_output_a: PrivateOutputAPostState0,
public_output_a: PublicOutputAPostState0,
message_a_to_b: MessageAToBPostState0,
}
#[derive(Serialize, Deserialize)]
struct PrivateOutputBPostState1 {
s_pk_b: SecretKeyProto,
}
#[derive(Serialize, Deserialize)]
struct PublicOutputBPostState1 {
ciphertext_b: CiphertextProto,
share_rlk_b_round2: CollectiveRlkShare2Proto,
rlk_agg_round1_h1s: CollectiveRlkAggTrimmedShare1Proto,
}
#[derive(Serialize, Deserialize)]
struct MessageBToAPostState1 {
share_pk_b: CollectivePublicKeyShareProto,
share_rlk_b_round1: CollectiveRlkShare1Proto,
share_rlk_b_round2: CollectiveRlkShare2Proto,
ciphertext_b: CiphertextProto,
}
#[derive(Serialize, Deserialize)]
struct OutputState1 {
private_output_b: PrivateOutputBPostState1,
public_output_b: PublicOutputBPostState1,
message_b_to_a: MessageBToAPostState1,
}
#[derive(Serialize, Deserialize)]
struct PublicOutputAPostState2 {
decryption_share_a: CollectiveDecryptionShareProto,
ciphertext_res: CiphertextProto,
}
#[derive(Serialize, Deserialize)]
struct MessageAToBPostState2 {
decryption_share_a: CollectiveDecryptionShareProto,
ciphertext_a: CiphertextProto,
share_rlk_a_round2: CollectiveRlkShare2Proto,
}
#[derive(Serialize, Deserialize)]
struct OutputState2 {
public_output_a: PublicOutputAPostState2,
message_a_to_b: MessageAToBPostState2,
}
#[derive(Serialize, Deserialize)]
struct MessageBToAPostState3 {
decryption_share_b: CollectiveDecryptionShareProto,
}
#[derive(Serialize, Deserialize)]
struct OutputState3 {
message_b_to_a: MessageBToAPostState3,
psi_output: Vec<u32>,
}
#[wasm_bindgen]
pub fn state0_bindgen() -> JsValue {
let (private_output_a, public_output_a, message_a_to_b) = state0();
let output = OutputState0 {
private_output_a,
public_output_a,
message_a_to_b,
};
serde_wasm_bindgen::to_value(&output).unwrap()
}
fn state0() -> (
PrivateOutputAPostState0,
PublicOutputAPostState0,
MessageAToBPostState0,
) {
let params = params();
let mut rng = thread_rng();
let s_pk_a = SecretKey::random_with_params(&params, &mut rng);
let s_rlk_a = CollectiveRlkGenerator::init_state(&params, &mut rng);
let share_pk_a =
CollectivePublicKeyGenerator::generate_share(&params, &s_pk_a, CRS_PK, &mut rng);
let share_rlk_a_round1 =
CollectiveRlkGenerator::generate_share_1(&params, &s_pk_a, &s_rlk_a, CRS_RLK, 0, &mut rng);
let message_a_to_b = MessageAToBPostState0 {
share_pk_a: convert_to_proto(&share_pk_a, &params),
share_rlk_a_round1: convert_to_proto(&share_rlk_a_round1, &params),
};
let private_output_a = PrivateOutputAPostState0 {
s_pk_a: convert_to_proto(&s_pk_a, &params),
s_rlk_a: convert_to_proto(&s_rlk_a, &params),
};
let public_output_a = PublicOutputAPostState0 {
share_pk_a: convert_to_proto(&share_pk_a, &params),
share_rlk_a_round1: convert_to_proto(&share_rlk_a_round1, &params),
};
(private_output_a, public_output_a, message_a_to_b)
}
#[wasm_bindgen]
pub fn state1_bindgen(message_a_to_b: JsValue, bit_vector: &[u32]) -> JsValue {
let message_a_to_b: MessageAToBPostState0 = serde_wasm_bindgen::from_value(message_a_to_b)
.expect("failed to deserialize message_a_to_b");
let (private_output_b, public_output_b, message_b_to_a) = state1(message_a_to_b, bit_vector);
let output = OutputState1 {
private_output_b,
public_output_b,
message_b_to_a,
};
serde_wasm_bindgen::to_value(&output).unwrap()
}
fn state1(
message_a_to_b: MessageAToBPostState0,
bit_vector: &[u32],
) -> (
PrivateOutputBPostState1,
PublicOutputBPostState1,
MessageBToAPostState1,
) {
let params = params();
let mut rng = thread_rng();
let s_pk_b = SecretKey::random_with_params(&params, &mut rng);
let s_rlk_b = CollectiveRlkGenerator::init_state(&params, &mut rng);
let share_pk_b =
CollectivePublicKeyGenerator::generate_share(&params, &s_pk_b, CRS_PK, &mut rng);
let share_rlk_b_round1 =
CollectiveRlkGenerator::generate_share_1(&params, &s_pk_b, &s_rlk_b, CRS_RLK, 0, &mut rng);
let share_rlk_a_round1 = convert_from_proto(&message_a_to_b.share_rlk_a_round1, &params);
let share_pk_a = convert_from_proto(&message_a_to_b.share_pk_a, &params);
// rlk key part 1
let rlk_shares_round1 = vec![share_rlk_a_round1, share_rlk_b_round1.clone()];
let rlk_agg_1 = CollectiveRlkGenerator::aggregate_shares_1(&params, &rlk_shares_round1, 0);
// B already has access to aggregate shares for rlk round 1 and can proceed with the second round of the protocol
let share_rlk_b_round2 = CollectiveRlkGenerator::generate_share_2(
&params, &s_pk_b, &rlk_agg_1, &s_rlk_b, 0, &mut rng,
);
// generate collective public key and encryt b's input
let collective_pk_shares = vec![share_pk_b.clone(), share_pk_a];
let collecitve_pk = CollectivePublicKeyGenerator::aggregate_shares_and_finalise(
&params,
&collective_pk_shares,
CRS_PK,
);
let pt = Plaintext::try_encoding_with_parameters(bit_vector, &params, Encoding::default());
let ciphertext_b = collecitve_pk.encrypt(&params, &pt, &mut rng);
let message_b_to_a = MessageBToAPostState1 {
share_pk_b: convert_to_proto(&share_pk_b, &params),
share_rlk_b_round1: convert_to_proto(&share_rlk_b_round1, &params),
share_rlk_b_round2: convert_to_proto(&share_rlk_b_round2, &params),
ciphertext_b: convert_to_proto(&ciphertext_b, &params),
};
let private_output_b = PrivateOutputBPostState1 {
s_pk_b: convert_to_proto(&s_pk_b, &params),
};
let rlk_aggregated_shares1_trimmed = rlk_agg_1.trim();
let public_output_b = PublicOutputBPostState1 {
ciphertext_b: convert_to_proto(&ciphertext_b, &params),
share_rlk_b_round2: convert_to_proto(&share_rlk_b_round2, &params),
rlk_agg_round1_h1s: convert_to_proto(&rlk_aggregated_shares1_trimmed, &params),
};
(private_output_b, public_output_b, message_b_to_a)
}
#[wasm_bindgen]
pub fn state2_bindgen(
private_output_a_state0: JsValue,
public_output_a_state0: JsValue,
message_b_to_a: JsValue,
bit_vector: &[u32],
) -> JsValue {
let private_output_a_state0: PrivateOutputAPostState0 =
serde_wasm_bindgen::from_value(private_output_a_state0)
.expect("failed to deserialize private_output_a_state0");
let public_output_a_state0: PublicOutputAPostState0 =
serde_wasm_bindgen::from_value(public_output_a_state0)
.expect("failed to deserialize public_output_a_state0");
let message_b_to_a: MessageBToAPostState1 = serde_wasm_bindgen::from_value(message_b_to_a)
.expect("failed to deserialize message_b_to_a");
let (public_output_a, message_a_to_b) = state2(
private_output_a_state0,
public_output_a_state0,
message_b_to_a,
bit_vector,
);
let output = OutputState2 {
public_output_a,
message_a_to_b,
};
serde_wasm_bindgen::to_value(&output).unwrap()
}
fn state2(
private_output_a_state0: PrivateOutputAPostState0,
public_output_a_state0: PublicOutputAPostState0,
message_b_to_a: MessageBToAPostState1,
bit_vector: &[u32],
) -> (PublicOutputAPostState2, MessageAToBPostState2) {
let params = params();
let mut rng = thread_rng();
// aggrgegate shares of rlk round 1
let rlk_shares_round1 = vec![
convert_from_proto(&public_output_a_state0.share_rlk_a_round1, &params),
convert_from_proto(&message_b_to_a.share_rlk_b_round1, &params),
];
let rlk_agg_1 = CollectiveRlkGenerator::aggregate_shares_1(&params, &rlk_shares_round1, 0);
let s_pk_a = convert_from_proto(&private_output_a_state0.s_pk_a, &params);
let s_rlk_a = convert_from_proto(&private_output_a_state0.s_rlk_a, &params);
// generate share 2 for rlk round 2
let share_rlk_a_round2 = CollectiveRlkGenerator::generate_share_2(
&params, &s_pk_a, &rlk_agg_1, &s_rlk_a, 0, &mut rng,
);
let rlk_agg_1_trimmed = rlk_agg_1.trim();
// aggregate rlk round 2 shares and generate rlk
let rlk_shares_round2 = vec![
share_rlk_a_round2.clone(),
convert_from_proto(&message_b_to_a.share_rlk_b_round2, &params),
];
let rlk = CollectiveRlkGenerator::aggregate_shares_2(
&params,
&rlk_shares_round2,
rlk_agg_1_trimmed,
0,
);
// create public key and encrypt A's bit vector'
let collective_pk_shares = vec![
convert_from_proto(&public_output_a_state0.share_pk_a, &params),
convert_from_proto(&message_b_to_a.share_pk_b, &params),
];
let collective_pk = CollectivePublicKeyGenerator::aggregate_shares_and_finalise(
&params,
&collective_pk_shares,
CRS_PK,
);
let pt = Plaintext::try_encoding_with_parameters(bit_vector, &params, Encoding::default());
let ciphertext_a = collective_pk.encrypt(&params, &pt, &mut rng);
// perform PSI
let evaluator = Evaluator::new(params.clone());
let evaluation_key = EvaluationKey::new_raw(&[0], vec![rlk], &[], &[], vec![]);
let ciphertext_b = convert_from_proto(&message_b_to_a.ciphertext_b, &params);
let ciphertext_res = evaluator.mul(&ciphertext_a, &ciphertext_b);
let ciphertext_res = evaluator.relinearize(&ciphertext_res, &evaluation_key);
// generate decryption share of ciphertext_res
let decryption_share_a = CollectiveDecryption::generate_share(
evaluator.params(),
&ciphertext_res,
&convert_from_proto(&private_output_a_state0.s_pk_a, &params),
&mut rng,
);
let decryption_share_a = CollectiveDecryptionShareProto::try_from_with_levelled_parameters(
&decryption_share_a,
&params,
0,
);
let public_output_a = PublicOutputAPostState2 {
decryption_share_a: decryption_share_a.clone(),
ciphertext_res: convert_to_proto(&ciphertext_res, &params),
};
let message_a_to_b = MessageAToBPostState2 {
decryption_share_a,
ciphertext_a: convert_to_proto(&ciphertext_a, &params),
share_rlk_a_round2: convert_to_proto(&share_rlk_a_round2, &params),
};
(public_output_a, message_a_to_b)
}
#[wasm_bindgen]
pub fn state3_bindgen(
private_output_b_state1: JsValue,
public_output_b_state1: JsValue,
message_a_to_b: JsValue,
) -> JsValue {
let private_output_b_state1: PrivateOutputBPostState1 =
serde_wasm_bindgen::from_value(private_output_b_state1)
.expect("failed to deserialize private_output_b_state1");
let public_output_b_state1: PublicOutputBPostState1 =
serde_wasm_bindgen::from_value(public_output_b_state1)
.expect("failed to deserialize public_output_b_state1");
let message_a_to_b: MessageAToBPostState2 = serde_wasm_bindgen::from_value(message_a_to_b)
.expect("failed to deserialize message_a_to_b");
let (message_b_to_a, psi_output) = state3(
private_output_b_state1,
public_output_b_state1,
message_a_to_b,
);
let output = OutputState3 {
message_b_to_a,
psi_output,
};
serde_wasm_bindgen::to_value(&output).unwrap()
}
fn state3(
private_output_b_state1: PrivateOutputBPostState1,
public_output_b_state1: PublicOutputBPostState1,
message_a_to_b: MessageAToBPostState2,
) -> (MessageBToAPostState3, Vec<u32>) {
let params = params();
let mut rng = thread_rng();
// create rlk
let rlk_shares_round2 = vec![
convert_from_proto(&message_a_to_b.share_rlk_a_round2, &params),
convert_from_proto(&public_output_b_state1.share_rlk_b_round2, &params),
];
let rlk_agg_round1_h1s =
convert_from_proto(&public_output_b_state1.rlk_agg_round1_h1s, &params);
let rlk = CollectiveRlkGenerator::aggregate_shares_2(
&params,
&rlk_shares_round2,
rlk_agg_round1_h1s,
0,
);
// perform PSI
let evaluator = Evaluator::new(params.clone());
let evaluation_key = EvaluationKey::new_raw(&[0], vec![rlk], &[], &[], vec![]);
let ciphertext_a = convert_from_proto(&message_a_to_b.ciphertext_a, &params);
let ciphertext_b = convert_from_proto(&public_output_b_state1.ciphertext_b, &params);
let ciphertext_res = evaluator.mul(&ciphertext_a, &ciphertext_b);
let ciphertext_res = evaluator.relinearize(&ciphertext_res, &evaluation_key);
let s_pk_b = convert_from_proto(&private_output_b_state1.s_pk_b, &params);
// generate B's decryption share
let decryption_share_b = CollectiveDecryption::generate_share(
evaluator.params(),
&ciphertext_res,
&s_pk_b,
&mut rng,
);
// decrypt ciphertext res
let decryption_shares_vec = vec![
decryption_share_b.clone(),
CollectiveDecryptionShare::try_from_with_levelled_parameters(
&message_a_to_b.decryption_share_a,
&params,
0,
),
];
let psi_output = CollectiveDecryption::aggregate_share_and_decrypt(
evaluator.params(),
&ciphertext_res,
&decryption_shares_vec,
);
let psi_output = Vec::<u32>::try_decoding_with_parameters(
&psi_output,
evaluator.params(),
Encoding::default(),
);
let message_b_to_a = MessageBToAPostState3 {
decryption_share_b: CollectiveDecryptionShareProto::try_from_with_levelled_parameters(
&decryption_share_b,
&params,
0,
),
};
(message_b_to_a, psi_output)
}
#[wasm_bindgen]
pub fn state4_bindgen(public_output_a_state2: JsValue, message_b_to_a: JsValue) -> Vec<u32> {
let public_output_a_state2: PublicOutputAPostState2 =
serde_wasm_bindgen::from_value(public_output_a_state2)
.expect("failed to deserialize public_output_a_state2");
let message_b_to_a: MessageBToAPostState3 = serde_wasm_bindgen::from_value(message_b_to_a)
.expect("failed to deserialize message_b_to_a");
let psi_output = state4(public_output_a_state2, message_b_to_a);
psi_output
}
fn state4(
public_output_a_state2: PublicOutputAPostState2,
message_b_to_a: MessageBToAPostState3,
) -> Vec<u32> {
let params = params();
// decrypt ciphertext res
let decryption_shares_vec = vec![
CollectiveDecryptionShare::try_from_with_levelled_parameters(
&public_output_a_state2.decryption_share_a,
&params,
0,
),
CollectiveDecryptionShare::try_from_with_levelled_parameters(
&message_b_to_a.decryption_share_b,
&params,
0,
),
];
let ciphertext_res = convert_from_proto(&public_output_a_state2.ciphertext_res, &params);
let psi_output = CollectiveDecryption::aggregate_share_and_decrypt(
&params,
&ciphertext_res,
&decryption_shares_vec,
);
let psi_output =
Vec::<u32>::try_decoding_with_parameters(&psi_output, &params, Encoding::default());
psi_output
}
#[cfg(test)]
mod tests {
use super::*;
use itertools::{izip, Itertools};
use rand::{distributions::Uniform, Rng};
fn random_bit_vector(hamming_weight: usize, size: usize) -> Vec<u32> {
let mut rng = thread_rng();
let mut bit_vector = vec![0; size];
(0..hamming_weight).into_iter().for_each(|_| {
let sample_index = rng.sample(Uniform::new(0, size));
bit_vector[sample_index] = 1;
});
bit_vector
}
fn plain_psi(bit_vector0: &[u32], bit_vector_1: &[u32]) -> Vec<u32> {
izip!(bit_vector0.iter(), bit_vector_1.iter())
.map(|(b0, b1)| b0 * b1)
.collect_vec()
}
#[test]
fn psi_works() {
let hamming_weight = 10;
let vector_size = 10;
// A: state 0
let (private_output_a_state0, public_output_a_state0, message_a_to_b_state0) = state0();
// B: state 1
let bit_vector_b = random_bit_vector(hamming_weight, vector_size);
let (private_output_b_state1, public_output_b_state1, message_b_to_a_state1) =
state1(message_a_to_b_state0, &bit_vector_b);
// A: state 2
let bit_vector_a = random_bit_vector(hamming_weight, vector_size);
let (public_output_a_state2, message_a_to_b_state2) = state2(
private_output_a_state0,
public_output_a_state0,
message_b_to_a_state1,
&bit_vector_a,
);
// B: state 3
let (message_b_to_a_state3, psi_output_b) = state3(
private_output_b_state1,
public_output_b_state1,
message_a_to_b_state2,
);
// A: state 4
let psi_output_a = state4(public_output_a_state2, message_b_to_a_state3);
let expected_psi_output = plain_psi(&bit_vector_a, &bit_vector_b);
assert_eq!(expected_psi_output, psi_output_a[..vector_size]);
assert_eq!(psi_output_a, psi_output_b);
}
}

View File

@@ -1,159 +1 @@
use bfv::{
BfvParameters, CollectiveDecryption, CollectivePublicKeyGenerator, CollectiveRlkGenerator,
Encoding, EvaluationKey, Evaluator, PartySecret, Plaintext, Poly, PublicKey, SecretKey,
};
use itertools::{izip, Itertools};
use rand::{distributions::Uniform, thread_rng, Rng};
struct Party {
secret: SecretKey,
bit_vector: Vec<u64>,
}
impl Party {
fn random(params: &BfvParameters, hamming_weight: usize) -> Party {
let mut rng = thread_rng();
let secret = SecretKey::random_with_params(params, &mut rng);
let mut bit_vector = vec![0; params.degree];
(0..hamming_weight).into_iter().for_each(|_| {
let sample_index = rng.sample(Uniform::new(0, params.degree));
bit_vector[sample_index] = 1;
});
Party { secret, bit_vector }
}
}
fn plain_psi(parties: &[Party]) -> Vec<u64> {
let mut common = parties[0].bit_vector.clone();
parties.iter().skip(1).for_each(|party_i| {
izip!(common.iter_mut(), party_i.bit_vector.iter()).for_each(|(b_out, b_in)| {
*b_out *= b_in;
});
});
common
}
fn main() {
let mut params = BfvParameters::new(&[50, 50, 50], 65537, 1 << 15);
params.enable_hybrid_key_switching(&[50, 50]);
params.enable_pke();
let hw = 21000;
let parties = vec![Party::random(&params, hw), Party::random(&params, hw)];
// Collective public key generation //
let crs = [0u8; 32];
let mut rng = thread_rng();
// Each party generates their share
let shares = parties
.iter()
.map(|party_i| {
CollectivePublicKeyGenerator::generate_share(&params, &party_i.secret, crs, &mut rng)
})
.collect::<Vec<Poly>>();
// After each party has broadcasted their share, any one can generate public key
let public_key =
CollectivePublicKeyGenerator::aggregate_shares_and_finalise(&params, &shares, crs);
// Collective relinearization key generation //
// This is a 2 round protocol
let crs = [0u8; 32];
let level = 0;
// Each party generates a ephemeral state
let parties_state = parties
.iter()
.map(|_| CollectiveRlkGenerator::init_state(&params, &mut rng))
.collect_vec();
// Each party generates share1
let mut share1s_part0 = vec![];
let mut share1s_part1 = vec![];
izip!(parties.iter(), parties_state.iter()).for_each(|(party_i, internal_state_i)| {
// Party i brodcasts `part0` and `part1`
let (part0, part1) = CollectiveRlkGenerator::generate_share_1(
&params,
&party_i.secret,
internal_state_i,
crs,
level,
&mut rng,
);
share1s_part0.push(part0);
share1s_part1.push(part1);
});
// After each party has broadcasted their share1, each party proceeds to aggregate share1s and generate their share2.
let (share1s_part0_agg, share1s_part1_agg) =
CollectiveRlkGenerator::aggregate_shares_1(&params, &share1s_part0, &share1s_part1, level);
// Round 2
// Each party generates share2
let mut share2s_part0 = vec![];
let mut share2s_part1 = vec![];
izip!(parties.iter(), parties_state.iter()).for_each(|(party_i, internal_state_i)| {
// Party i brodcasts `part0` and `part1`
let (part0, part1) = CollectiveRlkGenerator::generate_share_2(
&params,
&party_i.secret,
&share1s_part0_agg,
&share1s_part1_agg,
internal_state_i,
level,
&mut rng,
);
share2s_part0.push(part0);
share2s_part1.push(part1);
});
// Each party broadcasts their share2, after which they aggregate the received shares and finalise the protocol
let rlk = CollectiveRlkGenerator::aggregate_shares_2(
&params,
&share2s_part0,
&share2s_part1,
share1s_part1_agg,
level,
);
// PSI //
// Two users use the public key to encryt their `bit_vector`s. Note that unless the two users come together to collecticely decrypt, their inputs stay private.
// Party 1
let pt1 = Plaintext::encode(&parties[0].bit_vector, &params, Encoding::default());
let ct1 = public_key.encrypt(&params, &pt1, &mut rng);
// Party 2
let pt2 = Plaintext::encode(&parties[1].bit_vector, &params, Encoding::default());
let ct2 = public_key.encrypt(&params, &pt2, &mut rng);
// Each party sends their ciphertext to the other party and both of them evaluate the FHE circuit (FHE circuit is simple ciphertext multiplication)
let evaluation_key = EvaluationKey::new_raw(&[level], vec![rlk], &[], &[], vec![]);
let evaluator = Evaluator::new(params);
let ct1ct2 = evaluator.mul(&ct1, &ct2);
let psi_ct = evaluator.relinearize(&ct1ct2, &evaluation_key);
// Collective decryption //
// Each party can independently generate their share to decrypt `psi_ct`. Unless the other party has evaluated the FHE circuit maliciously, they should be able to decrypt `psi_ct` after receiving other party's share.
// As it is often the case in MPC, the last party to send their share has leverage to not send the share and prevent the other party from learning PSI output.
let party1_share = CollectiveDecryption::generate_share(
evaluator.params(),
&psi_ct,
&parties[0].secret,
&mut rng,
);
let party2_share = CollectiveDecryption::generate_share(
&evaluator.params(),
&psi_ct,
&parties[1].secret,
&mut rng,
);
// With shares from party1 and party2, one can decrypt the ciphertext
let psi_output_pt = CollectiveDecryption::aggregate_share_and_decrypt(
evaluator.params(),
&psi_ct,
&[party1_share, party2_share],
);
let psi_output: Vec<u64> = psi_output_pt.decode(Encoding::default(), evaluator.params());
let expected_outpout = plain_psi(&parties);
assert_eq!(psi_output, expected_outpout);
}
fn main() {}