Announcing Concrete v1.0.0

April 13, 2023
Alexandre Quint

Today marks the release of Concrete v.1.0.0, a compiler for TFHE that converts Python programs into FHE equivalents. Concrete is useful for developers who want to build a high level application that takes encrypted inputs and produces encrypted outputs.

Key changes

  • Concrete repository and product naming is now reserved exclusively for the Compiler
  • Concrete Numpy package is renamed in Concrete as Concrete Python
  • Concrete Rust library is replaced by the newly-released TFHE-rs library

Fully Homomorphic Encryption over the Torus (TFHE) is one of the various Fully Homomorphic Encryption (FHE) schemes available. When we talk about TFHE below, we are referring to the Zama variant of the TFHE scheme; when we talk about FHE, it is in reference to commonalities among all schemes.


Turn Python programs into TFHE circuits.

The main challenge for turning a regular program in FHE is to translate all operations into their equivalent encrypted forms. Simple operations like addition, subtraction, and multiplication are straightforward. When it comes to functions—even simple ones, like the sign function—it is not as easy. 

One of the main advantages of TFHE is that a homomorphic table lookup can be evaluated for free during the bootstrap operation, which is performed to reduce noise (see our TFHE Series if you are unfamiliar with FHE noise). Since any univariate function can be represented as a lookup table, this means TFHE can evaluate any function, even non-linear ones, without approximation. That is why it is called a Programmable Bootstrap (PBS).

Turning all regular functions into univariate ones, then generating the corresponding  lookup table based on the input variable bit width, is one of the tasks performed automatically by the Compiler to make program development as easy as possible.

from concrete import fhe

def add(x, y):
    return x + y

compiler = fhe.Compiler(add, {"x": "encrypted", "y": "clear"})

inputset = [(2, 3), (0, 0), (1, 6), (7, 7), (7, 1)]
circuit = compiler.compile(inputset)

x = 4
y = 4

clear_evaluation = add(x, y)
homomorphic_evaluation = circuit.encrypt_run_decrypt(x, y)

print(x, "+", y, "=", clear_evaluation, "=", homomorphic_evaluation)

Typical workflow.

The Compiler is meant to handle a circuit: a Directed Acyclic Graph of operations on one or more variables where each variable can be encrypted or plain. The result of a circuit compilation is:

  • a dynamic library with FHE operations
  • a JSON file with the cryptographic configuration called “Client Parameters” (`ClientSpecs`)

To interact with this circuit, clients must request `ClientSpecs` from the Server, then generate a private key and an evaluation key (also named server key) according to the parameters received. The client will then encrypt the input data, sending it and the evaluation key to the server to receive a result.

Here is a diagram of a typical workflow between the Client and Server:

While Concrete offers a convenient way to load the server library in Python, any programming language can be used.

Automatic cryptographic parameters optimization.

Another challenge when using any FHE library is to properly select cryptographic parameters. These parameters define how much space you have for your data and the generated noise. They also define how many sequential operations you can perform before calling a PBS to reduce this noise. The security, performances, and exactness of your application is directly linked to your choice of cryptographic parameters.

While it is common to have default parameter sets in FHE libraries, we created a TFHE Optimizer to automatically compute the best possible parameters for the program being compiled. Details on how this Optimizer works will be provided in an upcoming blog post, but you can view the eprint paper here.

These cryptographic parameters are stored in the Client Parameters file. The security of the parameters picked by the Optimizer are verified by the Lattice-estimator

Data types supported.

One of the main advantages of using TFHE is that all computations done in encrypted form produce the exact same result as in clear. There is currently a limitation of 16-bits on the size of the input variables. The research and engineering teams are working hard to support even greater efficiency and precision in the near future, although TFHE-rs already supports arbitrary precision.

Optimal performances.

Our Compiler also supports some level of parallelization. If you have a vector of values and need to compute a PBS on it or a loop over several inputs, then the Concrete Compiler will produce a multi-threaded library that leverages all available cores.

Multiple hardware backends.

Another big feature of our Compiler is the ability to compile FHE programs for a

given target architecture. Right now, it's not about cross compiling, but targeting architecture within the hardware that accelerates some of the cryptographic primitives.

These target architectures, named Concrete Compiler Backends, are now CPU and GPU. GPU is not yet available within the frontend, but will be very soon.

Integrating a new backend in our Compiler allows precise control of the memory and resources of the target hardware. We are actively working to offer more accelerators while making it as accessible as possible for you to build with.

Migration guide

Given the changes to Concrete v1.0.0, here are some expected impacts you might encounter.

Concrete Numpy users.

The Python Compiler frontend of Concrete Compiler is not new. You may already know it as Concrete Numpy. It will now be called Concrete Python (pip package concrete-python), while continuing to support NumPy types and functions.

We are currently focusing more on adding features to the Compiler than adding new language support but, technically, our Compiler is designed to support multiple frontends. Each frontend converts from the source language to the input format of our Compiler: MLIR.

Concrete Rust library users.

Until now, Concrete was both our set of Rust libraries implementing TFHE cryptographic primitives and our Compiler-based products: Concrete Numpy and Concrete ML. Concrete is now only reserved for Compiler-based products while the old Concrete library is now deprecated. The repository will be updated to reflect this change, and if you use one of the Rust libraries (either Concrete or Concrete Core), you will find a refactored version with simplified API in the TFHE-rs library.

Concrete ML users.

If you use Concrete ML, you are not impacted. Starting from v1.0.0, Concrete ML will be built on top of Concrete Python instead of Concrete Numpy.

Future work

Concrete aims to improve your experience by extending client support for languages other than Python and providing meaningful feedback on your code to anticipate performance issues, allowing you to build homomorphic applications faster. We will also work on reducing key and ciphertext size to limit payload size.

Mid-term goals include extending the maximum supported precision and helping researchers use our Optimizer to quickly validate their leads.

If you are interested in the inner workings of our Compiler or the reason why we choose LLVM and MLIR to build our FHE Compiler, stay tuned for the upcoming series of blog posts.

Additional links

Read more related posts

Zama Product Announcement - April 2023

With these releases, Zama continues to build its suite of products to make homomorphic encryption accessible, easy, and fast

Read Article

Announcing Concrete ML v1.0.0

Concrete ML v1.0.0 features a stable API, better inference performance, and user-friendly error reporting.

Read Article

Announcing TFHE-rs v0.2.0

TFHE-rs v0.2.0 adds support for large homomorphic unsigned integers up to 256 bits.

Read Article