Default Backend

The default backend contains the CPU implementation of the majority of the engines from the specification. It is lightweight and very portable.


Some additional features can be activated on top of the default backend:
  • seeder_unix and seeder_x86_64_rdseed: makes it possible to use a seeder based on the Unix system or rely on rdseed acceleration, which is a feature of (some) x86_64 platforms.
  • backend_default_generator_x86_64_aesni: makes it possible to generate randoms relying on aesni acceleration (a feature present on most modern x86_64 platforms) instead of the much slower software generation (that's activated by default).
  • backend_default_generator_aarch64_aes: makes it possible to generate randoms relying on the Neon aes acceleration (a feature present on modern aarch64 platforms).
  • backend_default_parallel: activates the creation of bootstrap keys with multithreading (relying on the rayon dependency).
  • backend_default_serialization: activates the compilation of serialization features in the default backend.


In the tutorials we do not try to build a "real life" use case: beware that the parameters used throughout the tutorials are not secure and may not produce decrypted results that are unaffected by the noise! Higher level crates, built on top of concrete-core, will be released and make it possible to use concrete-core more easily.
In this first tutorial, we'll just see how to create secret keys for LWE and GLWE ciphertexts, and a bootstrap key. More advanced tutorials can be found in the FFT backend and Cuda backend pages.
Here, we'll just set up a new project containing a Cargo.toml file and an src directory with a file. The Cargo.toml file should contain:
name = "tutorial"
version = "0.1.0"
edition = "2021"
concrete-core = {version = "=1.0.1", features=["backend_default", "backend_default_parallel"]}
concrete-csprng = {version = "=0.2.1"}
So we can use concrete-core version 1.0.1 as a dependency. Then, in the file ,we're going to:
  • import the necessary types and functions:
use concrete_core::prelude::*;
  • set up some cryptographic parameters (recall that the parameters chosen here do not guarantee any security, neither to produce a result unaffected by the noise)
  • create the engines we need for the key creation
  • create the keys themselves
fn main() {
// 1. Set up cryptographic parameters
// DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
let (lwe_dim, glwe_dim, poly_size) = (
let (dec_lc, dec_bl) = (DecompositionLevelCount(3), DecompositionBaseLog(5));
let noise = Variance(2_f64.powf(-60.));
// 2. Create the necessary engines
// Here we need to create a secret to give to the unix seeder, but we skip the actual secret creation
const UNSAFE_SECRET: u128 = 0;
let mut engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET))).unwrap();
let mut parallel_engine = DefaultParallelEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET))).unwrap();
// 3. Create the keys
let lwe_sk: LweSecretKey64 = engine.generate_new_lwe_secret_key(lwe_dim).unwrap();
let glwe_sk: GlweSecretKey64 = engine.generate_new_glwe_secret_key(glwe_dim, poly_size).unwrap();
// The bootstrap key is created with multithreading, relying on rayon
let bsk: LweBootstrapKey64 =
parallel_engine.generate_new_lwe_bootstrap_key(&lwe_sk, &glwe_sk, dec_bl, dec_lc, noise).unwrap();
In this example, you can see that the bootstrap key was created with a DefaultParallelEngine in order to accelerate computation via multithreading.
To execute this code, simply run:
cargo run --release
The full list of engines and entities implemented in the default backend is available in the Rust documentation.