### Install and Initialize Rust Project with Cargo Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/getting-started/quick-start.md Demonstrates using Cargo, the Rust build and package manager, to verify the installation and create a new binary application project. This is the first step in setting up a Rust environment for TFHE-rs. ```console $ cargo --version cargo 1.81.0 (2dbb1af80 2024-08-20) $ cargo new tfhe-example Creating binary (application) `tfhe-example` package note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html ``` -------------------------------- ### High-Level API Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/references/fine-grained-apis/quick-start.md Demonstrates the high-level API for homomorphic addition of unsigned 8-bit integers. It covers key generation, encryption, homomorphic addition using overloaded operators, and decryption. This example requires running with the `--release` flag. ```rust use tfhe::{ConfigBuilder, generate_keys, set_server_key, FheUint8}; use tfhe::prelude::*; fn main() { let config = ConfigBuilder::default() .build(); let (client_key, server_key) = generate_keys(config); set_server_key(server_key); let clear_a = 27u8; let clear_b = 128u8; let a = FheUint8::encrypt(clear_a, &client_key); let b = FheUint8::encrypt(clear_b, &client_key); let result = a + b; let decrypted_result: u8 = result.decrypt(&client_key); let clear_result = clear_a + clear_b; assert_eq!(decrypted_result, clear_result); } ``` -------------------------------- ### TFHE-rs High-Level API Usage Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/getting-started/quick-start.md A complete Rust code example demonstrating the TFHE-rs high-level API workflow. It covers key generation, encrypting two `FheUint8` values, performing homomorphic addition on the server-side, and decrypting the result back on the client-side, with an assertion to verify correctness. ```rust use tfhe::{ConfigBuilder, generate_keys, set_server_key, FheUint8}; use tfhe::prelude::*; fn main() { let config = ConfigBuilder::default().build(); // Client-side let (client_key, server_key) = generate_keys(config); let clear_a = 27u8; let clear_b = 128u8; let a = FheUint8::encrypt(clear_a, &client_key); let b = FheUint8::encrypt(clear_b, &client_key); //Server-side set_server_key(server_key); let result = a + b; //Client-side let decrypted_result: u8 = result.decrypt(&client_key); let clear_result = clear_a + clear_b; assert_eq!(decrypted_result, clear_result); } ``` -------------------------------- ### Shortint Arithmetic Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/references/fine-grained-apis/quick-start.md Provides an example of performing homomorphic addition with short integers using the `tfhe::shortint` module. It demonstrates key generation with specific parameters (2 bits message, 2 bits carry), encrypting integer messages, executing homomorphic addition on ciphertexts, and decrypting the result. This example requires running with the `--release` flag. ```rust use tfhe::shortint::prelude::*; fn main() { // We generate a set of client/server keys // using parameters with 2 bits of message and 2 bits of carry let (client_key, server_key) = gen_keys(PARAM_MESSAGE_2_CARRY_2); let msg1 = 1; let msg2 = 0; let modulus = client_key.parameters().message_modulus().0; // We use the client key to encrypt two messages: let ct_1 = client_key.encrypt(msg1); let ct_2 = client_key.encrypt(msg2); // We use the server public key to execute an integer circuit: let ct_3 = server_key.add(&ct_1, &ct_2); // We use the client key to decrypt the output of the circuit: let output = client_key.decrypt(&ct_3); assert_eq!(output, (msg1 + msg2) % modulus); } ``` -------------------------------- ### Boolean Circuit Evaluation Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/references/fine-grained-apis/quick-start.md Illustrates evaluating a Boolean circuit using the `tfhe::boolean` module. It shows how to encrypt boolean values, perform logical operations (NOT, AND, NAND, MUX) on ciphertexts using the server key, and decrypt the final result. This example requires running with the `--release` flag. ```rust use tfhe::boolean::prelude::*; fn main() { // We generate a set of client/server keys, using the default parameters: let (client_key, server_key) = gen_keys(); // We use the client secret key to encrypt two messages: let ct_1 = client_key.encrypt(true); let ct_2 = client_key.encrypt(false); // We use the server public key to execute a boolean circuit: // if ((NOT ct_2) NAND (ct_1 AND ct_2)) then (NOT ct_2) else (ct_1 AND ct_2) let ct_3 = server_key.not(&ct_2); let ct_4 = server_key.and(&ct_1, &ct_2); let ct_5 = server_key.nand(&ct_3, &ct_4); let ct_6 = server_key.mux(&ct_5, &ct_3, &ct_4); // We use the client key to decrypt the output of the circuit: let output = client_key.decrypt(&ct_6); assert!(output); } ``` -------------------------------- ### Full HPU Acceleration Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/configuration/hpu-acceleration/run-on-hpu.md A complete Rust program demonstrating the setup and usage of the TFHE-rs HPU backend. It covers device instantiation, key generation, encryption, homomorphic addition, and decryption. ```rust use tfhe::{Config, set_server_key, FheUint8, ClientKey, CompressedServerKey}; use tfhe::prelude::*; use tfhe::tfhe_hpu_backend::prelude::*; fn main() { // Instantiate HpuDevice -------------------------------------------------- // HPU configuration knobs are retrieved from a TOML configuration file. Prebuilt configurations could be find in `backends/tfhe-hpu-backend/config_store` // For ease of use a setup_hpu.sh script is available in repository root folder and it handle the required environment variables setup and driver initialisation // More details are available in `backends/tfhe-hpu-backend/README.md` let hpu_device = HpuDevice::from_config(ShellString::new("${HPU_BACKEND_DIR}/config_store/${HPU_CONFIG}/hpu_config.toml".to_string()).expand().as_str()); // Generate keys ---------------------------------------------------------- let config = Config::from_hpu_device(&hpu_device); let client_key = ClientKey::generate(config); let compressed_server_key = CompressedServerKey::new(&client_key); // Register HpuDevice and key as thread-local engine set_server_key((hpu_device, compressed_server_key)); let clear_a = 27u8; let clear_b = 128u8; let a = FheUint8::encrypt(clear_a, &client_key); let b = FheUint8::encrypt(clear_b, &client_key); // Server-side computation let result = a + b; // Client-side let decrypted_result: u8 = result.decrypt(&client_key); let clear_result = clear_a + clear_b; assert_eq!(decrypted_result, clear_result); } ``` -------------------------------- ### Build and Run HPU Examples Source: https://github.com/zama-ai/tfhe-rs/blob/main/backends/tfhe-hpu-backend/README.md Builds the tfhe-rs project with HPU features and runs pre-made examples like hpu_hlapi and hpu_bench. Requires setting up the HPU environment and potentially pulling HPU files. ```bash cargo build --release --features="hpu-v80" --example hpu_hlapi --example hpu_bench source setup_hpu.sh --config v80 ./target/release/examples/hpu_bench --integer-w 64 --integer-w 32 --iop MUL --iter 10 ./target/release/examples/hpu_hlapi ``` -------------------------------- ### Rust LWE Encryption and Decryption Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/references/core-crypto-api/presentation.md Demonstrates the process of encrypting and decrypting a message using LWE ciphertext primitives from the tfhe-rs core_crypto module. It covers parameter setup, key generation, plaintext creation, encryption, decryption, and message recovery. ```rust use tfhe::core_crypto::prelude::*; // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct // computations // Define parameters for LweCiphertext creation let lwe_dimension = LweDimension(742); let lwe_noise_distribution = Gaussian::from_dispersion_parameter(StandardDev(0.000007069849454709433), 0.0); let ciphertext_modulus = CiphertextModulus::new_native(); // Create the PRNG let mut seeder = new_seeder(); let seeder = seeder.as_mut(); let mut encryption_generator = EncryptionRandomGenerator::::new(seeder.seed(), seeder); let mut secret_generator = SecretRandomGenerator::::new(seeder.seed()); // Create the LweSecretKey let lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(lwe_dimension, &mut secret_generator); // Create the plaintext let msg = 3u64; let plaintext = Plaintext(msg << 60); // Create a new LweCiphertext let mut lwe = LweCiphertext::new(0u64, lwe_dimension.to_lwe_size(), ciphertext_modulus); encrypt_lwe_ciphertext( &lwe_secret_key, &mut lwe, plaintext, lwe_noise_distribution, &mut encryption_generator, ); let decrypted_plaintext = decrypt_lwe_ciphertext(&lwe_secret_key, &lwe); // Round and remove encoding // First create a decomposer working on the high 4 bits corresponding to our encoding. let decomposer = SignedDecomposer::new(DecompositionBaseLog(4), DecompositionLevelCount(1)); let rounded = decomposer.closest_representable(decrypted_plaintext.0); // Remove the encoding let cleartext = rounded >> 60; // Check we recovered the original message assert_eq!(cleartext, msg); ``` -------------------------------- ### Rust Integer Encryption and Homomorphic Max Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/references/fine-grained-apis/quick-start.md Demonstrates encrypting 16-bit integers using the TFHE library's radix encoding. It shows how to generate keys, encrypt two unsigned 16-bit integers, perform a homomorphic maximum operation on them using `smart_max_parallelized`, and then decrypt the result. This example utilizes `tfhe::integer::gen_keys_radix` and `tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2`. Note: Run with the `--release` flag. ```rust use tfhe::integer::gen_keys_radix; use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2; fn main() { // We generate keys to encrypt 16 bits radix-encoded integers // using 8 blocks of 2 bits let (cks, sks) = gen_keys_radix(PARAM_MESSAGE_2_CARRY_2, 8); let clear_a = 2382u16; let clear_b = 29374u16; let mut a = cks.encrypt(clear_a as u64); let mut b = cks.encrypt(clear_b as u64); let encrypted_max = sks.smart_max_parallelized(&mut a, &mut b); let decrypted_max: u64 = cks.decrypt(&encrypted_max); assert_eq!(decrypted_max as u16, clear_a.max(clear_b)) } ``` -------------------------------- ### Add TFHE-rs Dependency to Cargo.toml Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/getting-started/quick-start.md Illustrates how to modify the `Cargo.toml` file to include TFHE-rs as a project dependency. It specifies the version and enables the 'integer' feature, which is necessary for integer-based homomorphic computations. ```toml [package] name = "tfhe-example" version = "0.1.0" edition = "2021" [dependencies] tfhe = { version = "~1.3.0", features = ["integer"] } ``` -------------------------------- ### Command: Run TFHE-rs Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/README.md This command is used to compile and run the TFHE-rs Rust example. It is highly recommended to use the `--release` flag for optimal performance, as homomorphic encryption operations are computationally intensive. ```bash cargo run --release ``` -------------------------------- ### Setup HPU Mockup Environment Source: https://github.com/zama-ai/tfhe-rs/blob/main/mockups/tfhe-hpu-mockup/README.md Sources the setup script to configure the HPU mockup environment. This is a prerequisite for running mockup applications and tests. ```bash source setup_hpu.sh --config sim ``` -------------------------------- ### tfhe-rs: Homomorphic Doubling Example (Cleartext & PBS Setup) Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/references/core-crypto-api/tutorial.md This Rust code example from tfhe-rs demonstrates homomorphic computation of 2 * 3. It initializes cryptographic parameters, generates LWE and GLWE keys, and creates a bootstrapping key. The code then encrypts the message 3, performs a cleartext multiplication by 2, and decrypts the result. It also sets up the necessary components for a homomorphic multiplication using Programmable Bootstrapping (PBS). ```rust use tfhe::core_crypto::prelude::*; pub fn main() { // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct // computations // Define the parameters for a 4 bits message able to hold the doubled 2 bits message let small_lwe_dimension = LweDimension(742); let glwe_dimension = GlweDimension(1); let polynomial_size = PolynomialSize(2048); let lwe_noise_distribution = Gaussian::from_dispersion_parameter(StandardDev(0.000007069849454709433), 0.0); let glwe_noise_distribution = Gaussian::from_dispersion_parameter(StandardDev(0.00000000000000029403601535432533), 0.0); let pbs_base_log = DecompositionBaseLog(23); let pbs_level = DecompositionLevelCount(1); let ciphertext_modulus = CiphertextModulus::new_native(); // Request the best seeder possible, starting with hardware entropy sources and falling back to // /dev/random on Unix systems if enabled via cargo features let mut boxed_seeder = new_seeder(); // Get a mutable reference to the seeder as a trait object from the Box returned by new_seeder let seeder = boxed_seeder.as_mut(); // Create a generator which uses a CSPRNG to generate secret keys let mut secret_generator = SecretRandomGenerator::::new(seeder.seed()); // Create a generator which uses two CSPRNGs to generate public masks and secret encryption // noise let mut encryption_generator = EncryptionRandomGenerator::::new(seeder.seed(), seeder); println!("Generating keys..."); // Generate an LweSecretKey with binary coefficients let small_lwe_sk = LweSecretKey::generate_new_binary(small_lwe_dimension, &mut secret_generator); // Generate a GlweSecretKey with binary coefficients let glwe_sk = GlweSecretKey::generate_new_binary(glwe_dimension, polynomial_size, &mut secret_generator); // Create a copy of the GlweSecretKey re-interpreted as an LweSecretKey let big_lwe_sk = glwe_sk.clone().into_lwe_secret_key(); // Generate the bootstrapping key, we use the parallel variant for performance reason let std_bootstrapping_key = par_allocate_and_generate_new_lwe_bootstrap_key( &small_lwe_sk, &glwe_sk, pbs_base_log, pbs_level, glwe_noise_distribution, ciphertext_modulus, &mut encryption_generator, ); // Create the empty bootstrapping key in the Fourier domain let mut fourier_bsk = FourierLweBootstrapKey::new( std_bootstrapping_key.input_lwe_dimension(), std_bootstrapping_key.glwe_size(), std_bootstrapping_key.polynomial_size(), std_bootstrapping_key.decomposition_base_log(), std_bootstrapping_key.decomposition_level_count(), ); // Use the conversion function (a memory optimized version also exists but is more complicated // to use) to convert the standard bootstrapping key to the Fourier domain convert_standard_lwe_bootstrap_key_to_fourier(&std_bootstrapping_key, &mut fourier_bsk); // We don't need the standard bootstrapping key anymore drop(std_bootstrapping_key); // Our 4 bits message space let message_modulus = 1u64 << 4; // Our input message let input_message = 3u64; // Delta used to encode 4 bits of message + a bit of padding on u64 let delta = (1_u64 << 63) / message_modulus; // Apply our encoding let plaintext = Plaintext(input_message * delta); // Allocate a new LweCiphertext and encrypt our plaintext let lwe_ciphertext_in: LweCiphertextOwned = allocate_and_encrypt_new_lwe_ciphertext( &small_lwe_sk, plaintext, lwe_noise_distribution, ciphertext_modulus, &mut encryption_generator, ); // Compute a cleartext multiplication by 2 let mut cleartext_multiplication_ct = lwe_ciphertext_in.clone(); println!("Performing cleartext multiplication..."); lwe_ciphertext_cleartext_mul( &mut cleartext_multiplication_ct, &lwe_ciphertext_in, Cleartext(2), ); // Decrypt the cleartext multiplication result let cleartext_multiplication_plaintext: Plaintext = decrypt_lwe_ciphertext(&small_lwe_sk, &cleartext_multiplication_ct); // Create a SignedDecomposer to perform the rounding of the decrypted plaintext // We pass a DecompositionBaseLog of 5 and a DecompositionLevelCount of 1 indicating we want to // round the 5 MSB, 1 bit of padding plus our 4 bits of message let signed_decomposer = ``` -------------------------------- ### Running the TFHE-rs Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/integration/js-on-wasm-api.md Command to execute the JavaScript example script using Node.js after the TFHE-rs WASM package has been built and the example code is saved in a file (e.g., `example.js`). ```shell node example.js ``` -------------------------------- ### Reproduce TFHE-rs Benchmarks Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/getting-started/benchmarks/cpu/cpu-programmable-bootstrapping.md Instructions to run programmable bootstrapping (PBS) and keyswitch-PBS (KS-PBS) benchmarks for TFHE-rs. These commands utilize the 'make' utility to compile and execute the benchmark suites. ```shell #PBS benchmarks: make bench_pbs #KS-PBS benchmarks: make bench_ks_pbs ``` -------------------------------- ### Setup and Run HPU Benchmarks Source: https://github.com/zama-ai/tfhe-rs/blob/main/backends/tfhe-hpu-backend/README.md Sets up the HPU environment and initiates performance benchmarks for tfhe-rs. This includes benchmarks for the High-Level API (hlapi) and Integer API, with specific targets for different benchmark types. ```bash # Do not forget to correctly set environment before hand source setup_hpu.sh --config v80 --init-qdma # Run hlapi benches make test_high_level_api_hpu # Run hlapi erc20 benches make bench_hlapi_erc20_hpu # Run integer level benches make bench_integer_hpu ``` -------------------------------- ### Complete Example: Parity Bit Calculation with FHE and Clear Values Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/tutorials/parity-bit.md This example demonstrates the usage of the generic `compute_parity_bit` function with both clear boolean values and TFHE encrypted booleans (`FheBool`). It includes key generation, server key setup, and the application of the parity bit logic to different data types. ```Rust use tfhe::{FheBool, ConfigBuilder, generate_keys, set_server_key}; use tfhe::prelude::*; use std::ops::{Not, BitXor}; #[derive(Copy, Clone, Debug)] enum ParityMode { // The sum bits of message + parity bit must an odd number Odd, // The sum bits of message + parity bit must an even number Even, } fn compute_parity_bit(fhe_bits: &[BoolType], mode: ParityMode) -> BoolType where BoolType: Clone + Not, for<'a> &'a BoolType: BitXor, { let mut parity_bit = fhe_bits[0].clone(); for fhe_bit in &fhe_bits[1..] { parity_bit = fhe_bit ^ parity_bit } match mode { ParityMode::Odd => !parity_bit, ParityMode::Even => parity_bit, } } fn is_even(n: u8) -> bool { (n & 1) == 0 } fn is_odd(n: u8) -> bool { !is_even(n) } fn check_parity_bit_validity(bits: &[bool], mode: ParityMode, parity_bit: bool) -> bool { let num_bit_set = bits .iter() .map(|bit| *bit as u8) .fold(parity_bit as u8, |acc, bit| acc + bit); match mode { ParityMode::Even => is_even(num_bit_set), ParityMode::Odd => is_odd(num_bit_set), } } fn main() { let config = ConfigBuilder::default().build(); let (client_key, server_key) = generate_keys(config); set_server_key(server_key); let clear_bits = [0, 1, 0, 0, 0, 1, 1].map(|b| (b != 0)); let fhe_bits = clear_bits } ``` -------------------------------- ### Build and Run User Application (HPU Bench) Source: https://github.com/zama-ai/tfhe-rs/blob/main/mockups/tfhe-hpu-mockup/README.md Compiles and runs a user application example, such as `hpu_bench`, with HPU support enabled. It demonstrates how to specify integer width and IO operations. ```bash # Example of CLI for building/running hpu_bench application # For convenienc, `just hpu_bench` could be also used cargo build --release --features="hpu" --example hpu_bench # Start MUL and ADD IOp on 64b integer ./target/release/examples/hpu_bench --integer-w 64 --iop MUL --iop ADD ``` -------------------------------- ### Add TFHE-rs Dependency (Standard) Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/getting-started/installation.md Include the TFHE-rs crate in your Rust project's Cargo.toml file. This configuration enables the 'boolean', 'shortint', and 'integer' features for core TFHE functionalities. ```toml tfhe = { version = "~1.3.0", features = ["boolean", "shortint", "integer"] } ``` -------------------------------- ### Build and Run Mockup Application Source: https://github.com/zama-ai/tfhe-rs/blob/main/mockups/tfhe-hpu-mockup/README.md Compiles the HPU mockup binary in release mode and runs it with specified parameter files and optional knobs for debugging and performance analysis. ```bash # Example of CLI for building/running mockup application # For convenience, `just mockup` could be also used cargo build --release --bin hpu_mockup ./target/release/hpu_mockup \ --params mockups/tfhe-hpu-mockup/params/gaussian_64b_fast.ron \ [--freq-hz --register --isc-depth] [--dump-out mockup_out/ --dump-reg]\ [--report-out mockup_rpt/ --report-trace] ``` -------------------------------- ### Add TFHE-rs Dependency (Software PRNG) Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/getting-started/installation.md Configure your Rust project's Cargo.toml to include TFHE-rs with the 'software-prng' feature. This is recommended for systems without hardware AES acceleration, ensuring broader compatibility. ```toml tfhe = { version = "~1.3.0", features = ["boolean", "shortint", "integer", "software-prng"] } ``` -------------------------------- ### Filter tfhe-rs CUDA Backend Tests Source: https://github.com/zama-ai/tfhe-rs/blob/main/backends/tfhe-cuda-backend/cuda/tests_and_benchmarks/tests/README.md How to run a subset of tests by specifying a filter for test names. This example shows running tests starting with 'Bootstrap'. The `--gtest_list_tests` flag can be used to list all available tests. ```bash tests/src/test_tfhe_cuda_backend --gtest_filter=Bootstrap* ``` -------------------------------- ### TFHE-rs GPU Key Generation and Setup Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/configuration/gpu-acceleration/simple-example.md Illustrates the process of generating a compressed server key and decompressing it to the GPU for accelerated computations. This involves creating a client key, a compressed server key, and then transferring the server key to the GPU. ```rust let client_key= ClientKey::generate(config); let compressed_server_key = CompressedServerKey::new(&client_key); let gpu_key = compressed_server_key.decompress_to_gpu(); ``` -------------------------------- ### TriviumStreamShortint Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/apps/trivium/README.md Demonstrates the usage of TriviumStreamShortint with tfhe-rs for FHE shortint (bit-level) operations. It shows key generation, parameter setup, initialization of the Trivium stream cipher, and trans-ciphering a message using `trans_encrypt_64`. ```rust use tfhe::shortint::prelude::*; use tfhe::shortint::parameters::current_params::{ V1_3_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M128, V1_3_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128, V1_3_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128_2M128 }; use tfhe::{ConfigBuilder, generate_keys, FheUint64}; use tfhe::prelude::*; use tfhe_trivium::TriviumStreamShortint; fn test_shortint() { // Setup for high-level API (e.g., FheUint64) let config = ConfigBuilder::default() .use_custom_parameters(V1_3_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128) .build(); let (hl_client_key, hl_server_key) = generate_keys(config); let underlying_ck: tfhe::shortint::ClientKey = (*hl_client_key.as_ref()).clone().into(); let underlying_sk: tfhe::shortint::ServerKey = (*hl_server_key.as_ref()).clone().into(); // Setup for low-level shortint API let (client_key, server_key): (ClientKey, ServerKey) = gen_keys(V1_3_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M128); // Key switching key for parameter transformation let ksk = KeySwitchingKey::new( (&client_key, Some(&server_key)), (&underlying_ck, &underlying_sk), V1_3_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128_2M128 ); // Example key and IV strings (hexadecimal) let key_string = "0053A6F94C9FF24598EB".to_string(); let mut key = [0u8; 80]; // Assuming 80 bits for this example for i in (0..key_string.len()).step_by(2) { let mut val = u64::from_str_radix(&key_string[i..i+2], 16).unwrap(); for j in 0..8 { key[8*(i>>1) + j] = (val % 2) as u8; val >>= 1; } } let iv_string = "0D74DB42A91077DE45AC".to_string(); let mut iv = [0u8; 80]; // Assuming 80 bits for this example for i in (0..iv_string.len()).step_by(2) { let mut val = u64::from_str_radix(&iv_string[i..i+2], 16).unwrap(); for j in 0..8 { iv[8*(i>>1) + j] = (val % 2) as u8; val >>= 1; } } // Expected output for verification let output_0_63 = "F4CD954A717F26A7D6930830C4E7CF0819F80E03F25F342C64ADC66ABA7F8A8E6EAA49F23632AE3CD41A7BD290A0132F81C6D4043B6E397D7388F3A03B5FE358".to_string(); // Encrypt key and IV using the high-level client key let cipher_key = key.map(|x| hl_client_key.encrypt(x)); let cipher_iv = iv.map(|x| hl_client_key.encrypt(x)); // Initialize a vector of FheUint64 ciphertexts for the message let mut ciphered_message = vec![FheUint64::try_encrypt(0u64, &hl_client_key).unwrap(); 9]; // Initialize the Trivium stream cipher with encrypted key, IV, server key, and key switching key let mut trivium = TriviumStreamShortint::new(cipher_key, cipher_iv, &server_key, &ksk); // Process the message using trans_encrypt_64 let mut vec = Vec::::with_capacity(8); while vec.len() < 8 { let trans_ciphered_message = trivium.trans_encrypt_64(ciphered_message.pop().unwrap(), &hl_server_key); vec.push(trans_ciphered_message.decrypt(&hl_client_key)); } // Helper function to convert vector of u64 to hex string (assumed to exist) // let hexadecimal = get_hexagonal_string_from_u64(vec); // assert_eq!(output_0_63, hexadecimal[0..64*2]); } // Placeholder for the helper function if it were part of the snippet // fn get_hexagonal_string_from_u64(data: Vec) -> String { // let mut hex_string = String::new(); // for val in data { // hex_string.push_str(&format!("{:016X}", val)); // } // hex_string // } ``` -------------------------------- ### Build TFHE Cuda Backend Source: https://github.com/zama-ai/tfhe-rs/blob/main/backends/tfhe-cuda-backend/README.md Instructions to clone the repository, navigate to the CUDA backend directory, create a build directory, configure with CMake, and compile the project using make. ```bash git clone git@github.com:zama-ai/tfhe-rs cd backends/tfhe-cuda-backend/cuda mkdir build cd build cmake .. make ``` -------------------------------- ### TFHE-rs Zero-Knowledge Proof Example Source: https://github.com/zama-ai/tfhe-rs/blob/main/tfhe/docs/fhe-computation/advanced-features/zk-pok.md Demonstrates the client-side encryption and proof generation, and server-side verification and computation using TFHE-rs' zero-knowledge proof feature. It covers parameter setup, CRS generation, ciphertext encryption with proof, and decryption of the result. ```rust use rand::prelude::*;\nuse tfhe::prelude::*;\nuse tfhe::set_server_key;\nuse tfhe::zk::{CompactPkeCrs, ZkComputeLoad};\n\npub fn main() -> Result<(), Box> {\n let mut rng = thread_rng();\n\n let params = tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;\n // Indicate which parameters to use for the Compact Public Key encryption\n let cpk_params = tfhe::shortint::parameters::PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;\n // And parameters allowing to keyswitch/cast to the computation parameters.\n let casting_params = tfhe::shortint::parameters::PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;\n // Enable the dedicated parameters on the config\n let config = tfhe::ConfigBuilder::with_custom_parameters(params)\n .use_dedicated_compact_public_key_parameters((cpk_params, casting_params)).build();\n\n // The CRS should be generated in an offline phase then shared to all clients and the server\n let crs = CompactPkeCrs::from_config(config, 64).unwrap();\n\n // Then use TFHE-rs as usual\n let client_key = tfhe::ClientKey::generate(config);\n let server_key = tfhe::ServerKey::new(&client_key);\n let public_key = tfhe::CompactPublicKey::try_new(&client_key).unwrap();\n // This can be left empty, but if provided allows to tie the proof to arbitrary data\n let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];\n\n let clear_a = rng.gen::();\n let clear_b = rng.gen::();\n\n let proven_compact_list = tfhe::ProvenCompactCiphertextList::builder(&public_key)\n .push(clear_a)\n .push(clear_b)\n .build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Verify)?;\n\n // Server side\n let result = {\n set_server_key(server_key);\n\n // Verify the ciphertexts\n let expander =\n proven_compact_list.verify_and_expand(&crs, &public_key, &metadata)?;\n let a: tfhe::FheUint64 = expander.get(0)?.unwrap();\n let b: tfhe::FheUint64 = expander.get(1)?.unwrap();\n\n a + b\n };\n\n // Back on the client side\n let a_plus_b: u64 = result.decrypt(&client_key);\n assert_eq!(a_plus_b, clear_a.wrapping_add(clear_b));\n\n Ok(())\n} ``` -------------------------------- ### HPU Device User API Source: https://github.com/zama-ai/tfhe-rs/blob/main/backends/tfhe-hpu-backend/README.md Functions for instantiating and initializing the HPU accelerator device. These functions allow users to set up the HPU, configure it from a file, and upload necessary public materials for TFHE computations. ```APIDOC HpuDevice::new - Instantiates the HPU device abstraction. HpuDevice::from_config - Instantiates the HPU device abstraction from a configuration file. HpuDevice::init - Configures and uploads the required public material to the HPU accelerator. ```