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