mirror of
https://github.com/cursive-team/2P-PSI.git
synced 2026-01-09 12:07:54 -05:00
add prototype
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
359
Cargo.lock
generated
Normal file
359
Cargo.lock
generated
Normal file
@@ -0,0 +1,359 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aligned-vec"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bfv"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Janmajayamall/bfv?branch=pk#34090532ce04ee6c143753edab11f902c057837c"
|
||||
dependencies = [
|
||||
"concrete-ntt",
|
||||
"crypto-bigint",
|
||||
"itertools",
|
||||
"ndarray",
|
||||
"num-bigint",
|
||||
"num-bigint-dig",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
"seq-macro",
|
||||
"traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "concrete-ntt"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1167c583765f273205c691a0a8bff23a925aa5bc66f2448031e4a6e518cd64d7"
|
||||
dependencies = [
|
||||
"aligned-vec",
|
||||
"pulp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp-psi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bfv",
|
||||
"itertools",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"libm",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"serde",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulp"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "866e8018d6397b0717100dd4a7948fc8cbc8c4b8ce3e39e98a0e1e878d3ba925"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "seq-macro"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "traits"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Janmajayamall/bfv?branch=pk#34090532ce04ee6c143753edab11f902c057837c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "mp-psi"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bfv = {git = "https://github.com/Janmajayamall/bfv", branch = "pk"}
|
||||
rand = "0.8.5"
|
||||
itertools = "0.10.5"
|
||||
159
src/main.rs
Normal file
159
src/main.rs
Normal file
@@ -0,0 +1,159 @@
|
||||
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(¶ms, hw), Party::random(¶ms, 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(¶ms, &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(¶ms, &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(¶ms, &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(
|
||||
¶ms,
|
||||
&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(¶ms, &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(
|
||||
¶ms,
|
||||
&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(
|
||||
¶ms,
|
||||
&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, ¶ms, Encoding::default());
|
||||
let ct1 = public_key.encrypt(¶ms, &pt1, &mut rng);
|
||||
|
||||
// Party 2
|
||||
let pt2 = Plaintext::encode(&parties[1].bit_vector, ¶ms, Encoding::default());
|
||||
let ct2 = public_key.encrypt(¶ms, &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);
|
||||
}
|
||||
Reference in New Issue
Block a user