Ver código fonte

research/tfhe: More examples

parazyd 3 anos atrás
pai
commit
9ea8eef22b
2 arquivos alterados com 53 adições e 5 exclusões
  1. 1 1
      script/research/tfhe/Cargo.toml
  2. 52 4
      script/research/tfhe/src/main.rs

+ 1 - 1
script/research/tfhe/Cargo.toml

@@ -8,4 +8,4 @@ edition = "2021"
 [workspace]
 
 [dependencies]
-tfhe = {version = "0.2.3", features = ["boolean", "shortint", "x86_64"]}
+tfhe = {version = "0.2.3", features = ["boolean", "shortint", "integer", "x86_64-unix"]}

+ 52 - 4
script/research/tfhe/src/main.rs

@@ -16,13 +16,44 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use tfhe::shortint::{gen_keys, Parameters};
+use tfhe::{
+    boolean::prelude::{gen_keys as boolean_gen_keys, *},
+    integer::gen_keys_radix,
+    shortint::prelude::{gen_keys as shortint_gen_keys, *},
+};
 
 fn main() {
+    // ===============
+    // Boolean circuit
+    // ===============
     // Generate a set of client/server keys, using the default parameters.
     // The client generates both keys. The server key is meant to be published
     // so that homomorphic circuits can be computed.
-    let (client_key, server_key) = gen_keys(Parameters::default());
+    let (client_key, server_key) = boolean_gen_keys();
+
+    // Encrypt two messages using the (private) client key:
+    let msg1 = true;
+    let msg2 = false;
+    let ct_1 = client_key.encrypt(msg1);
+    let ct_2 = client_key.encrypt(msg2);
+
+    // We use the server public key to execute a boolean circuit:
+    // if ((NOT ct_2) NAND (ct_1 AND ct_2)) then (NOT ct_2) else (ct_1 AND ct_2)
+    let ct_3 = server_key.not(&ct_2);
+    let ct_4 = server_key.and(&ct_1, &ct_2);
+    let ct_5 = server_key.nand(&ct_3, &ct_4);
+    let ct_6 = server_key.mux(&ct_5, &ct_3, &ct_4);
+
+    // We use the client key to decrypt the output of the circuit
+    let output = client_key.decrypt(&ct_6);
+    assert!(output);
+
+    // ================
+    // Shortint circuit
+    // ================
+    // Generate a set of client/server keys
+    // with 2 bits of message and 2 bits of carry
+    let (client_key, server_key) = shortint_gen_keys(PARAM_MESSAGE_2_CARRY_2);
 
     let msg1 = 3;
     let msg2 = 2;
@@ -42,10 +73,27 @@ fn main() {
     let acc = server_key.generate_accumulator(f);
 
     // Compute the function over the ciphertext using the PBS
-    let ct_res = server_key.keyswitch_programmable_bootstrap(&ct_add, &acc);
+    let ct_res = server_key.apply_lookup_table(&ct_add, &acc);
 
     // Decrypt the ciphertext using the (private) client key
     let output = client_key.decrypt(&ct_res);
     assert_eq!(output, f(msg1 + msg2));
-    println!("{:#b}", msg1 + msg2);
+
+    // ===============
+    // Integer circuit
+    // ===============
+    // We create keys to create 16 bits integers
+    // using 8 blocks of 2 bits
+    let (cks, sks) = gen_keys_radix(&PARAM_MESSAGE_2_CARRY_2, 8);
+
+    let clear_a = 2382u16;
+    let clear_b = 29374u16;
+
+    let mut a = cks.encrypt(clear_a as u64);
+    let mut b = cks.encrypt(clear_b as u64);
+
+    let encrypted_max = sks.smart_max_parallelized(&mut a, &mut b);
+    let decrypted_max: u64 = cks.decrypt(&encrypted_max);
+
+    assert_eq!(decrypted_max as u16, clear_a.max(clear_b))
 }