Coder Social home page Coder Social logo

zama-ai / tfhe-rs Goto Github PK

View Code? Open in Web Editor NEW
882.0 17.0 134.0 14.49 MB

TFHE-rs: A Pure Rust implementation of the TFHE Scheme for Boolean and Integer Arithmetics Over Encrypted Data.

License: Other

Rust 82.80% HTML 0.05% Shell 0.19% CMake 0.10% C 1.35% Makefile 0.50% Python 0.23% JavaScript 0.69% Sage 0.04% Cuda 11.49% C++ 2.58%
cryptography homomorphic-encryption rust tfhe

tfhe-rs's Introduction

Zama TFHE-rs


📒 Documentation | 💛 Community support | 📚 FHE resources by Zama

About

What is TFHE-rs

TFHE-rs is a pure Rust implementation of TFHE for boolean and integer arithmetics over encrypted data.

It includes:

  • a Rust API
  • a C API
  • and a client-side WASM API

TFHE-rs is designed for developers and researchers who want full control over what they can do with TFHE, while not having to worry about the low-level implementation. The goal is to have a stable, simple, high-performance, and production-ready library for all the advanced features of TFHE.

Main features

  • Low-level cryptographic library that implements Zama’s variant of TFHE, including programmable bootstrapping
  • Implementation of the original TFHE boolean API that can be used as a drop-in replacement for other TFHE libraries
  • Short integer API that enables exact, unbounded FHE integer arithmetics with up to 8 bits of message space
  • Size-efficient public key encryption
  • Ciphertext and server key compression for efficient data transfer
  • Full Rust API, C bindings to the Rust High-Level API, and client-side Javascript API using WASM.

Learn more about TFHE-rs features in the documentation.

Table of Contents

Getting started

Cargo.toml configuration

To use the latest version of TFHE-rs in your project, you first need to add it as a dependency in your Cargo.toml:

  • For x86_64-based machines running Unix-like OSes:
tfhe = { version = "*", features = ["boolean", "shortint", "integer", "x86_64-unix"] }
  • For Apple Silicon or aarch64-based machines running Unix-like OSes:
tfhe = { version = "*", features = ["boolean", "shortint", "integer", "aarch64-unix"] }
tfhe = { version = "*", features = ["boolean", "shortint", "integer", "x86_64"] }

Note

Note: You need to use a Rust version >= 1.73 to compile TFHE-rs.

Note

Note: aarch64-based machines are not yet supported for Windows as it's currently missing an entropy source to be able to seed the CSPRNGs used in TFHE-rs.

↑ Back to top

A simple example

Here is a full example:

use tfhe::prelude::*;
use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint32, FheUint8};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Basic configuration to use homomorphic integers
    let config = ConfigBuilder::default().build();

    // Key generation
    let (client_key, server_keys) = generate_keys(config);

    let clear_a = 1344u32;
    let clear_b = 5u32;
    let clear_c = 7u8;

    // Encrypting the input data using the (private) client_key
    // FheUint32: Encrypted equivalent to u32
    let mut encrypted_a = FheUint32::try_encrypt(clear_a, &client_key)?;
    let encrypted_b = FheUint32::try_encrypt(clear_b, &client_key)?;

    // FheUint8: Encrypted equivalent to u8
    let encrypted_c = FheUint8::try_encrypt(clear_c, &client_key)?;

    // On the server side:
    set_server_key(server_keys);

    // Clear equivalent computations: 1344 * 5 = 6720
    let encrypted_res_mul = &encrypted_a * &encrypted_b;

    // Clear equivalent computations: 6720 >> 5 = 210
    encrypted_a = &encrypted_res_mul >> &encrypted_b;

    // Clear equivalent computations: let casted_a = a as u8;
    let casted_a: FheUint8 = encrypted_a.cast_into();

    // Clear equivalent computations: min(210, 7) = 7
    let encrypted_res_min = &casted_a.min(&encrypted_c);

    // Operation between clear and encrypted data:
    // Clear equivalent computations: 7 & 1 = 1
    let encrypted_res = encrypted_res_min & 1_u8;

    // Decrypting on the client side:
    let clear_res: u8 = encrypted_res.decrypt(&client_key);
    assert_eq!(clear_res, 1_u8);

    Ok(())
}

To run this code, use the following command:

cargo run --release

Note

Note that when running code that uses TFHE-rs, it is highly recommended to run in release mode with cargo's --release flag to have the best performances possible.

Find an example with more explanations in this part of the documentation

↑ Back to top

Resources

TFHE deep dive

Tutorials

Explore more useful resources in TFHE-rs tutorials and Awesome Zama repo

Documentation

Full, comprehensive documentation is available here: https://docs.zama.ai/tfhe-rs.

↑ Back to top

Working with TFHE-rs

Disclaimers

Security estimation

Security estimations are done using the Lattice Estimator with red_cost_model = reduction.RC.BDGL16.

When a new update is published in the Lattice Estimator, we update parameters accordingly.

Security model

The default parameters for the TFHE-rs library are chosen considering the IND-CPA security model, and are selected with a bootstrapping failure probability fixed at p_error = $2^{-64}$. In particular, it is assumed that the results of decrypted computations are not shared by the secret key owner with any third parties, as such an action can lead to leakage of the secret encryption key. If you are designing an application where decryptions must be shared, you will need to craft custom encryption parameters which are chosen in consideration of the IND-CPA^D security model [1].

[1] Li, Baiyu, et al. "Securing approximate homomorphic encryption using differential privacy." Annual International Cryptology Conference. Cham: Springer Nature Switzerland, 2022. https://eprint.iacr.org/2022/816.pdf

Side-channel attacks

Mitigation for side-channel attacks has not yet been implemented in TFHE-rs, and will be released in upcoming versions.

Citations

To cite TFHE-rs in academic papers, please use the following entry:

@Misc{TFHE-rs,
  title={{TFHE-rs: A Pure Rust Implementation of the TFHE Scheme for Boolean and Integer Arithmetics Over Encrypted Data}},
  author={Zama},
  year={2022},
  note={\url{https://github.com/zama-ai/tfhe-rs}},
}

Contributing

There are two ways to contribute to TFHE-rs:

Becoming an approved contributor involves signing our Contributor License Agreement (CLA). Only approved contributors can send pull requests, so please make sure to get in touch before you do!

License

This software is distributed under the BSD-3-Clause-Clear license. Read this for more details.

FAQ

Is Zama’s technology free to use?

Zama’s libraries are free to use under the BSD 3-Clause Clear license only for development, research, prototyping, and experimentation purposes. However, for any commercial use of Zama's open source code, companies must purchase Zama’s commercial patent license.

Everything we do is open source and we are very transparent on what it means for our users, you can read more about how we monetize our open source products at Zama in this blogpost.

What do I need to do if I want to use Zama’s technology for commercial purposes?

To commercially use Zama’s technology you need to be granted Zama’s patent license. Please contact us [email protected] for more information.

Do you file IP on your technology?

Yes, all Zama’s technologies are patented.

Can you customize a solution for my specific use case?

We are open to collaborating and advancing the FHE space with our partners. If you have specific needs, please email us at [email protected].

↑ Back to top

Support

Support

🌟 If you find this project helpful or interesting, please consider giving it a star on GitHub! Your support helps to grow the community and motivates further development.

↑ Back to top

tfhe-rs's People

Contributors

agnesleroy avatar aquint-zama avatar bbarbakadze avatar bencrts avatar dartdart26 avatar dd23 avatar dependabot[bot] avatar guillermo-oyarzun avatar icetdrinker avatar jborfila avatar josesk999 avatar jshul avatar kc1212 avatar leonardohn avatar madsmtm avatar mayeul-zama avatar miles-six avatar mortendahl avatar nsarlin-zama avatar pdroalves avatar rdlopes avatar rklompuu avatar sarah-ek avatar soonum avatar titouantanguy avatar tmontaigu avatar y-pakorn avatar yagizsenal avatar yuxizama avatar zaccherinij avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tfhe-rs's Issues

Unit tests fail

Unit tests fail (main branch, fresh clone)

To Reproduce

  1. Clone this repo
  2. Confirm current branch is main
  3. Install nextest
  4. Run any of integer-tests.sh, shortint-tests.sh, or cargo test.

Expected behaviour
All unit tests are executed and pass.

Evidence
Output of shortint-tests.sh attached. Summary:

 `Summary [24289.015s] 459 tests run: 423 passed (95 slow, 1 flaky), 36 failed, 673 skipped`

Output of integer-test.sh attached. (Note: I hit ctrl-c after about 20 seconds). Summary:

 `Summary [  18.202s] 42/224 tests run: 22 passed, 20 failed, 1 skipped`

Output of cargo-test attached. (Note: I hit ctrl-c after about an hour). Failed tests:

test server_key::crt::tests::test_integer_smart_crt_mul_param_message_1_carry_1 ... FAILED
test server_key::crt::tests::test_integer_smart_crt_scalar_add_param_message_1_carry_1 ... FAILED
test server_key::crt::tests::test_integer_smart_crt_neg_param_message_1_carry_1 ... FAILED
test server_key::crt::tests::test_integer_smart_crt_add_param_message_1_carry_1 ... FAILED
test server_key::crt::tests::test_integer_smart_crt_sub_param_message_1_carry_1 ... FAILED
test server_key::crt::tests::test_integer_unchecked_crt_mul_param_message_1_carry_1 ... FAILED
test server_key::radix::tests::test_integer_smart_bitand_param_message_1_carry_1 ... FAILED

Configuration(please complete the following information):

  • OS: OsX 12.6
  • Rust: rustc 1.65.0 (897e37553 2022-11-02)
  • Cargo: cargo 1.65.0 (4bc8f24d3 2022-10-20)

Attachments:

Buffer issue in 'generate_lwe_private_functional_packing_keyswitch_key'

Describe the bug
LwePrivateFunctionalPackingKeyswitchKeyList object generated by allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list seems to be incorrect, while that generated by par_allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list works well.

To Reproduce

  1. For new_wopbs_key_only_for_wopbs function in shortint\engine\wopbs\mod.rs, change par_allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list function into allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list.
  2. Run the example code of generate_lut_without_padding function several times.

Expected behaviour
The assertion condition assert_eq!(res, (m * m) % message_modulus) fails.

Evidence
When new_wopbs_key_only_for_wopbs uses par_allocate_asnd_generate_new_circuit_bootstrap_lwe_pfpksk_list, the test passes.
par_allocate

However, when it is changed into allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list, the test fails.
allocate_error

Configuration(please complete the following information):

  • OS: Ubuntu 22.04
  • CPU: AMD Ryzen 7 2700X

Additional context
I think the problem comes from the buffer variable messages is not reset in the last loop of generate_lwe_private_functional_packing_keyswitch_key function. In the case of par_generate_lwe_private_functional_packing_keyswitch_key, the variable is declared inside the loop, so that it is always filled with zero in every iteration. I found that this issue is fixed after declaring the buffer variable inside the last loop of generate_lwe_private_functional_packing_keyswitch_key.
allocate_fix

Problem with test_tools::assert_noise_distribution

Describe the bug
There appears to be an inconsistency in test_tools::assert_noise_distribution

This function computes the modular distance of the errors on the torus:
https://github.com/zama-ai/concrete/blob/fbca4f8e998628e08a235550e4bb30fdae126972/concrete-core/src/backends/core/private/mod.rs#L119-L122

However, it is often called with std/variance that is the output of concrete-npe:

https://github.com/zama-ai/concrete/blob/fbca4f8e998628e08a235550e4bb30fdae126972/concrete-core/src/backends/core/private/crypto/bootstrap/fourier/tests.rs#L362-L372

Those last standard deviations/variances are not on the torus, but given as u32 or u64.

Because of this inconsistency, even if you introduce maximum errors of +/- 0.5 on the torus in any of those tested routines, the tests will still pass. There are other tests that use assert_noise_distribution where the std or variance input doesn't come from concrete-npe that don't seem to have this problem.

To Reproduce
One of the easiest ways to reproduce: just comment out something critical in the external product. The bootstrapping tests will still pass.

TFHE-rs for Web Assembly

Hi!
I'm opening this issue to ask about the progress of the migration of Concrete's libraries to Web Assembly. I intend to use it with wasm-bindgen, but, at the moment, Concrete only supports x86_64 arch from what I've seen.
Thank you in advance.

Not able to run benchmark on GCP

Hi there,

I was trying to reproduce the benchmark result on a GCP instance (with Ubuntu 20.04 x86-64 boot disk).
After the installation steps, I ran cargo bench and got the following error message:

thread 'main' panicked at 'Unable to instantiate a seeder, make sure to enable a seeder feature like seeder_unix for example on unix platforms.', tfhe/src/core_crypto/seeders.rs:122:12 note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

Could you please provide any insights on how to work this around?

Great thanks!

run tfhe-rs in macos m1 aarch64

Describe the bug
run tfhe-rs in macos aarch64

Evidence
error: failed to select a version for tfhe.
... required by package tfhetest v0.1.0 (/Users/miao/Documents/Miao/2021 MA/rust_projects/tfhetest)
versions that meet the requirements * are: 0.1.10, 0.1.9, 0.1.8, 0.1.7, 0.1.6, 0.1.5, 0.1.4, 0.1.3, 0.1.2, 0.0.0

the package tfhetest depends on tfhe, with features: aarch64-unix but tfhe does not have these features.

failed to select a version for tfhe which could resolve this conflict
image

Configuration(please complete the following information):

  • OS: macos m1

`tfhe::integer` comparison causing overhead

Currently, tfhe::integer comparison functions, e.g. smart_le() return whole BaseRadixCiphertext.

But if I want to MUX result base on smart_le() outcome, then due to the large overhead speed is ~2000ms per multiplication on my PC.
However, if instead I MUX by only multiply with one block using encrypt_one_block and unchecked_block_mul, then speed increase to ~330ms.
May I know if there is native way to reduce the outcome of smart_le() to single block? Thank you.

[BUILD] fix arguments for wasm-pack build targets in Makefile

Describe the bug
One cannot build wasm bindingd for JS and Node using Makefile build targets.

To Reproduce
Steps to reproduce the behaviour

  1. clone the repo
  2. run a make target for WASM bindgen

Expected behaviour

  • build should execute with no errors and
  • wasm file should be present in tfhe-rs/tfhe/pkg

Evidence
This is the error we get from the command line

/usr/bin/make -f /Users/rdlopes/Developer/rdlopes/tfhe-rs/Makefile -C /Users/rdlopes/Developer/rdlopes/tfhe-rs build_node_js_api
cd tfhe && \
	RUSTFLAGS="" rustup run "stable" \
		wasm-pack build --release --target=nodejs \
		--features=boolean-client-js-wasm-api,shortint-client-js-wasm-api
error: Found argument '--features' which wasn't expected, or isn't valid in this context

USAGE:
    wasm-pack build --release --target <target>

For more information try --help
make: *** [build_node_js_api] Error 1

Process finished with exit code 2

Configuration(please complete the following information):

  • OS: Mac OSX (x86 intel)

Why do WoPBS LUT generation require ciphertext input?

Hello, I was wondering why the LUT generation (generate_lut_radix) for Wopbs requires the ciphertext input when I use the same input for the LUT evaluation. In my code, I am recursively calling a function, and in my head, I imagine that I only need to generate the LUT once to compute on the function (which stays the same) for multiple different inputs. Is there a mathematical reason for this?

To show what I mean, in the example code you provide, you input the ciphertexts twice: one to generate the LUT and one to compute it.

let lut = wopbs_key.generate_lut_bivariate_radix(&ct1, &ct2, |x, y| 2 * x * y);
let ct_res = wopbs_key.bivariate_wopbs_with_degree(&ct1, &ct2, &lut);

Applying bootstrap to VectorLWE

I am working on implementing the forward pass of a neural network homomorphically encrypted using Concrete. For bootstrapping I am currently looping over the VectorLWE and applying bootstrap_nth for each encrypted value separately. This would look significantly cleaner code-wise if there was a method to apply the (functional) Bootstrap to the entire VectorLWE at once.

Would it be possible to have an analogue to the LWE bootstrap and bootstrap_with_function methods that operate on an entire VectorLWE in a future release?

How to Use the `private_functional_packing_keyswitch_key` Function in TFHE-rs

Hi,

I am currently attempting to use the packing algorithm in order to pack various LWE ciphertexts into one RLWE (or GLWE) ciphertext. I believe that the private_functional_packing_keyswitch_key function is related to this subject and that it is based on algorithm 2 in [CGGI20]. However, unlike other functions, I have not been able to find any explanation or test documentation for this function in the code, such as in lwe_private_functional_packing_keyswitch_key_generation.rs.

Could you please provide an example code for using this function, or recommend other options for packing multiple ciphertexts? Additionally, do you have any plans to implement a public key version of this function as well?

Execute TFHE Encrypted WASM?

What is the problem you want to solve and can not with the current version?
This isn't really an issue I have, but I am curious, is it possible (or been attempted) to create an executor for encrypted WASM. My guess is that the stack and heap would be encrypted, but there could be some pipe that allows the binary to message to some outer process some arbitrary plaintext instructions.

Describe the solution you'd like
For example, using a Model View Controller, the Model would be compiled to an encrypted binary, and the actual program will be a conventionally compiled binary which includes the executor. Data can be piped into the executing wasm, from the controller and data can be returned from it with instructions to the view. That way, graphics can still be handled quickly without this, but core functionality will remain hidden.

Describe alternatives you've considered
I have not been able to find any alternatives, but please let me know if you've found any

Add benchmarks

Boolean and shortint to be run at some regular interval

cc @soonum I will certainly annoy you with this down the line !

GSW encryption decryption missing steps?

Hello, currently, I am trying to encrypt bit inputs to compute cmux gates with the core tools. I suspected that I need to encrypt to gsw but in trying to run a script that I made to encrypt the number one, I couldn't get back my intended input. I believe I am making a mistake with my bit decomposition or my understanding how the ggsw data type is encoded and iterated through. I tested ggsw encryption/glwe decryption as my test code below. Do you mind pointing out my flaw in logic?

fn testggsw(){

    //LWE
    let glwe_size = GlweSize(3);
    let polynomial_size = PolynomialSize(1);
    let decomp_base_log = DecompositionBaseLog(4);
    let decomp_level_count = DecompositionLevelCount(1);
    let glwe_modular_std_dev = StandardDev(0.00000000000000029403601535432533);

    // Create the PRNG
    let mut seeder = new_seeder();
    let seeder = seeder.as_mut();
    let mut encryption_generator =
        EncryptionRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed(), seeder);
    let mut secret_generator =
        SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());

    // Create the GlweSecretKey
    let glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
        glwe_size.to_glwe_dimension(),
        polynomial_size,
        &mut secret_generator,
    );

    // Encrypt 1<<60 into ggsw
    let mut ggsw = GgswCiphertext::new(
        0u64,
        glwe_size,
        polynomial_size,
        decomp_base_log,
        decomp_level_count,
    );
    let mut plain = Plaintext(1u64 << 60);
    encrypt_ggsw_ciphertext(
        &glwe_secret_key,
        &mut ggsw,
        plain,
        glwe_modular_std_dev,
        & mut encryption_generator,
    );

    //Decrypt
    let glwe_list = ggsw.as_glwe_list();
    let glwe = glwe_list.get(glwe_list.glwe_ciphertext_count().0 - 1);
    let mut output_plaintext_list = PlaintextList::new(0u64, PlaintextCount(polynomial_size.0));
    decrypt_glwe_ciphertext(&glwe_secret_key, &glwe, &mut output_plaintext_list);

    let decomposer = SignedDecomposer::new(DecompositionBaseLog(4), DecompositionLevelCount(1));

    output_plaintext_list
        .iter_mut()
        .for_each(|elt| *elt.0 = decomposer.closest_representable(*elt.0));

    let output = output_plaintext_list.into_container()[0] >> 60;
    
    //Returns 0, not 1
    println!("{}", output);

}

Support for LUTs of varying bit widths

I noticed the boolean gate API here doesn't use programmable bootstrapping, and instead only supports a few 2-bit boolean gates. Would it be possible to support general programmable bootstrapping of varying bit-widths in the front-facing API? I.e., a 3-bit LUT would take three inputs (a, b, c), form the ciphertext 4*c + 2*b + a (assuming the cleartexts are 0-1 valued), and use that as an input to an 8-entry lookup table.

I could have use for PBS on up to 6-bit LUTs, though I imagine 6 bits would be too large for a 32-bit LWE ciphertext to handle under 128-bit security params. Let me know if I'm mistaken. Either way, 2-bit, 3-bit, and 4-bit LUTs would be of great use as well. I have a variety of circuits using mixed-size LUTs (2-N where N <= 6) that I would like to benchmark with tfhe-rs, and having these LUTs would make the runtime significantly faster.

I noticed that PBS is implemented, though the docs suggest generating LUTs as RLWE ciphertexts from an integer is manual (and it's not clear if there's a means to pad the LWE ciphertexts with an extra bit to avoid the requirement of a negacyclic LUT). Having an easy API to generate the LUT RLWE ciphertexts to pass to PBS would also make this much easier.

Wrong LUT encoding in case `en(de)crypt_without_padding` is used

Describe the bug

The combination of en(de)crypt_without_padding together with generate_accumulator gives incorrect results.
E.g., with func = |x:u64| x + 4, the output after decryption shows that rather x + 2 has been evaluated.

My conjecture is that omitting padding with en(de)crypt_without_padding is not addressed correctly in generate_accumulator: it seems to be transforming x -> 2x for the LUT evaluation (~ padding?) and back as y -> y/2, effectively evaluating ((2x) + 4) / 2 = x + 2, which is what I observe instead of the expected x + 4.

To Reproduce

Demonstrated in a toy example.

Evidence

Output of the toy example (parts omitted) with PARAM_MESSAGE_5_CARRY_0:

>>> DEMO PBS with TFHE-rs, function:   x -> x + 4

(i =  0) decrypted IN -> OUT:  0 ->  2
(i =  1) decrypted IN -> OUT:  1 ->  3
(i =  2) decrypted IN -> OUT:  2 ->  4
...
(i = 14) decrypted IN -> OUT: 14 -> 16
(i = 15) decrypted IN -> OUT: 15 -> 17
(i = 16) decrypted IN -> OUT: 16 -> 30   // negacyclic overlap as expected in 5-bit msg space
(i = 17) decrypted IN -> OUT: 17 -> 29
(i = 18) decrypted IN -> OUT: 18 -> 28
...
(i = 30) decrypted IN -> OUT: 30 -> 16
(i = 31) decrypted IN -> OUT: 31 -> 15
(i = 32) decrypted IN -> OUT:  0 ->  2   // indeed 5 bits of msg space

Configuration(please complete the following information):

Cargo.lock

Deterministic seeder

Hi!

Is there a preferred way to use tfhe-rs with purely deterministic and reproducible encryption? The way I'm currently doing this is like so:

let deterministic_seed = Seed(0);

let mut boolean_engine = BooleanEngine::new_from_seeder(
    Box::new(DeterministicSeeder::<ActivatedRandomGenerator>::new(
        deterministic_seed,
    ))
    .as_mut(),
);

// generate client key
let client_key = boolean_engine.create_client_key(DEFAULT_PARAMETERS);

// generate the server key
let server_key = boolean_engine.create_server_key(&client_key);

// this is deterministic
let ct = boolean_engine.encrypt(true, &client_key);

However, this is error-prone. If somewhere in the code, I would accidentally call:

// this is not deterministic
let ct = client_key.encrypt(true);

This falls back to the default non-deterministic BooleanEngine, instead of the deterministic one I created earlier.

What would help here is a deterministic seeding strategy in seeders.rs. Is there any preferred solution here?

Best,

Michiel

RUSTSEC-2021-0060: `aes-soft` has been merged into the `aes` crate

aes-soft has been merged into the aes crate

Details
Status unmaintained
Package aes-soft
Version 0.6.4
URL RustCrypto/block-ciphers#200
Date 2021-04-29

Please use the aes crate going forward. The new repository location is at:

<https://github.com/RustCrypto/block-ciphers/tree/master/aes>

AES-NI is now autodetected at runtime on i686/x86-64 platforms.
If AES-NI is not present, the aes crate will fallback to a constant-time
portable software implementation.

To force the use of a constant-time portable implementation on these platforms,
even if AES-NI is available, use the new force-soft feature of the aes
crate to disable autodetection.

See advisory page for additional details.

Help wanted: look into a table homomorphically with concrete

Hello to Zama/Concrete team, and thanks for allowing us to mimic a fraction of TFHE power.

What is the problem you want to solve and can not with the current version?
I'm actually trying to implement an AES using concrete. Since AES can be reduced as exclusively XOR and look-ups, I have the felling that the function-bootsrapping feature of TFHE fits perfectly this use case. I've tried different ways to achieve this goal using almost all of the bootstrapping functions available in concrete/concrete-core but was not able to get accurate results. I have the feeling that something is wrong with my choice of parameters, but all those I tried led to miserable failures...

Describe the solution you'd like
I would like to understand what's wrong with my choice of parameters, or if it's even possible with concrete, and how.

Describe alternatives you've considered
I already implemented a working version (albeit slow) of it using a bit-wise approach, where each bit is encrypted individually using the concrete-boolean package, and lookups are implemented using a network of CMUX gates. It works, but is slow as hell...

Additional context
I'm attaching my latest code (as a TXT file, since GitHub does not let me import .rs files) trying to make it work (NB: I tried with both different and same LWE/RLWE key, neither worked)
main.txt

Integer negation doesn't work properly

Describe the bug
When using homomorphic negation with RadixCiphertextBig types, result is always +1 than should be (LSB is not negated). This seems to happen for integers of any length. Below an example with 8 bits.

To Reproduce

use tfhe::integer::gen_keys_radix;
use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

fn main() {
// We have 4 * 2 = 8 bits of message
    let size = 4;
    let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, size);

    let msg = 1u64;

// Encrypt two messages:
    let mut ctxt = cks.encrypt(msg);

// Compute homomorphically a negation
    let ct_res = sks.smart_neg_parallelized(&mut ctxt);

// Decrypt
    let dec: u64 = cks.decrypt(&ct_res);

    // Panics: decrypted value is the correct result + 1
    assert_eq!(!(msg as u8), dec as u8);
}

Expected behaviour
The correct value of the negation should be 254.

Configuration:

  • OS: MacOS Big Sur 11.7.1

Bootstraping result have low padding bits and/or precision bits

Describe the bug
I am trying to use bootstraping to perform some neural-network-like computation.
I need about 30 padding bits for the computation of a layer (like a weighted summation). But I cannot make it work. The result is either low in precision bits or low in padding bits.
I don't know it is a bug or my configuration problem.

To Reproduce
Since it is just a proof-of-concept, I just use low-security settings.

let encoder = Encoder::new(-10., 10., 10, 30)?; // 10 precision bits, 30 padding bits
let sk_rlwe = RLWESecretKey::new(RLWEParams::new(512, -43));
let sk_in = LWESecretKey::new(LWEParams::new(1024, 1, -43));
// 13 higher than padding bits of the encoder. so there is no warning
let bsk = LWEBSK::new(&sk_in, &sk_rlwe, 5, 3);

let m = 5.0;
let c1 = LWE::encode_encrypt(&sk_in, message, &encoder)?;
let c2 = c1.bootstrap(&bsk)?;

I got the following message after calling bootstrap:

Loss of precision during bootstrap: 34 bit(s) of precision lost over 10 bit(s) of message originally. Consider increasing the number of level and/or decreasing the log base.

And the result has 0 precision bit. The encoder of c2 is:

Encoder {
-> [-10,10.019550342130987[
-> center = 0.009775171065493637
-> radius = 10.009775171065494
-> nb bit precision = 0
-> granularity = 20.019550342130987
-> nb bit padding = 30
-> round = false
}

(So this is also a bug report for the display. The ending bracket should be "]". The same problem seems to happen on some other classes.)

I tried to tune the level and base-log of bootstraping, and the dimension and noise-log of key parameter, but I still the same problem.

Configuration(please complete the following information):

  • OS: [e.g. Ubuntu 20.04]

Other Questions:
For bootstrapping, what is the relationship among input/output key dimension (key parameter), noise level (key parameter), input/output precision bits (encoder), input/output padding bits (encoder), level and base-log (bootstrapping). Is there a function/approximate function?
Is there a way to estimate the parameter so as to satisfy my computing requirement?

RUSTSEC-2021-0139: ansi_term is Unmaintained

ansi_term is Unmaintained

Details
Status unmaintained
Package ansi_term
Version 0.12.1
URL ogham/rust-ansi-term#72
Date 2021-08-18

The maintainer has adviced this crate is deprecated and will not
receive any maintenance.

The crate does not seem to have much dependencies and may or may not be ok to use as-is.

Last release seems to have been three years ago.

Possible Alternative(s)

The below list has not been vetted in any way and may or may not contain alternatives;

See advisory page for additional details.

Best way to add a plaintext argument for PBS functions

I would like to pass an additional argument to a function that will get converted to a LUT for PBS. Ideally, I want something like this:

fn foo(x: u64, my_vec: &Vec<u64>) -> u64 {
    my_vec[x as usize]
}

For radix ciphertexts, it was straightforward to modify the generate_lut_radix function to support input functions that take in an additional argument. However, it seems that modifying the generate_accumulator function will not be so straightforward since the call chain is fairly deep. I noticed that there are bivariate versions of the generate_accumulator function, but these seem to take in an additional ciphertext. Is there an easier way to do this?

cc @jimouris

editing subprojects locally

Hello, it looks like this repo contains copies of the subrepos (concrete, conrete-core, concrete-bool, etc) with different versions each, so when you clone everything and point each dependency to its local version, it simply won't work. Shouldn't you be using git submodules and keep each cargo subproject in a different repo, so you point each to the exact commit where everything works together? How are you guys doing local modifications?

Add rotation (left/right) operation to integer digits

What is the problem you want to solve and can not with the current version?
At the moment, no rotate (left/right) operation is available for the shortint/integer digits.

Describe the solution you'd like
Adding to the shortint/integers API two methods:

  • rotate_left
  • rotate_right

Describe alternatives you've considered
Only manual implementation can offer an alternative at the moment.

RUSTSEC-2021-0139: ansi_term is Unmaintained

ansi_term is Unmaintained

Details
Status unmaintained
Package ansi_term
Version 0.12.1
URL ogham/rust-ansi-term#72
Date 2021-08-18

The maintainer has adviced that this crate is deprecated and will not receive any maintenance.

The crate does not seem to have much dependencies and may or may not be ok to use as-is.

Last release seems to have been three years ago.

Possible Alternative(s)

The below list has not been vetted in any way and may or may not contain alternatives;

Dependency Specific Migration(s)

See advisory page for additional details.

key_id hashing error

Describe the bug
The buffer_for_keys method returns the same buffer for different keys. This leads to a buffer created for one key, being provided for another key in methods such as keyswitch_programmable_bootstrap_assign. The buffer's LWE dimension mismatches the LWE dimension of the second key leading to a panic.

To Reproduce
Steps to reproduce the behaviour

  1. Generate the first key pair with the first parameter set (e.g. PARAM_MESSAGE_5_CARRY_1)
  2. Create an accumulator and evaluate a keyswitch_programmable_bootstrap_assign with the first key pair.
  3. Generate the second key pair with the second parameter set (e.g. PARAM_MESSAGE_4_CARRY_2)
  4. Create an accumulator and evaluate a keyswitch_programmable_bootstrap_assign with the second key pair.

Expected behaviour
Both PBS steps should succeed independently from each other.

Evidence
Minimal example:

use tfhe::shortint::gen_keys;
use tfhe::shortint::parameters::*;

fn main() {
    let params1 = PARAM_MESSAGE_5_CARRY_1;
    let (ck1, sk1) = gen_keys(params1);
    let acc1 = sk1.generate_accumulator(|a| a);
    let mut idx1 = ck1.encrypt(0);
    sk1.keyswitch_programmable_bootstrap_assign(&mut idx1, &acc1);
    let res1 = ck1.decrypt(&idx1);

    let params2 = PARAM_MESSAGE_4_CARRY_2;
    let (ck2, sk2) = gen_keys(params2);
    let acc2 = sk2.generate_accumulator(|a| a);
    let mut idx2 = ck2.encrypt(0);
    sk2.keyswitch_programmable_bootstrap_assign(&mut idx2, &acc2);
    let res2 = ck2.decrypt(&idx2);

    println!("res1 = {}; res2 = {}", res1, res2);
}

Cargo.toml

[package]
...

[dependencies]
tfhe = { version = "0.1.9", features = ["shortint", "x86_64-unix"] }

Output:

LweCiphertext LweDimension LweDimension(875).', [...]/.cargo/registry/src/github.com-1ecc6299db9ec823/tfhe-0.1.9/src/core_crypto/algorithms/lwe_keyswitch.rs:104:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/panicking.rs:575:5
   1: core::panicking::panic_fmt
             at /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/panicking.rs:64:14
   2: tfhe::core_crypto::algorithms::lwe_keyswitch::keyswitch_lwe_ciphertext
   3: tfhe::shortint::engine::server_side::<impl tfhe::shortint::engine::ShortintEngine>::keyswitch_programmable_bootstrap_assign
   4: std::thread::local::LocalKey<T>::with
   5: tfhe::shortint::server_key::ServerKey::keyswitch_programmable_bootstrap_assign
   6: [...]::main

Configuration(please complete the following information):

  • 5.15.94-1-MANJARO

Give original plaintext after decrypting?

What is the problem you want to solve and can not with the current version?
I was following the documentation for both tfhe-rs and zama-concrete. When it comes to decrypting the values after operation, zama-concrete is able to fully decrypt the value and give the expected value whereas tfhe-rs is only able to assert if the modulus is correct. I couldn't find anything in the documentation to make tfhe-rs behave similarly to zama-concrete. Is there something in tfhe-rs currently that can support this? Thank you!

How to turn on GPU support

I read on your web page that concrete supports GPU acceleration. ("Optional GPU acceleration makes things even faster." on https://zama.ai/concrete/)

The question is that how can we turn on GPU support? I have searched through this repo and the document, but didn't find any clue about GPU. Could you provide a benchmark on the speedup of GPU acceleration?

GPU/CUDA support for PBS and gate evaluation

What is the problem you want to solve and can not with the current version?
Hi, I was wondering if you have considered GPU/CUDA acceleration for gate evaluation and bootstrapping.

Describe the solution you'd like
Ideally, adding CUDA/GPU support :) I'd be interested in looking into it as well.

Describe alternatives you've considered
I saw that concrete has some CUDA support but I was mostly interested in tfhe-rs rather than concrete.

combining<TFHE rs>with<risc zero>

I am combiningwith, but introducing dependencies tfhe={version="*", features=["boolean", "shortint", "integer", "x86_64 unix"]} in guest will result in an error.

Has anyone successfully combined these two tool libraries? I am very eager for your help.

the package `*` depends on `tfhe`, with features: `integer` but `tfhe` does not have these features.

Describe the bug
"integer" feature not exist when I try to add it to Cargo.toml.

To Reproduce

  1. Create project with cargo new test
  2. add 'tfhe = { version = "*", features = ["boolean", "shortint", "integer", "x86_64-unix"] }`
  3. broken

Configuration(please complete the following information):

  • OS: Arch Rolling

Additional Context
I tried removing "integer" feature, cargo.toml pass, but the "shortint" example still doesn't run. which is another problem i guess.

RUSTSEC-2021-0060: `aes-soft` has been merged into the `aes` crate

aes-soft has been merged into the aes crate

Details
Status unmaintained
Package aes-soft
Version 0.6.4
URL RustCrypto/block-ciphers#200
Date 2021-04-29

Please use the aes crate going forward. The new repository location is at:

<https://github.com/RustCrypto/block-ciphers/tree/master/aes>

AES-NI is now autodetected at runtime on i686/x86-64 platforms.
If AES-NI is not present, the aes crate will fallback to a constant-time
portable software implementation.

To force the use of a constant-time portable implementation on these platforms,
even if AES-NI is available, use the new force-soft feature of the aes
crate to disable autodetection.

See advisory page for additional details.

[feature] Reduce the number of FFTs needed for external product

Hi! I was curious if you knew about this https://eprint.iacr.org/2023/357.pdf improvement to external product in TFHE - it reduces the number of FFTs needed in the external product by replacing the FFT computations on each of the levels of the decomposed GLWE polynomial with a single FFT on the input GLWE polynomial followed by a modified decomposition.

If this sounds like an improvement you'd be curious about, I'd be happy to implement it and benchmark it.

Describe the solution you'd like

With the optimization from the paper above, these FFT on the input GLWE polynomial would be eliminated:

// We perform the forward fft transform for the glwe polynomial
let fourier = fft
.forward_as_integer(
FourierPolynomialMutView { data: &mut fourier },
glwe_poly,
substack3,
)
.data;
, and a custom decomposition with FFT method would be called on the input. Only a single FFT transform would be needed on the GLWE polynomial.

cc @sarah-ek

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.