zama/tfhe-rs-lib
Zama TFHE-rs Rust Library
zamatechnical-doc👥 Communityconfidence mediumhealth 100%
v1.0.0·Updated 4/5/2026
Use this skill when writing Rust programs that perform FHE computation using Zama's TFHE-rs library.
Installation
# Cargo.toml
[dependencies]
tfhe = { version = "0.10", features = ["integer", "x86_64-unix"] }
Available feature flags:
integer— FheUint/FheInt integer types (required for most use cases)x86_64-unix— optimized for x86-64 Linux/macOSaarch64-unix— optimized for Apple Silicon / ARM64boolean— FheBool operationsshortint— low-level shortint primitives
Quick Start
use tfhe::{ConfigBuilder, generate_keys, set_server_key, FheUint32};
use tfhe::prelude::*;
fn main() {
// 1. Generate keys
let config = ConfigBuilder::default().build();
let (client_key, server_key) = generate_keys(config);
// 2. Set server key (needed for FHE ops on this thread)
set_server_key(server_key);
// 3. Encrypt
let a = FheUint32::encrypt(10u32, &client_key);
let b = FheUint32::encrypt(20u32, &client_key);
// 4. Compute on ciphertexts — no decryption needed
let sum = a + b;
// 5. Decrypt result
let result: u32 = sum.decrypt(&client_key);
assert_eq!(result, 30);
}
Supported Types
| Type | Plaintext equivalent | Notes |
|---|---|---|
FheBool | bool | Encrypted boolean |
FheUint8 | u8 | |
FheUint16 | u16 | |
FheUint32 | u32 | |
FheUint64 | u64 | |
FheUint128 | u128 | |
FheUint256 | U256 | |
FheInt8 | i8 | Signed |
FheInt16 | i16 | Signed |
FheInt32 | i32 | Signed |
FheInt64 | i64 | Signed |
FheString | String | Experimental |
Arithmetic & Comparison
use tfhe::prelude::*;
// Arithmetic (works like native operators)
let sum = &a + &b;
let diff = &a - &b;
let prod = &a * &b;
let div = &a / &b;
let rem = &a % &b;
// Comparison (returns FheBool)
let gt: FheBool = a.gt(&b);
let lt: FheBool = a.lt(&b);
let eq: FheBool = a.eq(&b);
let ge: FheBool = a.ge(&b);
let le: FheBool = a.le(&b);
// Bitwise
let and = &a & &b;
let or = &a | &b;
let xor = &a ^ &b;
let shl = &a << 3u32;
let shr = &a >> 3u32;
// Conditional select (if_then_else)
let result = condition.if_then_else(&a, &b);
Key Management
use tfhe::{ConfigBuilder, generate_keys, CompressedServerKey};
use tfhe::prelude::*;
// Generate keys
let config = ConfigBuilder::default().build();
let (client_key, server_key) = generate_keys(config);
// Serialize server key for sending to compute server
let compressed = CompressedServerKey::new(&client_key);
let bytes = bincode::serialize(&compressed).unwrap();
// On compute server: deserialize and set
let server_key: ServerKey = bincode::deserialize(&bytes).unwrap()
.decompress();
set_server_key(server_key);
Client/Server Split Pattern
TFHE-rs is designed for a client-server model:
- Client: holds
client_key, encrypts inputs, decrypts outputs - Server: holds
server_keyonly, performs all FHE operations on ciphertexts without ever seeing plaintext
// CLIENT SIDE
let encrypted_input = FheUint32::encrypt(secret_value, &client_key);
let serialized = bincode::serialize(&encrypted_input).unwrap();
// → send serialized bytes to server
// SERVER SIDE
set_server_key(server_key);
let input: FheUint32 = bincode::deserialize(&received_bytes).unwrap();
let result = input + FheUint32::encrypt_trivial(42u32); // trivial = known constant
let result_bytes = bincode::serialize(&result).unwrap();
// → send result_bytes back to client
// CLIENT SIDE
let result: FheUint32 = bincode::deserialize(&result_bytes).unwrap();
let plaintext: u32 = result.decrypt(&client_key);
Parallel / Multi-threaded Computation
use tfhe::set_server_key;
use rayon::prelude::*;
// Set server key per thread when using rayon
rayon::broadcast(|_| set_server_key(server_key.clone()));
let results: Vec<FheUint32> = inputs
.par_iter()
.map(|x| x + &constant)
.collect();