Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This document explains public key encryption and provides instructions for 2 methods.
Public key encryption refers to the cryptographic paradigm where the encryption key can be publicly distributed, whereas the decryption key remains secret to the owner. This differs from the usual case where the same secret key is used to encrypt and decrypt the data. In TFHE-rs, there are two methods for public key encryptions:
Classical public key: the first method involves the public key containing many encryptions of zero, as detailed in Guide to Fully Homomorphic Encryption over the [Discretized] Torus, Appendix A.
Compact public key: the second method is based on the paper TFHE Public-Key Encryption Revisited, allowing for significantly smaller key sizes compared to the first method.
Public keys can also be compressed to reduce size.
This example shows how to use classical public keys.
This example shows how to use compact public keys. The main difference is in the ConfigBuilder
where the parameter set has been changed.
For more information on using compact public keys to encrypt data and generate a zero-knowledge proof of correct encryption at the same time, see the guide on ZK proofs.
This document describes how to use trivial encryption in TFHE-rs to initialize server-side values.
Sometimes, the server side needs to initialize a value. For example, when computing the sum of a list of ciphertexts, you typically initialize the sum
variable to 0
.
Instead of asking the client to send an actual encrypted zero, the server can use a trivial encryption. A trivial encryption creates a ciphertext that contains the desired value but isn't securely encrypted - essentially anyone, any key can decrypt it.
Note that when you want to do an operation that involves a ciphertext and a clear value (often called scalar operation), you should only use trivial encryption of the clear value if the scalar operations that you want to run are not supported.
This document describes how to use Rayon for parallel processing in TFHE-rs, detailing configurations for single and multi-client applications with code examples.
is a popular Rust crate that simplifies writing multi-threaded code. You can use Rayon to write multi-threaded TFHE-rs code. However, due to the specifications of Rayon and TFHE-rs, certain setups are necessary.
The high-level API requires to call set_server_key
on each thread where computations need to be done. So a first attempt to use Rayon with TFHE-rs might look like this:
However, due to Rayon's work-stealing mechanism and TFHE-rs' internals, this may create BorrowMutError
.
The correct way is to call rayon::broadcast
as follows:
For applications that need to operate concurrently on data from different clients and require each client to use multiple threads, you need to create separate Rayon thread pools:
This can be useful if you have some rust #[test]
, see the example below:
This document explains how to implement the zero-knowledge proofs function for compact public key encryption to verify the encryption process without revealing the encrypted information.
TFHE-rs can generate zero-knowledge proofs to verify that the compact public key encryption process is correct. In other words, TFHE-rs generates the proof without revealing any information other than the already known range of the encrypted message. This technique is derived from Libert’s work.
You can enable this feature using the flag: --features=zk-pok
when building TFHE-rs.
To use this feature, you must first generate a CRS (Common Reference String). The CRS is a piece of cryptographic data that is necessary to ensure the security of zero-knowledge proofs. The CRS should be generated in advance and shared between all the clients and the server. A CRS can be reused for multiple encryptions with the same parameters.
Once the CRS is generated, using zero-knowledge proofs is straightforward: during encryption, the client generates the proof, and the server validates it before performing any homomorphic computations.
Note that you need to use dedicated parameters for the compact public key encryption. This helps to reduce the size of encrypted data and speed up the zero-knowledge proof computation.
The following example shows how a client can encrypt and prove a ciphertext, and how a server can verify and compute the ciphertext:
Performance can be improved by setting lto="fat"
in Cargo.toml
and by building the code for the native CPU architecture and in release mode, e.g. by calling RUSTFLAGS="-C target-cpu=native" cargo run --release
.
You can choose a more costly proof with ZkComputeLoad::Proof
, which has a faster verification time. Alternatively, you can select ZkComputeLoad::Verify
for a faster proof and slower verification.
The ZK scheme used to generate and verify proofs is available in two versions:
ZKV1: This version is close to the original paper from Libert.
ZKV2: Differing from the paper, this version provides better performance for provers and verifiers.
TFHE-rs selects automatically the scheme to use based on the encryption parameters during the CRS generation. With default parameters, ZKV2 is selected.
The following example shows how to generate a CRS and proofs for ZKV1. Compared to the previous example, only the parameters are changed:
Please refer to the Zero-knowledge proof benchmarks for detailed performance benchmark results.
This document explains the mechanism and steps to generate an oblivious encrypted random value using only server keys.
The goal is to give to the server the possibility to generate a random value, which will be obtained in an encrypted format and will remain unknown to the server. The implementation is based on this article.
This is possible through two methods on FheUint
and FheInt
:
generate_oblivious_pseudo_random
which return an integer taken uniformly in the full integer range ([0; 2^N[
for a FheUintN
and [-2^(N-1); 2^(N-1)[
for a FheIntN
).
generate_oblivious_pseudo_random_bounded
which return an integer taken uniformly in [0; 2^random_bits_count[
. For a FheUintN
, we must have random_bits_count <= N
. For a FheIntN
, we must have random_bits_count <= N - 1
.
Both methods functions take a seed Seed
as input, which could be any u128
value. They both rely on the use of the usual server key. The output is reproducible, i.e., the function is deterministic from the inputs: assuming the same hardware, seed and server key, this function outputs the same random encrypted value.
Here is an example of the usage:
This document explains how TFHE-rs implements specific operations to detect overflows in computations.
The mechanism of detecting overflow consists in returning an encrypted flag with a specific ciphertext that reflects the state of the computation. When an overflow occurs, this flag is set to true. Since the server is not able to evaluate this encrypted value, the client has to check the flag value when decrypting to determine if an overflow has happened.
These operations might be slower than their non-overflow-detecting equivalent, so they are not enabled by default. To use them, you must explicitly call specific operators. At the moment, only additions, subtractions, and multiplications are supported. We plan to add more operations in future releases.
Here's the list of operations supported along with their symbol:
The usage of these operations is similar to the standard ones. The key difference is in the decryption process, as shown in following example:
overflow_add
Binary
overflow_sub
Binary
overflow_mul
Binary