concrete_boolean/lib.rs
1#![deny(rustdoc::broken_intra_doc_links)]
2//! Welcome the the `concrete-boolean` documentation!
3//!
4//! # Description
5//! This library makes it possible to execute boolean gates over encrypted bits.
6//! It allows to execute a boolean circuit on an untrusted server because both circuit inputs and
7//! outputs are kept private.
8//! Data are indeed encrypted on the client side, before being sent to the server.
9//! On the server side every computation is performed on ciphertexts.
10//! The server however has to know the boolean circuit to be evaluated.
11//! At the end of the computation, the server returns the encryption of the result to the user.
12//!
13//!
14//!
15//! # Quick Example
16//!
17//! The following piece of code shows how to generate keys and run a small Boolean circuit
18//! homomorphically.
19//!
20//! ```rust
21//! # #[cfg(not(feature = "cuda"))]
22//! # fn main() {
23//!
24//! //! use concrete_boolean::gen_keys;
25//! use concrete_boolean::prelude::*;
26//!
27//! // We generate a set of client/server keys, using the default parameters:
28//! let (mut client_key, mut server_key) = gen_keys();
29//!
30//! // We use the client secret key to encrypt two messages:
31//! let ct_1 = client_key.encrypt(true);
32//! let ct_2 = client_key.encrypt(false);
33//!
34//! // We use the server public key to execute a boolean circuit:
35//! // if ((NOT ct_2) NAND (ct_1 AND ct_2)) then (NOT ct_2) else (ct_1 AND ct_2)
36//! let ct_3 = server_key.not(&ct_2);
37//! let ct_4 = server_key.and(&ct_1, &ct_2);
38//! let ct_5 = server_key.nand(&ct_3, &ct_4);
39//! let ct_6 = server_key.mux(&ct_5, &ct_3, &ct_4);
40//!
41//! // We use the client key to decrypt the output of the circuit:
42//! let output_1 = client_key.decrypt(&ct_6);
43//! assert_eq!(output_1, true);
44//!
45//! // It is possible to compute gates with one input unencrypted
46//! let ct_7 = server_key.and(&ct_6, true);
47//! let output_2 = client_key.decrypt(&ct_7);
48//! assert_eq!(output_2, true);
49//!
50//! // It is possible to trivially encrypt on the server side
51//! // i.e. to not encrypt but still generate a compatible Ciphertext
52//! let ct_8 = server_key.trivial_encrypt(false);
53//! let ct_9 = server_key.mux(&ct_7, &ct_3, &ct_8);
54//! let output_3 = client_key.decrypt(&ct_9);
55//! assert_eq!(output_3, true);
56//! # }
57//!
58//! # #[cfg(feature = "cuda")]
59//! # fn main() {}
60//! ```
61
62use crate::client_key::ClientKey;
63use crate::parameters::DEFAULT_PARAMETERS;
64use crate::server_key::ServerKey;
65#[cfg(test)]
66use rand::Rng;
67
68pub mod ciphertext;
69pub mod client_key;
70pub mod engine;
71pub mod parameters;
72pub mod prelude;
73pub mod server_key;
74
75/// The scaling factor used for the plaintext
76pub(crate) const PLAINTEXT_LOG_SCALING_FACTOR: usize = 3;
77
78/// The plaintext associated with true: 1/8
79pub(crate) const PLAINTEXT_TRUE: u32 = 1 << (32 - PLAINTEXT_LOG_SCALING_FACTOR);
80
81/// The plaintext associated with false: -1/8
82pub(crate) const PLAINTEXT_FALSE: u32 = 7 << (32 - PLAINTEXT_LOG_SCALING_FACTOR);
83
84/// tool to generate random booleans
85#[cfg(test)]
86pub(crate) fn random_boolean() -> bool {
87 // create a random generator
88 let mut rng = rand::thread_rng();
89
90 // generate a random bit
91 let n: u32 = (rng.gen::<u32>()) % 2;
92
93 // convert it to boolean and return
94 n != 0
95}
96
97/// tool to generate random integers
98#[cfg(test)]
99pub(crate) fn random_integer() -> u32 {
100 // create a random generator
101 let mut rng = rand::thread_rng();
102
103 // generate a random u32
104 rng.gen::<u32>()
105}
106
107/// Generate a couple of client and server keys with the default cryptographic parameters:
108/// `DEFAULT_PARAMETERS`.
109/// The client is the one generating both keys.
110/// * the client key is used to encrypt and decrypt and has to be kept secret;
111/// * the server key is used to perform homomorphic operations on the server side and it is
112/// meant to be published (the client sends it to the server).
113///
114/// ```rust
115/// # #[cfg(not(feature = "cuda"))]
116/// # fn main() {
117/// use concrete_boolean::gen_keys;
118/// use concrete_boolean::prelude::*;
119/// // generate the client key and the server key:
120/// let (cks, sks) = gen_keys();
121/// # }
122/// # #[cfg(feature = "cuda")]
123/// # fn main() {}
124/// ```
125pub fn gen_keys() -> (ClientKey, ServerKey) {
126 // generate the client key
127 let cks = ClientKey::new(&DEFAULT_PARAMETERS);
128
129 // generate the server key
130 let sks = ServerKey::new(&cks);
131
132 // return
133 (cks, sks)
134}