From db65fe239ded2348c467b04f7231ec6e24351db7 Mon Sep 17 00:00:00 2001 From: Florent Michel Date: Mon, 16 Mar 2026 15:52:01 +0000 Subject: [PATCH 1/6] bump TFHE-rs version to 1.5.4 --- measurements/single/results-1.json | 20 ++++++++++---------- measurements/single/results.json | 18 ++++++++++++++++++ submission/Cargo.toml | 2 +- 3 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 measurements/single/results.json diff --git a/measurements/single/results-1.json b/measurements/single/results-1.json index dd74823..aaa6796 100644 --- a/measurements/single/results-1.json +++ b/measurements/single/results-1.json @@ -1,17 +1,17 @@ { "Timing": { - "Input generation": "0.1273s", - "Input preprocessing": "0.0008s", - "Key Generation": "0.7905s", - "Input encryption": "0.0122s", - "Encrypted computation": "1.4031s", - "Result decryption": "0.0026s", - "Result postprocessing": "0.0006s", - "Total": "2.3371s" + "Input generation": "0.083s", + "Input preprocessing": "0.0009s", + "Key Generation": "0.7183s", + "Input encryption": "0.0173s", + "Encrypted computation": "3.7988s", + "Result decryption": "0.0029s", + "Result postprocessing": "0.0008s", + "Total": "4.622s" }, "Bandwidth": { - "Public and evaluation keys": "125.0M", + "Public and evaluation keys": "114.8M", "Encrypted input": "1.0M", - "Encrypted results": "514.4K" + "Encrypted results": "514.5K" } } \ No newline at end of file diff --git a/measurements/single/results.json b/measurements/single/results.json new file mode 100644 index 0000000..40b1012 --- /dev/null +++ b/measurements/single/results.json @@ -0,0 +1,18 @@ +{ + "total_latency_s": 4.4112, + "per_stage": { + "Dataset generation": "0.1095s", + "Client: Key Generation": "0.7331s", + "Client: Input preprocessing": "0.002s", + "Client: Encryption": "0.0079s", + "Server: Homomorphic mul": "3.553s", + "Client: Result decryption": "0.0028s", + "Client: Result postprocessing": "0.0011s", + "Checking results": "0.002s" + }, + "bandwidth": { + "Public and evaluation keys": "125.0M", + "Client: encrypted inputs": "1.0M", + "Client: encrypted results": "514.4K" + } +} \ No newline at end of file diff --git a/submission/Cargo.toml b/submission/Cargo.toml index 62d8ca3..a78b751 100644 --- a/submission/Cargo.toml +++ b/submission/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] bincode = "1.3" serde = "1" -tfhe = { version = "~1.1.3", features = ["integer"] } +tfhe = { version = "1.5.4", features = ["integer"] } rand = { version = "0.9.1" } [[bin]] From dfe031dde5425a2a2b63101ad4fde7c3b94ad526 Mon Sep 17 00:00:00 2001 From: Florent Michel Date: Mon, 16 Mar 2026 16:01:49 +0000 Subject: [PATCH 2/6] add a paragraph on parameters --- submission/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/submission/README.md b/submission/README.md index cc573cb..b112fc1 100644 --- a/submission/README.md +++ b/submission/README.md @@ -2,6 +2,12 @@ This is a reference implementation for the 64-bits multiplication workload, written in [Rust](https://rust-lang.org/) and using the [TFHE-rs](https://docs.zama.org/tfhe-rs) library. +## Security and Parameters + +The reference implementation uses the default parameter set of TFHE-rs, version 1.5.4. According to the [the TFHE-rs documentation](https://docs.zama.org/tfhe-rs/1.5/get-started/security-and-cryptography#security), these parameters provide 128 bits of security in the IND-CPA-D model: +* The lowest attack cost as estimated by the [Lattice Estimator](https://github.com/malb/lattice-estimator) is above $2^{128}$. +* The probability of decryption failure after a programmable bootstrap using the [drift reduction technique](https://eprint.iacr.org/2024/1718.pdf) is below $2^{-128}$. + ## Build and run Building the workflow requires the [Rust toolchain](https://rust-lang.org/tools/install/). From ee59cc2d2da20c1c2ca83e94990b5f1b61b2dbe6 Mon Sep 17 00:00:00 2001 From: Florent Michel Date: Mon, 16 Mar 2026 16:06:06 +0000 Subject: [PATCH 3/6] correct a typo --- submission/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submission/README.md b/submission/README.md index b112fc1..8bb49a1 100644 --- a/submission/README.md +++ b/submission/README.md @@ -4,7 +4,7 @@ This is a reference implementation for the 64-bits multiplication workload, writ ## Security and Parameters -The reference implementation uses the default parameter set of TFHE-rs, version 1.5.4. According to the [the TFHE-rs documentation](https://docs.zama.org/tfhe-rs/1.5/get-started/security-and-cryptography#security), these parameters provide 128 bits of security in the IND-CPA-D model: +The reference implementation uses the default parameter set of TFHE-rs, version 1.5.4. According to the [TFHE-rs documentation](https://docs.zama.org/tfhe-rs/1.5/get-started/security-and-cryptography#security), these parameters provide 128 bits of security in the IND-CPA-D model: * The lowest attack cost as estimated by the [Lattice Estimator](https://github.com/malb/lattice-estimator) is above $2^{128}$. * The probability of decryption failure after a programmable bootstrap using the [drift reduction technique](https://eprint.iacr.org/2024/1718.pdf) is below $2^{-128}$. From b5fbc671270c83a88dd84d59c3da3b65c376fce9 Mon Sep 17 00:00:00 2001 From: Florent Michel Date: Tue, 31 Mar 2026 10:41:08 +0100 Subject: [PATCH 4/6] revert tfhe-rs version --- measurements/single/results-1.json | 22 +++++++++++----------- submission/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/measurements/single/results-1.json b/measurements/single/results-1.json index aaa6796..89b5a10 100644 --- a/measurements/single/results-1.json +++ b/measurements/single/results-1.json @@ -1,17 +1,17 @@ { "Timing": { - "Input generation": "0.083s", - "Input preprocessing": "0.0009s", - "Key Generation": "0.7183s", - "Input encryption": "0.0173s", - "Encrypted computation": "3.7988s", - "Result decryption": "0.0029s", - "Result postprocessing": "0.0008s", - "Total": "4.622s" + "Input generation": "0.1273s", + "Input preprocessing": "0.0008s", + "Key Generation": "0.7905s", + "Input encryption": "0.0122s", + "Encrypted computation": "1.4031s", + "Result decryption": "0.0026s", + "Result postprocessing": "0.0006s", + "Total": "2.3371s" }, "Bandwidth": { - "Public and evaluation keys": "114.8M", + "Public and evaluation keys": "125.0M", "Encrypted input": "1.0M", - "Encrypted results": "514.5K" + "Encrypted results": "514.4K" } -} \ No newline at end of file +} diff --git a/submission/Cargo.toml b/submission/Cargo.toml index a78b751..62d8ca3 100644 --- a/submission/Cargo.toml +++ b/submission/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] bincode = "1.3" serde = "1" -tfhe = { version = "1.5.4", features = ["integer"] } +tfhe = { version = "~1.1.3", features = ["integer"] } rand = { version = "0.9.1" } [[bin]] From 572b669a7a6f52e06a56f89fb6693716b9d4cb3b Mon Sep 17 00:00:00 2001 From: Florent Michel Date: Tue, 31 Mar 2026 12:16:25 +0100 Subject: [PATCH 5/6] Bump TFHE-rs version and compress the server key and inputs --- measurements/single/results-1.json | 24 +++++++++---------- submission/Cargo.toml | 2 +- .../src/bin/client_encode_encrypt_input.rs | 6 ++--- submission/src/bin/client_key_generation.rs | 7 +++--- .../src/bin/server_encrypted_compute.rs | 15 ++++++------ 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/measurements/single/results-1.json b/measurements/single/results-1.json index 89b5a10..9c7811b 100644 --- a/measurements/single/results-1.json +++ b/measurements/single/results-1.json @@ -1,17 +1,17 @@ { "Timing": { - "Input generation": "0.1273s", - "Input preprocessing": "0.0008s", - "Key Generation": "0.7905s", - "Input encryption": "0.0122s", - "Encrypted computation": "1.4031s", - "Result decryption": "0.0026s", - "Result postprocessing": "0.0006s", - "Total": "2.3371s" + "Input generation": "0.0922s", + "Input preprocessing": "0.0012s", + "Key Generation": "1.0345s", + "Input encryption": "0.0114s", + "Encrypted computation": "3.798s", + "Result decryption": "0.0027s", + "Result postprocessing": "0.0008s", + "Total": "4.9409s" }, "Bandwidth": { - "Public and evaluation keys": "125.0M", - "Encrypted input": "1.0M", - "Encrypted results": "514.4K" + "Public and evaluation keys": "28.8M", + "Encrypted input": "6.0K", + "Encrypted results": "514.5K" } -} +} \ No newline at end of file diff --git a/submission/Cargo.toml b/submission/Cargo.toml index 62d8ca3..a78b751 100644 --- a/submission/Cargo.toml +++ b/submission/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] bincode = "1.3" serde = "1" -tfhe = { version = "~1.1.3", features = ["integer"] } +tfhe = { version = "1.5.4", features = ["integer"] } rand = { version = "0.9.1" } [[bin]] diff --git a/submission/src/bin/client_encode_encrypt_input.rs b/submission/src/bin/client_encode_encrypt_input.rs index 47256aa..9d78160 100644 --- a/submission/src/bin/client_encode_encrypt_input.rs +++ b/submission/src/bin/client_encode_encrypt_input.rs @@ -8,7 +8,7 @@ use std::env; use std::path::Path; use std::fs; -use tfhe::{ClientKey, FheUint64}; +use tfhe::{ClientKey, CompressedFheUint64}; use tfhe::prelude::*; use zn_multiplication::utils::*; @@ -32,7 +32,7 @@ pub fn main() -> Result<(), Box> { let rhs_cleartext: Vec = read_numbers_from_file(Path::new(&("datasets/".to_owned() + &size + "/rhs.txt")))?; // Encode and encrypt the LHS - let lhs_ciphers = lhs_cleartext.into_iter().map(|m| FheUint64::encrypt(m, &lwe_sk)); + let lhs_ciphers = lhs_cleartext.into_iter().map(|m| CompressedFheUint64::encrypt(m, &lwe_sk)); // Write the LHS let ciphertexts_dir = io_dir.clone() + "/ciphertexts_upload"; @@ -44,7 +44,7 @@ pub fn main() -> Result<(), Box> { } // Encode and encrypt the RHS - let rhs_ciphers = rhs_cleartext.into_iter().map(|m| FheUint64::encrypt(m, &lwe_sk)); + let rhs_ciphers = rhs_cleartext.into_iter().map(|m| CompressedFheUint64::encrypt(m, &lwe_sk)); // Write the RHS for (i, cipher) in rhs_ciphers.enumerate() { diff --git a/submission/src/bin/client_key_generation.rs b/submission/src/bin/client_key_generation.rs index 20290c9..45c9fad 100644 --- a/submission/src/bin/client_key_generation.rs +++ b/submission/src/bin/client_key_generation.rs @@ -6,7 +6,7 @@ use std::env; use std::fs; -use tfhe::{ConfigBuilder, generate_keys}; +use tfhe::{CompressedServerKey, ConfigBuilder, generate_keys}; pub fn main() -> Result<(), Box> { let args: Vec = env::args().collect(); @@ -19,7 +19,7 @@ pub fn main() -> Result<(), Box> { // Generate the keys let config = ConfigBuilder::default().build(); - let (client_key, server_key) = generate_keys(config); + let (client_key, _) = generate_keys(config); // Serialize and save the secret key let serialised_data = bincode::serialize(&client_key)?; @@ -27,7 +27,8 @@ pub fn main() -> Result<(), Box> { fs::write(io_dir.clone() + "/private_keys/sk.bin", &serialised_data)?; // Serialize and save the public key - let serialised_data = bincode::serialize(&server_key)?; + let compressed_server_key = CompressedServerKey::new(&client_key); + let serialised_data = bincode::serialize(&compressed_server_key)?; fs::create_dir(io_dir.clone() + "/public_keys")?; fs::write(io_dir.clone() + "/public_keys/pk.bin", &serialised_data)?; diff --git a/submission/src/bin/server_encrypted_compute.rs b/submission/src/bin/server_encrypted_compute.rs index 78f8d92..1dc6acc 100644 --- a/submission/src/bin/server_encrypted_compute.rs +++ b/submission/src/bin/server_encrypted_compute.rs @@ -8,7 +8,7 @@ use std::env; use std::path::Path; use std::fs; -use tfhe::{ FheUint64, set_server_key, ServerKey }; +use tfhe::{ CompressedFheUint64, CompressedServerKey, FheUint64, set_server_key }; use zn_multiplication::half_cipher_cipher_mul_64; @@ -25,23 +25,24 @@ pub fn main() -> Result<(), Box> { // Load the server key let serialised_data = fs::read(io_dir.clone() + "/public_keys/pk.bin")?; - let server_key: ServerKey = bincode::deserialize(&serialised_data)?; + let compressed_server_key: CompressedServerKey = bincode::deserialize(&serialised_data)?; + let server_key = compressed_server_key.decompress(); set_server_key(server_key); // Load the LHS input ciphers let ciphertexts_in_dir = io_dir.clone() + "/ciphertexts_upload"; let ciphers_lhs = (0 .. data_size).map(|i| - bincode::deserialize::(&fs::read(ciphertexts_in_dir.clone() + "/cipher_lhs_" + &i.to_string() + ".bin")?) - ).collect::, Box>>()?; + bincode::deserialize::(&fs::read(ciphertexts_in_dir.clone() + "/cipher_lhs_" + &i.to_string() + ".bin")?) + ).collect::, Box>>()?; // Load the RHS input ciphers let ciphers_rhs = (0 .. data_size).map(|i| - bincode::deserialize::(&fs::read(ciphertexts_in_dir.clone() + "/cipher_rhs_" + &i.to_string() + ".bin")?) - ).collect::, Box>>()?; + bincode::deserialize::(&fs::read(ciphertexts_in_dir.clone() + "/cipher_rhs_" + &i.to_string() + ".bin")?) + ).collect::, Box>>()?; // Run the homomorphic multiplications let ciphers_out = ciphers_lhs.iter().zip(ciphers_rhs.iter()) - .map(|(lhs, rhs)| half_cipher_cipher_mul_64(lhs, rhs)) + .map(|(lhs, rhs)| half_cipher_cipher_mul_64(&lhs.decompress(), &rhs.decompress())) .collect::>(); // Write the results From 896f2efa712b449f691f6b5de87c1c43b5cc15c8 Mon Sep 17 00:00:00 2001 From: Florent Michel Date: Thu, 2 Apr 2026 08:58:18 +0100 Subject: [PATCH 6/6] delete results.json --- measurements/single/results.json | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 measurements/single/results.json diff --git a/measurements/single/results.json b/measurements/single/results.json deleted file mode 100644 index 40b1012..0000000 --- a/measurements/single/results.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "total_latency_s": 4.4112, - "per_stage": { - "Dataset generation": "0.1095s", - "Client: Key Generation": "0.7331s", - "Client: Input preprocessing": "0.002s", - "Client: Encryption": "0.0079s", - "Server: Homomorphic mul": "3.553s", - "Client: Result decryption": "0.0028s", - "Client: Result postprocessing": "0.0011s", - "Checking results": "0.002s" - }, - "bandwidth": { - "Public and evaluation keys": "125.0M", - "Client: encrypted inputs": "1.0M", - "Client: encrypted results": "514.4K" - } -} \ No newline at end of file