#fully #homomorphic #encryption #fhe #cryptography

concrete-core

Concrete is a fully homomorphic encryption (FHE) library that implements Zama’s variant of TFHE

8 releases

Uses new Rust 2021

1.0.0-gamma Jul 6, 2022
1.0.0-beta Apr 6, 2022
1.0.0-alpha Feb 1, 2022
0.1.10 Sep 30, 2021
0.1.7 Mar 25, 2021

#91 in Cryptography

Download history 38/week @ 2022-06-08 25/week @ 2022-06-15 44/week @ 2022-06-22 45/week @ 2022-06-29 141/week @ 2022-07-06 98/week @ 2022-07-13 38/week @ 2022-07-20 70/week @ 2022-07-27 105/week @ 2022-08-03 172/week @ 2022-08-10 58/week @ 2022-08-17 68/week @ 2022-08-24 31/week @ 2022-08-31 46/week @ 2022-09-07 29/week @ 2022-09-14 26/week @ 2022-09-21

143 downloads per month
Used in 2 crates

BSD-3-Clause-Clear and GPL-2.0-or-later

5.5MB
91K SLoC

Concrete Core

This crate contains low-level implementations of homomorphic operators used in the concrete library (GitHub Repo).

⚠ Warning ⚠

This crate assumes that the user is comfortable with the theory behind FHE. If you prefer to use a simpler API, that will perform sanity checks on your behalf, the higher-level concrete crate should have your back.

Example

Here is a small example of how one could use concrete-core to perform a simple operation homomorphically:

// This examples shows how to multiply a secret value by a public one homomorphically.
// First we import the proper symbols:

use concrete_commons::dispersion::Variance;
use concrete_commons::parameters::LweDimension;
use concrete_core::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let lwe_dimension = LweDimension(750);
    let noise = Variance(2_f64.powf(-104.));

    // Here a hard-set encoding is applied on the input (shift by 59 bits) which corresponds here
    // to a precision of 4 bits with an additional bit of padding (won't be used but required for
    // PBS)
    let raw_input = 3_u64 << 59;

    // We will multiply by 4
    let raw_input_cleatext = 4_u64;

    // Unix seeder must be given a secret input.
    // Here we just give it 0, which is totally unsafe.
    const UNSAFE_SECRET: u128 = 0;
    let mut engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;

    // We create a cleartext from the raw cleartext
    let cleartext: Cleartext64 = engine.create_cleartext(&raw_input_cleatext)?;
    let key: LweSecretKey64 = engine.create_lwe_secret_key(lwe_dimension)?;

    // We crate the input plaintext from the raw input
    let input_plaintext = engine.create_plaintext(&raw_input)?;
    let input_ciphertext = engine.encrypt_lwe_ciphertext(&key, &input_plaintext, noise)?;

    // The content of the output ciphertext will be discarded, use a placeholder plaintext of 0
    let placeholder_output_plaintext = engine.create_plaintext(&0u64)?;
    let mut ouptut_ciphertext =
        engine.encrypt_lwe_ciphertext(&key, &placeholder_output_plaintext, noise)?;

    // Perform the multiplication, overwriting (discarding) the output ciphertext content
    engine.discard_mul_lwe_ciphertext_cleartext(
        &mut ouptut_ciphertext,
        &input_ciphertext,
        &cleartext
    )?;

    // Get the decrypted result as a plaintext and then a raw value
    let decrypted_plaintext = engine.decrypt_lwe_ciphertext(&key, &ouptut_ciphertext)?;
    let raw_decrypted_plaintext = engine.retrieve_plaintext(&decrypted_plaintext)?;

    // Round the output for our 4 bits of precision
    let output = raw_decrypted_plaintext >> 58;
    let carry = output % 2;
    let output = ((output >> 1) + carry) % (1 << 5);

    // Check the high bits have the result we expect
    assert_eq!(output, 12);

    engine.destroy(cleartext)?;
    engine.destroy(key)?;
    engine.destroy(input_plaintext)?;
    engine.destroy(placeholder_output_plaintext)?;
    engine.destroy(decrypted_plaintext)?;
    engine.destroy(input_ciphertext)?;
    engine.destroy(ouptut_ciphertext)?;

    Ok(())
}

Links

License

This software is distributed under the BSD-3-Clause-Clear license. If you have any questions, please contact us at hello@zama.ai.

Dependencies

~12MB
~322K SLoC