1 unstable release

0.1.0-beta.8 Feb 3, 2024
0.1.0-beta.7 Oct 12, 2023
0.1.0-beta.5 Sep 5, 2023
0.1.0-beta.4 Oct 13, 2022
0.1.0-beta.3 Sep 11, 2022

#1681 in Cryptography

Custom license

540KB
12K SLoC

fhe fhe crate version

A pure-Rust implementation of fully homomorphic encryption schemes based on Ring-LWE.

This library implements Fully Homomorphic Encryption schemes, i.e., encryption schemes which perform implicit additions and multiplications on plaintext values while exclusively manipulating encrypted data.

This library provides implementations of:

  • BFV, the Brakerski-Fan-Vercauteren (BFV) homomorphic encryption scheme. More precisely, this library implements a leveled variant of the HPS (Halevi--Polyakov--Shoup) RNS-variant of the scheme.

Example

Below is a simple example using BFV of an homomorphic multiplication. One ciphertext encrypts the value 20 using the secret key, and one ciphertext encrypts the value -7 using the public key. The ciphertexts are then multiplied, and after decryption, the program checks that the decrypted value has 20 * (-7) = -140 in the first coefficient.

use fhe::bfv::{BfvParametersBuilder, Ciphertext, Encoding, Plaintext, PublicKey, SecretKey};
use fhe_traits::*;
use rand::{rngs::OsRng, thread_rng};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let parameters = BfvParametersBuilder::new()
            .set_degree(2048)
            .set_moduli(&[0x3fffffff000001])
            .set_plaintext_modulus(1 << 10)
            .build_arc()?;
    let mut rng = thread_rng();

    let secret_key = SecretKey::random(&parameters, &mut OsRng);
    let public_key = PublicKey::new(&secret_key, &mut rng);

    let plaintext_1 = Plaintext::try_encode(&[20_u64], Encoding::poly(), &parameters)?;
    let plaintext_2 = Plaintext::try_encode(&[-7_i64], Encoding::poly(), &parameters)?;

    let ciphertext_1: Ciphertext = secret_key.try_encrypt(&plaintext_1, &mut rng)?;
    let ciphertext_2: Ciphertext = public_key.try_encrypt(&plaintext_2, &mut rng)?;

    let result = &ciphertext_1 * &ciphertext_2;

    let decrypted_plaintext = secret_key.try_decrypt(&result)?;
    let decrypted_vector = Vec::<i64>::try_decode(&decrypted_plaintext, Encoding::poly())?;

    assert_eq!(decrypted_vector[0], -140);

    Ok(())
}

Note that operations actually happen modulo the plaintext_modulus, here set to 1024 (= 1 << 10); for example, we would have had that the homomorphic multiplication of 805 and -7 is 509 = (805 * (-7)) mod 1024. Additionally, the poly() encoding means that the vector being encoded corresponds to the coefficients of a polynomial in (ZZ / (1024))[x] / (x^2048+1) (and homomorphic multiplication happens in that ring); here since only one coefficient is provided, the value is placed in the constant coefficient. The library also contains a simd() encoding, which enables component-wise operation on the values of the vector, provided the technical limitation that the plaintext modulus is congruent to 1 modulo twice the polynomial degree.

Examples

More examples exercizing multiple functions from the API are provided in the repository examples/. For example, this library implements SealPIR and MulPIR, which can be run as follows:

cargo run --release --example sealpir

and

cargo run --release --example mulpir

Performance

Micro benchmarks can be obtained by running cargo bench. This crate uses criterion.rs for benchmarks.

Unit tests

Run tests with cargo test.

⚠️ Security / Stability

The implementations in this crate have never been independently audited for security. Additionally, no promise on the API and ABI stability will be made until version 1.0.0 of the crate.

Use at your own risk.

Dependencies

~5–8MB
~142K SLoC