Understanding Fully Homomorphic Encryption
Fully Homomorphic Encryption (FHE) allows computations on encrypted data without decrypting it. This page explains the fundamentals and how Privora uses FHE.
What is Homomorphic Encryption?
Homomorphic encryption is a form of encryption that allows specific mathematical operations to be performed on ciphertexts, producing an encrypted result that, when decrypted, matches the result of operations performed on the plaintext.
Encrypt(A) + Encrypt(B) = Encrypt(A + B)
This means programs can process sensitive data without ever seeing the actual values.
TFHE (Torus FHE)
Privora uses TFHE (Torus Fully Homomorphic Encryption), a modern FHE scheme with:
- Fast Boolean and Integer Operations: Efficient arithmetic on encrypted integers
- Programmable Bootstrapping: Enables arbitrary operations through function evaluation
- Practical Performance: Fast enough for real-world applications
Supported Operations
Privora supports the following operations on encrypted data:
Arithmetic Operations
| Operation | Method | Operator | Example |
|---|
| Addition | .add(&other) | &a + &b | let sum = a.add(&b)?; |
| Subtraction | .sub(&other) | &a - &b | let diff = a.sub(&b)?; |
| Multiplication | .mul(&other) | &a * &b | let prod = a.mul(&b)?; |
use privora_sdk_program::prelude::*;
// Load encrypted values
let a: Encrypted<u64> = a_ref.load()?;
let b: Encrypted<u64> = b_ref.load()?;
// Using methods (returns Result)
let sum = a.add(&b)?;
let difference = a.sub(&b)?;
let product = a.mul(&b)?;
// Using operators (panics on error)
let sum = &a + &b;
let difference = &a - &b;
let product = &a * &b;
Comparison Operations
| Operation | Method | Returns |
|---|
| Greater or Equal | .ge(&other) | EncryptedBool |
| Greater Than | .gt(&other) | EncryptedBool |
| Less or Equal | .le(&other) | EncryptedBool |
| Less Than | .lt(&other) | EncryptedBool |
| Equal | .eq_enc(&other) | EncryptedBool |
// Compare encrypted values
let is_greater: EncryptedBool = price.ge(&threshold)?;
let is_equal: EncryptedBool = value_a.eq_enc(&value_b)?;
Comparison operations are more expensive than arithmetic operations in FHE. See the optimization guide for best practices.
Min/Max Operations
// Get minimum/maximum of two encrypted values
let minimum = buy_qty.min(&sell_qty)?;
let maximum = price_a.max(&price_b)?;
Conditional Selection
The select operation is the FHE equivalent of an if-then-else:
// If condition is true, return true_val; otherwise return false_val
let result = condition.select(&true_val, &false_val)?;
This is essential for implementing branching logic in FHE programs:
// Example: Select price based on match condition
let can_match: EncryptedBool = buy_price.ge(&sell_price)?;
let fill_price = can_match.select(&sell_price, &buy_price)?;
// Equivalent to: if (buy >= sell) { sell_price } else { buy_price }
Supported Integer Types
| Type | Rust Type | Range | Ciphertext Size |
|---|
| u8 | Encrypted<u8> | 0-255 | ~10KB |
| u32 | Encrypted<u32> | 0-4B | ~40KB |
| u64 | Encrypted<u64> | 0-18Q | ~80KB |
Choose the smallest integer type that fits your use case. Larger types have proportionally larger ciphertexts and slower operations.
FHE operations have different performance profiles:
| Operation | Relative Cost | Notes |
|---|
| Addition | Low | Fast, use freely |
| Subtraction | Low | Same as addition |
| Multiplication | Medium | ~2-3x addition |
| Comparison | High | Requires bootstrapping |
| Min/Max | High | Built on comparison |
| Select | High | Built on comparison |
Optimization Tips
- Minimize comparisons: Each comparison is expensive; batch when possible
- Use smaller types:
u8 operations are faster than u64
- Avoid deep chains: FHE operations add noise; keep computation chains short
- Batch operations: Submit multiple operations in a single transaction
Ciphertext Properties
FHE ciphertexts have specific properties:
| Property | Description |
|---|
| Deterministic | Same plaintext + key = same ciphertext |
| Large | 10KB-100KB depending on type |
| Noise | Operations add noise; too much = decryption failure |
| Type-bound | Cannot mix Encrypted<u8> with Encrypted<u64> |
Security Considerations
- 128-bit security: TFHE parameters provide ~128-bit security
- Key management: FHE public key is shared; private key is distributed via MPC
- No plaintext leakage: Programs never see plaintext during computation
- Verifiable computation: All FHE operations are deterministic and verifiable
Next Steps