pub struct ServerKey {
    pub key_switching_key: LweKeyswitchKey64,
    pub bootstrapping_key: FftFourierLweBootstrapKey64,
    pub message_modulus: MessageModulus,
    pub carry_modulus: CarryModulus,
    pub max_degree: MaxDegree,
}
Expand description

A structure containing the server public key.

The server key is generated by the client and is meant to be published: the client sends it to the server so it can compute homomorphic circuits.

Fields

key_switching_key: LweKeyswitchKey64bootstrapping_key: FftFourierLweBootstrapKey64message_modulus: MessageModuluscarry_modulus: CarryModulusmax_degree: MaxDegree

Implementations

Computes homomorphically an addition between two ciphertexts encrypting integer values.

The result is returned in a new ciphertext.

This function computes the addition without checking if it exceeds the capacity of the ciphertext.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg1 = 1;
let msg2 = 2;
let ct1 = cks.encrypt(msg1);
let ct2 = cks.encrypt(msg2);

// Compute homomorphically an addition:
let ct_res = sks.unchecked_add(&ct1, &ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!(msg1 + msg2, res);

Computes homomorphically an addition between two ciphertexts encrypting integer values.

The result is stored in the ct_left ciphertext.

This function computes the addition without checking if it exceeds the capacity of the ciphertext.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

let mut ct_left = cks.encrypt(msg);
let ct_right = cks.encrypt(msg);

// Compute homomorphically an addition:
sks.unchecked_add_assign(&mut ct_left, &ct_right);

// Decrypt:
let two = cks.decrypt(&ct_left);
assert_eq!(msg + msg, two);

Verifies if ct_left and ct_right can be added together.

This checks that the sum of their degree is smaller than the maximum degree.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg = 2;

 // Encrypt two messages:
 let ct_left = cks.encrypt(msg);
 let ct_right = cks.encrypt(msg);

 // Check if we can perform an addition
 let can_be_added = sks.is_add_possible(&ct_left, &ct_right);

 assert_eq!(can_be_added, true);

Computes homomorphically an addition between two ciphertexts encrypting integer values.

If the operation can be performed, the result is returned a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

// Encrypt two messages:
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);

// Compute homomorphically an addition:
let ct_res = sks.checked_add(&ct1, &ct2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, msg + msg);

Computes homomorphically an addition between two ciphertexts encrypting integer values.

If the operation can be performed, the result is stored in the ct_left ciphertext. Otherwise CheckError::CarryFull is returned, and ct_left is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an addition:
let res = sks.checked_add_assign(&mut ct_left, &ct_right);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct_left);
assert_eq!(clear_res, msg + msg);

Computes homomorphically an addition between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an addition:
let ct_res = sks.smart_add(&mut ct1, &mut ct2);

// Decrypt:
let two = cks.decrypt(&ct_res);
assert_eq!(msg + msg, two);

Computes homomorphically an addition between two ciphertexts

The result is stored in the ct_left cipher text.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let msg1 = 15;
let msg2 = 3;

let mut ct1 = cks.unchecked_encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);

// Compute homomorphically an addition:
sks.smart_add_assign(&mut ct1, &mut ct2);

// Decrypt:
let two = cks.decrypt(&ct1);

// 15 + 3 mod 4 -> 3 + 3 mod 4 -> 2 mod 4
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!((msg2 + msg1) % modulus, two);

Compute bitwise AND between two ciphertexts without checks.

The result is returned in a new ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 let (cks, sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_1 = 2;
 let clear_2 = 1;

 let ct_1 = cks.encrypt(clear_1);
 let ct_2 = cks.encrypt(clear_2);

 let ct_res = sks.unchecked_bitand(&ct_1, &ct_2);

 let res = cks.decrypt(&ct_res);
 assert_eq!(clear_1 & clear_2, res);

Compute bitwise AND between two ciphertexts without checks.

The result is assigned in the ct_left ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 let (cks, sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_1 = 1;
 let clear_2 = 2;

 let mut ct_left = cks.encrypt(clear_1);
 let ct_right = cks.encrypt(clear_2);

 sks.unchecked_bitand_assign(&mut ct_left, &ct_right);

 let res = cks.decrypt(&ct_left);
 assert_eq!(clear_1 & clear_2, res);

Compute bitwise AND between two ciphertexts without checks.

If the operation can be performed, the result is returned a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

// Encrypt two messages:
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);

// Compute homomorphically an AND:
let ct_res = sks.checked_bitand(&ct1, &ct2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, msg & msg);

Compute bitwise AND between two ciphertexts without checks.

If the operation can be performed, the result is stored in the ct_left ciphertext. Otherwise CheckError::CarryFull is returned, and ct_left is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an AND:
let res = sks.checked_bitand_assign(&mut ct_left, &ct_right);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct_left);
assert_eq!(clear_res, msg & msg);

Computes homomorphically an AND between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an AND:
let ct_res = sks.smart_bitand(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!(msg & msg, res);

Computes homomorphically an AND between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

The result is stored in the ct_left cipher text.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let modulus = 4;
// Encrypt two messages:
let msg1 = 15;
let msg2 = 3;

let mut ct1 = cks.unchecked_encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);

// Compute homomorphically an AND:
sks.smart_bitand_assign(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct1);

assert_eq!((msg2 & msg1) % modulus, res);

Compute bitwise XOR between two ciphertexts without checks.

The result is returned in a new ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 let (cks, sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_1 = 1;
 let clear_2 = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(clear_1);
 let ct_right = cks.encrypt(clear_2);

 let ct_res = sks.unchecked_bitxor(&ct_left, &ct_right);

 let res = cks.decrypt(&ct_res);
 assert_eq!(clear_1 ^ clear_2, res);

Compute bitwise XOR between two ciphertexts without checks.

The result is assigned in the ct_left ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 let (cks, sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_1 = 2;
 let clear_2 = 0;

 // Encrypt two messages
 let mut ct_left = cks.encrypt(clear_1);
 let mut ct_right = cks.encrypt(clear_2);

 sks.smart_bitxor(&mut ct_left, &mut ct_right);

 let res = cks.decrypt(&ct_left);
 assert_eq!(clear_1 ^ clear_2, res);

Compute bitwise XOR between two ciphertexts without checks.

If the operation can be performed, the result is returned a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

// Encrypt two messages:
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);

// Compute homomorphically a xor:
let ct_res = sks.checked_bitxor(&ct1, &ct2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, msg ^ msg);

Compute bitwise XOR between two ciphertexts without checks.

If the operation can be performed, the result is stored in the ct_left ciphertext. Otherwise CheckError::CarryFull is returned, and ct_left is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically a xor:
let res = sks.checked_bitxor_assign(&mut ct_left, &ct_right);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct_left);
assert_eq!(clear_res, msg ^ msg);

Computes homomorphically an XOR between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically a XOR:
let ct_res = sks.smart_bitxor(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!(msg ^ msg, res);

Computes homomorphically a XOR between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

The result is stored in the ct_left cipher text.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let modulus = 4;
// Encrypt two messages:
let msg1 = 15;
let msg2 = 3;

let mut ct1 = cks.unchecked_encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);

// Compute homomorphically a XOR:
sks.smart_bitxor_assign(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct1);

assert_eq!((msg2 ^ msg1) % modulus, res);

Compute bitwise OR between two ciphertexts.

The result is returned in a new ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_left = 1;
 let clear_right = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(clear_left);
 let ct_right = cks.encrypt(clear_right);

 let ct_res = sks.unchecked_bitor(&ct_left, &ct_right);

 let res = cks.decrypt(&ct_res);
 assert_eq!(clear_left | clear_right, res);

Compute bitwise OR between two ciphertexts.

The result is assigned in the ct_left ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_left = 2;
 let clear_right = 1;

 // Encrypt two messages
 let mut ct_left = cks.encrypt(clear_left);
 let ct_right = cks.encrypt(clear_right);

 sks.unchecked_bitor_assign(&mut ct_left, &ct_right);

 let res = cks.decrypt(&ct_left);
 assert_eq!(clear_left | clear_right, res);

Compute bitwise OR between two ciphertexts without checks.

If the operation can be performed, the result is returned a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

// Encrypt two messages:
let ct1 = cks.encrypt(msg);
let ct2 = cks.encrypt(msg);

// Compute homomorphically a or:
let ct_res = sks.checked_bitor(&ct1, &ct2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, msg | msg);

Compute bitwise OR between two ciphertexts without checks.

If the operation can be performed, the result is stored in the ct_left ciphertext. Otherwise CheckError::CarryFull is returned, and ct_left is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an or:
let res = sks.checked_bitor_assign(&mut ct_left, &ct_right);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct_left);
assert_eq!(clear_res, msg | msg);

Computes homomorphically an OR between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an OR:
let ct_res = sks.smart_bitor(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!(msg | msg, res);

Computes homomorphically an OR between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

The result is stored in the ct_left cipher text.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let modulus = 4;
// Encrypt two messages:
let msg1 = 15;
let msg2 = 3;

let mut ct1 = cks.unchecked_encrypt(msg1);
let mut ct2 = cks.encrypt(msg2);

// Compute homomorphically an OR:
sks.smart_bitor_assign(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct1);

assert_eq!((msg2 | msg1) % modulus, res);

Implements the “greater” (>) operator between two ciphertexts without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 1;
 let msg_2 = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);
 let ct_right = cks.encrypt(msg_2);

 let ct_res = sks.unchecked_greater(&ct_left, &ct_right);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!((msg_1 > msg_2) as u64, res);

Implements the “greater” (>) operator between two ciphertexts with checks.

If the operation can be performed, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 1;
let msg_2 = 2;

// Encrypt two messages:
let ct_left = cks.encrypt(msg_1);
let ct_right = cks.encrypt(msg_2);

let res = sks.checked_greater(&ct_left, &ct_right);

assert!(res.is_ok());
let res = res.unwrap();

let clear_res = cks.decrypt(&res);
assert_eq!((msg_1 > msg_2) as u64, clear_res);

Computes homomorphically a > between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an OR:
let ct_res = sks.smart_greater(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!((msg > msg) as u64, res);

Implements the “greater or equal” (>=) operator between two ciphertexts without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 1;
 let msg_2 = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);
 let ct_right = cks.encrypt(msg_2);

 let ct_res = sks.unchecked_greater_or_equal(&ct_left, &ct_right);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!((msg_1 >= msg_2) as u64, res);

Computes homomorphically a >= between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an OR:
let ct_res = sks.smart_greater_or_equal(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!((msg >= msg) as u64, res);

Implements the “greater or equal” (>=) operator between two ciphertexts with checks.

If the operation can be performed, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 1;
let msg_2 = 2;

// Encrypt two messages:
let ct_left = cks.encrypt(msg_1);
let ct_right = cks.encrypt(msg_2);

let res = sks.checked_greater(&ct_left, &ct_right);

assert!(res.is_ok());
let res = res.unwrap();

let clear_res = cks.decrypt(&res);
assert_eq!((msg_1 >= msg_2) as u64, clear_res);

Implements the “less” (<) operator between two ciphertexts without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 1;
 let msg_2 = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);
 let ct_right = cks.encrypt(msg_2);

 // Do the comparison
 let ct_res = sks.unchecked_less(&ct_left, &ct_right);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!((msg_1 < msg_2) as u64, res);

Implements the “less” (<) operator between two ciphertexts with checks.

If the operation can be performed, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 1;
let msg_2 = 2;

// Encrypt two messages:
let ct_left = cks.encrypt(msg_1);
let ct_right = cks.encrypt(msg_2);

let res = sks.checked_less(&ct_left, &ct_right);

assert!(res.is_ok());
let res = res.unwrap();

let clear_res = cks.decrypt(&res);
assert_eq!((msg_1 < msg_2) as u64, clear_res);

Computes homomorphically a < between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an OR:
let ct_res = sks.smart_less(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!((msg < msg) as u64, res);

Implements the “less or equal” (<=) between two ciphertexts operator without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 1;
 let msg_2 = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);
 let ct_right = cks.encrypt(msg_2);

 let ct_res = sks.unchecked_less_or_equal(&ct_left, &ct_right);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!((msg_1 <= msg_2) as u64, res);

Implements the “less or equal” (<=) operator between two ciphertexts with checks.

If the operation can be performed, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 1;
let msg_2 = 2;

// Encrypt two messages:
let ct_left = cks.encrypt(msg_1);
let ct_right = cks.encrypt(msg_2);

let res = sks.checked_less_or_equal(&ct_left, &ct_right);

assert!(res.is_ok());
let res = res.unwrap();

let clear_res = cks.decrypt(&res);
assert_eq!((msg_1 <= msg_2) as u64, clear_res);

Computes homomorphically a <= between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an OR:
let ct_res = sks.smart_less_or_equal(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!((msg >= msg) as u64, res);

Implements the “equal” operator (==) between two ciphertexts without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 2;
 let msg_2 = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);
 let ct_right = cks.encrypt(msg_2);

 let ct_res = sks.unchecked_equal(&ct_left, &ct_right);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(res, 1);

Implements the “less” (==) operator between two ciphertexts with checks.

If the operation can be performed, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 1;
let msg_2 = 2;

// Encrypt two messages:
let ct_left = cks.encrypt(msg_1);
let ct_right = cks.encrypt(msg_2);

let res = sks.checked_equal(&ct_left, &ct_right);

assert!(res.is_ok());
let res = res.unwrap();

let clear_res = cks.decrypt(&res);
assert_eq!((msg_1 == msg_2) as u64, clear_res);

Computes homomorphically a == between two ciphertexts encrypting integer values.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

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

// Compute homomorphically an OR:
let ct_res = sks.smart_equal(&mut ct1, &mut ct2);

// Decrypt:
let res = cks.decrypt(&ct_res);
assert_eq!((msg == msg) as u64, res);

Implements the “equal” operator (==) between a ciphertext and a scalar without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 2;
 let scalar = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);

 let ct_res = sks.smart_scalar_equal(&ct_left, scalar);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(res, (msg_1 == scalar as u64) as u64);

Implements the “equal” operator (>=) between a ciphertext and a scalar without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 2;
 let scalar = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);

 let ct_res = sks.smart_scalar_greater_or_equal(&ct_left, scalar);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(res, (msg_1 >= scalar as u64) as u64);

Implements the “less or equal” operator (<=) between a ciphertext and a scalar without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 2;
 let scalar = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);

 let ct_res = sks.smart_scalar_less_or_equal(&ct_left, scalar);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(res, (msg_1 <= scalar as u64) as u64);

Implements the “equal” operator (>) between a ciphertext and a scalar without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 2;
 let scalar = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);

 let ct_res = sks.smart_scalar_greater(&ct_left, scalar);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(res, (msg_1 > scalar as u64) as u64);

Implements the “less” operator (<) between a ciphertext and a scalar without checks.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg_1 = 2;
 let scalar = 2;

 // Encrypt two messages
 let ct_left = cks.encrypt(msg_1);

 let ct_res = sks.smart_scalar_less(&ct_left, scalar);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(res, (msg_1 < scalar as u64) as u64);

Compute a division between two ciphertexts without checks.

The result is returned in a new ciphertext.

Warning

/!\ A division by zero returns 0!

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear_1 = 1;
 let clear_2 = 2;

 // Encrypt two messages
 let ct_1 = cks.encrypt(clear_1);
 let ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 let ct_res = sks.unchecked_div(&ct_1, &ct_2);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(clear_1 / clear_2, res);

Compute a division between two ciphertexts without checks.

The result is assigned in ct_left.

Warning

/!\ A division by zero returns 0!

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear_1 = 1;
 let clear_2 = 2;

 // Encrypt two messages
 let mut ct_1 = cks.encrypt(clear_1);
 let ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 sks.unchecked_div_assign(&mut ct_1, &ct_2);

 // Decrypt
 let res = cks.decrypt(&ct_1);
 assert_eq!(clear_1 / clear_2, res);

Compute a division between two ciphertexts.

The result is returned in a new ciphertext.

Warning

/!\ A division by zero returns 0!

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear_1 = 1;
 let clear_2 = 2;

 // Encrypt two messages
 let mut ct_1 = cks.encrypt(clear_1);
 let mut ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 let ct_res = sks.smart_div(&mut ct_1, &mut ct_2);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(clear_1 / clear_2, res);

Compute a division between two ciphertexts without checks.

The result is assigned in ct_left.

Warning

/!\ A division by zero returns 0!

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear_1 = 3;
 let clear_2 = 2;

 // Encrypt two messages
 let mut ct_1 = cks.encrypt(clear_1);
 let mut ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 sks.unchecked_div_assign(&mut ct_1, &ct_2);

 // Decrypt
 let res = cks.decrypt(&ct_1);
 assert_eq!(clear_1 / clear_2, res);

Compute a division of a ciphertext by a scalar without checks.

Panics

This function will panic if scalar == 0.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear_1 = 3;
 let clear_2 = 2;

 // Encrypt one message
 let mut ct_1 = cks.encrypt(clear_1);

 // Compute homomorphically a multiplication
 let ct_res = sks.unchecked_scalar_div(&mut ct_1, clear_2);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!(clear_1 / (clear_2 as u64), res);

Computes homomorphically a modular reduction without checks.

Panics

This function will panic if modulus == 0.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 3;

let mut ct = cks.encrypt(msg);

let modulus: u8 = 2;
// Compute homomorphically an addition:
let ct_res = sks.unchecked_scalar_mod(&mut ct, modulus);

// Decrypt:
let dec = cks.decrypt(&ct_res);
assert_eq!(1, dec);

Multiplies two ciphertexts together without checks.

Returns the “least significant bits” of the multiplication, i.e., the result modulus the message_modulus.

The result is returned in a new ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_1_CARRY_1;

 // Generate the client key and the server key
 let (mut cks, mut sks) = gen_keys(PARAM_MESSAGE_1_CARRY_1);

 let clear_1 = 1;
 let clear_2 = 1;

 // Encrypt two messages
 let ct_1 = cks.encrypt(clear_1);
 let ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 let ct_res = sks.unchecked_mul_lsb(&ct_1, &ct_2);
 // 2*3 == 6 == 01_10 (base 2)
 // Only the message part is returned (lsb) so `ct_res` is:
 // |      ct_res     |
 // | carry | message |
 // |-------|---------|
 // |  0 0  |   1 0   |

 // Decrypt
 let res = cks.decrypt(&ct_res);
 let modulus = cks.parameters.message_modulus.0 as u64;
 assert_eq!((clear_1 * clear_2) % modulus, res);

Multiplies two ciphertexts together without checks.

Returns the “least significant bits” of the multiplication, i.e., the result modulus the message_modulus.

The result is assigned in the first ciphertext

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 // Generate the client key and the server key
 let (mut cks, mut sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_1 = 3;
 let clear_2 = 2;

 // Encrypt two messages
 let mut ct_1 = cks.encrypt(clear_1);
 let ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 sks.unchecked_mul_lsb_assign(&mut ct_1, &ct_2);

 // Decrypt
 let res = cks.decrypt(&ct_1);
 let modulus = cks.parameters.message_modulus.0 as u64;
 assert_eq!((clear_1 * clear_2) % modulus, res);

Multiplies two ciphertexts together without checks.

Returns the “most significant bits” of the multiplication, i.e., the part in the carry buffer.

The result is returned in a new ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::DEFAULT_PARAMETERS;

 // Generate the client key and the server key
 let (mut cks, mut sks) = gen_keys(DEFAULT_PARAMETERS);

 let clear_1 = 3;
 let clear_2 = 2;

 // Encrypt two messages
 let mut ct_1 = cks.encrypt(clear_1);
 let mut ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 let ct_res = sks.unchecked_mul_msb(&ct_1, &ct_2);
 // 2*3 == 6 == 01_10 (base 2)
 // however the ciphertext will contain only the carry buffer
 // as the message, the ct_res is actually:
 // |      ct_res     |
 // | carry | message |
 // |-------|---------|
 // |  0 0  |   0 1   |

 // Decrypt
 let res = cks.decrypt(&ct_res);
 let modulus = cks.parameters.message_modulus.0 as u64;
 assert_eq!((clear_1 * clear_2) / modulus, res);

Verifies if two ciphertexts can be multiplied together.

Example
 use concrete_shortint::{gen_keys, Parameters};

 // Generate the client key and the server key:
 let (mut cks, mut sks) = gen_keys(Parameters::default());

 let msg = 2;

 // Encrypt two messages:
 let ct_1 = cks.encrypt(msg);
 let ct_2 = cks.encrypt(msg);

 // Check if we can perform a multiplication
 let res = sks.is_mul_possible(&ct_1, &ct_2);

 assert_eq!(true, res);

Multiplies two ciphertexts together with checks.

Returns the “least significant bits” of the multiplication, i.e., the result modulus the message_modulus.

If the operation can be performed, a new ciphertext with the result is returned. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (mut cks, mut sks) = gen_keys(Parameters::default());

// Encrypt two messages:
let ct_1 = cks.encrypt(2);
let ct_2 = cks.encrypt(1);

// Compute homomorphically a multiplication:
let ct_res = sks.checked_mul_lsb(&ct_1, &ct_2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt_message_and_carry(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res % modulus, 2);

Multiplies two ciphertexts together with checks.

Returns the “least significant bits” of the multiplication, i.e., the result modulus the message_modulus.

If the operation can be performed, the result is assigned to the first ciphertext given as a parameter. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (mut cks, mut sks) = gen_keys(Parameters::default());

// Encrypt two messages:
let mut ct_1 = cks.encrypt(2);
let ct_2 = cks.encrypt(1);

// Compute homomorphically a multiplication:
let ct_res = sks.checked_mul_lsb_assign(&mut ct_1, &ct_2);

assert!(ct_res.is_ok());

let clear_res = cks.decrypt_message_and_carry(&ct_1);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res % modulus, 2);

Multiplies two ciphertexts together without checks.

Returns the “most significant bits” of the multiplication, i.e., the part in the carry buffer.

If the operation can be performed, a new ciphertext with the result is returned. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (mut cks, mut sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 2;
let msg_2 = 2;

// Encrypt two messages:
let ct_1 = cks.encrypt(msg_1);
let ct_2 = cks.encrypt(msg_2);

// Compute homomorphically a multiplication:
let ct_res = sks.checked_mul_msb(&ct_1, &ct_2);
assert!(ct_res.is_ok());

// 2*2 == 4 == 01_00 (base 2)
// however the ciphertext will contain only the carry buffer
// as the message, the ct_res is actually:
// |      ct_res     |
// | carry | message |
// |-------|---------|
// |  0 0  |   0 1   |

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(
    clear_res,
    (msg_1 * msg_2) / cks.parameters.message_modulus.0 as u64
);

Multiply two ciphertexts together using one bit of carry only.

The algorithm uses the (.)^2/4 trick. For more information: page 4, §Computing a multiplication in Chillotti, I., Joye, M., Ligier, D., Orfila, J. B., & Tap, S. (2020, December). CONCRETE: Concrete operates on ciphertexts rapidly by extending TfhE. In WAHC 2020–8th Workshop on Encrypted Computing & Applied Homomorphic Cryptography (Vol. 15).

Example
 use concrete_shortint::parameters::PARAM_MESSAGE_1_CARRY_1;
 use concrete_shortint::{gen_keys, Parameters};

 // Generate the client key and the server key:
 let (mut cks, mut sks) = gen_keys(PARAM_MESSAGE_1_CARRY_1);

 let clear_1 = 1;
 let clear_2 = 1;

 // Encrypt two messages
 let mut ct_1 = cks.encrypt(clear_1);
 let mut ct_2 = cks.encrypt(clear_2);

 // Compute homomorphically a multiplication
 let ct_res = sks.unchecked_mul_lsb_small_carry(&mut ct_1, &mut ct_2);

 // Decrypt
 let res = cks.decrypt(&ct_res);
 assert_eq!((clear_2 * clear_1), res);

Verifies if two ciphertexts can be multiplied together in the case where the carry modulus is smaller than the message modulus.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_1;

 // Generate the client key and the server key:
 let (mut cks, mut sks) = gen_keys(PARAM_MESSAGE_2_CARRY_1);

 let msg = 2;

 // Encrypt two messages:
 let ct_1 = cks.encrypt(msg);
 let ct_2 = cks.encrypt(msg);

 // Check if we can perform a multiplication
 let mut res = sks.is_mul_small_carry_possible(&ct_1, &ct_2);

 assert_eq!(true, res);

 //Encryption with a full carry buffer
 let large_msg = 7;
 let ct_3 = cks.unchecked_encrypt(large_msg);

 //  Check if we can perform a multiplication
 res = sks.is_mul_small_carry_possible(&ct_1, &ct_3);

 assert_eq!(false, res);

Computes homomorphically a multiplication between two ciphertexts encrypting integer values.

The operation is done using a small carry buffer.

If the operation can be performed, a new ciphertext with the result of the multiplication is returned. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (mut cks, mut sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg_1 = 2;
let msg_2 = 3;

// Encrypt two messages:
let mut ct_1 = cks.encrypt(msg_1);
let mut ct_2 = cks.encrypt(msg_2);

// Compute homomorphically a multiplication
let ct_res = sks.checked_mul_lsb_with_small_carry(&mut ct_1, &mut ct_2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res % modulus, (msg_1 * msg_2) % modulus);

Multiplies two ciphertexts.

Returns the “least significant bits” of the multiplication, i.e., the result modulus the message_modulus.

The result is assigned in the first ciphertext

Example
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_1;
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_1);

// Encrypt two messages:
let msg1 = 5;
let msg2 = 3;

let mut ct_1 = cks.unchecked_encrypt(msg1);
let mut ct_2 = cks.unchecked_encrypt(msg2);

// Compute homomorphically a multiplication
sks.smart_mul_lsb_assign(&mut ct_1, &mut ct_2);

let res = cks.decrypt(&ct_1);
let modulus = sks.message_modulus.0 as u64;
assert_eq!(res % modulus, (msg1 * msg2) % modulus);

Multiply two ciphertexts together

Returns the “least significant bits” of the multiplication, i.e., the result modulus the message_modulus.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

// Encrypt two messages:
let msg1 = 12;
let msg2 = 13;

let mut ct_left = cks.unchecked_encrypt(msg1);
// |      ct_left    |
// | carry | message |
// |-------|---------|
// |  1 1  |   0 0   |
let mut ct_right = cks.unchecked_encrypt(msg2);
// |      ct_right   |
// | carry | message |
// |-------|---------|
// |  1 1  |   0 1   |

// Compute homomorphically a multiplication:
let ct_res = sks.smart_mul_lsb(&mut ct_left, &mut ct_right);
// |      ct_res     |
// | carry | message |
// |-------|---------|
// |  0 0  |   0 0   |

let res = cks.decrypt(&ct_res);
let modulus = sks.message_modulus.0;
assert_eq!(res, (msg1 * msg2) % modulus as u64);

Multiply two ciphertexts together

Returns the “most significant bits” of the multiplication, i.e., the part in the carry buffer.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

// Encrypt two messages:
let msg1 = 12;
let msg2 = 12;

let mut ct_1 = cks.unchecked_encrypt(msg1);
let mut ct_2 = cks.unchecked_encrypt(msg2);

// Compute homomorphically a multiplication:
let ct_res = sks.smart_mul_msb(&mut ct_1, &mut ct_2);

let res = cks.decrypt(&ct_res);
let modulus = sks.carry_modulus.0;
assert_eq!(res, (msg1 * msg2) % modulus as u64);

Homomorphically negates a message without checks.

Negation here means the opposite value in the modulo set.

This function computes the opposite of a message without checking if it exceeds the capacity of the ciphertext.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (mut cks, mut sks) = gen_keys(Parameters::default());

let msg = 1;

// Encrypt a message
let ct = cks.encrypt(msg);

// Compute homomorphically a negation
let mut ct_res = sks.unchecked_neg(&ct);

// Decrypt
let three = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(modulus - msg, three);

Homomorphically negates a message inplace without checks.

Negation here means the opposite value in the modulo set.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

// Encrypt a message
let msg = 3;
let mut ct = cks.encrypt(msg);

// Compute homomorphically a negation
sks.unchecked_neg_assign(&mut ct);

// Decrypt
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(modulus - msg, cks.decrypt(&ct));

Verifies if a ciphertext can be negated.

Example
 use concrete_shortint::{gen_keys, Parameters};

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(Parameters::default());

 // Encrypt a message
 let msg = 2;
 let ct = cks.encrypt(msg);

 // Check if we can perform a negation
 let can_be_negated = sks.is_neg_possible(&ct);

 assert_eq!(can_be_negated, true);

Computes homomorphically a negation of a ciphertext.

If the operation can be performed, the result is returned a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

// Encrypt a message
let msg = 1;
let ct = cks.encrypt(msg);

// Compute homomorphically a negation:
let ct_res = sks.checked_neg(&ct);

assert!(ct_res.is_ok());

let clear_res = cks.decrypt(&ct_res.unwrap());
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res, modulus - msg);

Computes homomorphically a negation of a ciphertext.

If the operation is possible, the result is stored in the input ciphertext. Otherwise CheckError::CarryFull is returned and the ciphertext is not .

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

// Encrypt a message:
let msg = 1;
let mut ct = cks.encrypt(msg);

// Compute homomorphically the negation:
let res = sks.checked_neg_assign(&mut ct);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res, modulus - msg);

Computes homomorphically a negation of a ciphertext.

This checks that the negation is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

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

// Compute homomorphically a negation
let ct_res = sks.smart_neg(&mut ct);

// Decrypt
let clear_res = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res, modulus - msg);

Computes homomorphically a negation of a ciphertext.

This checks that the addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::{gen_keys, Parameters};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(Parameters::default());

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

// Compute homomorphically a negation
sks.smart_neg_assign(&mut ct);

// Decrypt
let clear_res = cks.decrypt(&ct);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res, modulus - msg);

Computes homomorphically an addition between a ciphertext and a scalar.

The result is returned in a new ciphertext.

This function does not check whether the capacity of the ciphertext is exceeded.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let ct = cks.encrypt(1);

// Compute homomorphically a scalar addition:
let ct_res = sks.unchecked_scalar_add(&ct, 2);

let clear = cks.decrypt(&ct_res);
assert_eq!(3, clear);

Computes homomorphically an addition between a ciphertext and a scalar.

The result it stored in the given ciphertext.

This function does not check whether the capacity of the ciphertext is exceeded.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let mut ct = cks.encrypt(1);

// Compute homomorphically a scalar addition:
sks.unchecked_scalar_add_assign(&mut ct, 2);

let clear = cks.decrypt(&ct);
assert_eq!(3, clear);

Verifies if a scalar can be added to the ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let ct = cks.encrypt(2);

 // Verification if the scalar addition can be computed:
 let can_be_computed = sks.is_scalar_add_possible(&ct, 3);

 assert_eq!(can_be_computed, true);

Computes homomorphically an addition between a ciphertext and a scalar.

If the operation is possible, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt a message:
let ct = cks.encrypt(1);

// Compute homomorphically a addition multiplication:
let ct_res = sks.checked_scalar_add(&ct, 2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, 3);

Computes homomorphically an addition between a ciphertext and a scalar.

If the operation is possible, the result is stored in the input ciphertext. Otherwise CheckError::CarryFull is returned and the ciphertext is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt a message:
let mut ct = cks.encrypt(1);

// Compute homomorphically a scalar addition:
let res = sks.checked_scalar_add_assign(&mut ct, 2);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct);
assert_eq!(clear_res, 3);

Computes homomorphically an addition between a ciphertext and a scalar.

The result is returned in a new ciphertext.

This checks that the scalar addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1_u64;
let scalar = 9_u8;

let mut ct = cks.encrypt(msg);

// Compute homomorphically a scalar multiplication:
let ct_res = sks.smart_scalar_add(&mut ct, scalar);

// The input ciphertext content is not changed
assert_eq!(cks.decrypt(&ct), msg);

// Our result is what we expect
let clear = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(2, clear % modulus);

Computes homomorphically an addition of a ciphertext by a scalar.

The result is stored in the ct ciphertext.

This checks that the scalar addition is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1_u64;
let scalar = 5_u8;

let mut ct = cks.encrypt(msg);

// Compute homomorphically a scalar multiplication:
sks.smart_scalar_add_assign(&mut ct, scalar);

// Our result is what we expect
let clear = cks.decrypt_message_and_carry(&ct);
assert_eq!(6, clear);

Computes homomorphically a multiplication of a ciphertext by a scalar.

The result is returned in a new ciphertext.

The operation is modulo the the precision bits to the power of two.

This function does not check whether the capacity of the ciphertext is exceeded.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let ct = cks.encrypt(1);

// Compute homomorphically a scalar multiplication:
let ct_res = sks.unchecked_scalar_mul(&ct, 3);

let clear = cks.decrypt(&ct_res);
assert_eq!(3, clear);

Computes homomorphically a multiplication of a ciphertext by a scalar.

The result it stored in the given ciphertext.

The operation is modulo the the precision bits to the power of two.

This function does not check whether the capacity of the ciphertext is exceeded.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let mut ct = cks.encrypt(1);

// Compute homomorphically a scalar multiplication:
sks.unchecked_scalar_mul_assign(&mut ct, 3);

let clear = cks.decrypt(&ct);
assert_eq!(3, clear);

Verifies if the ciphertext can be multiplied by a scalar.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let ct = cks.encrypt(2);

 // Verification if the scalar multiplication can be computed:
 let can_be_computed = sks.is_scalar_mul_possible(&ct, 3);

 assert_eq!(can_be_computed, true);

Computes homomorphically a multiplication of a ciphertext by a scalar.

If the operation is possible, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

The operation is modulo the precision bits to the power of two.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt a message:
let ct = cks.encrypt(1);

// Compute homomorphically a scalar multiplication:
let ct_res = sks.checked_scalar_mul(&ct, 3);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, 3);

Computes homomorphically a multiplication of a ciphertext by a scalar.

If the operation is possible, the result is stored in the input ciphertext. Otherwise CheckError::CarryFull is returned and the ciphertext is not .

The operation is modulo the precision bits to the power of two.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt a message:
let mut ct = cks.encrypt(1);

// Compute homomorphically a scalar multiplication:
let res = sks.checked_scalar_mul_assign(&mut ct, 3);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct);
assert_eq!(clear_res, 3);

Computes homomorphically a multiplication of a ciphertext by a scalar.

This checks that the multiplication is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1_u64;
let scalar = 3_u8;

let mut ct = cks.encrypt(msg);

// Compute homomorphically a scalar multiplication:
let ct_res = sks.smart_scalar_mul(&mut ct, scalar);

// The input ciphertext content is not changed
assert_eq!(cks.decrypt(&ct), msg);

// Our result is what we expect
let clear = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(3, clear % modulus);

Computes homomorphically a multiplication of a ciphertext by a scalar.

This checks that the multiplication is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1_u64;
let scalar = 3_u8;

let mut ct = cks.encrypt(msg);

// Compute homomorphically a scalar multiplication:
sks.smart_scalar_mul_assign(&mut ct, scalar);

// Our result is what we expect
let clear = cks.decrypt(&ct);
assert_eq!(3, clear);

Computes homomorphically a subtraction of a ciphertext by a scalar.

The result is returned in a new ciphertext.

This function does not check whether the capacity of the ciphertext is exceeded.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let ct = cks.encrypt(5);

// Compute homomorphically a scalar subtraction:
let ct_res = sks.unchecked_scalar_sub(&ct, 6);

// 5 - 6 mod 4 = 3 mod 4
let clear = cks.decrypt(&ct_res);
assert_eq!(3, clear);

Computes homomorphically a subtraction of a ciphertext by a scalar.

The result it stored in the given ciphertext.

This function does not check whether the capacity of the ciphertext is exceeded.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let mut ct = cks.encrypt(5);

// Compute homomorphically a scalar subtraction:
sks.unchecked_scalar_sub_assign(&mut ct, 2);

let clear = cks.decrypt(&ct);
assert_eq!(3, clear);

Verifies if a scalar can be subtracted to the ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let ct = cks.encrypt(5);

 // Verification if the scalar subtraction can be computed:
 let can_be_computed = sks.is_scalar_sub_possible(&ct, 3);

 assert_eq!(can_be_computed, true);

Computes homomorphically a subtraction of a ciphertext by a scalar.

If the operation is possible, the result is returned in a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt a message:
let ct = cks.encrypt(5);

// Compute homomorphically a subtraction multiplication:
let ct_res = sks.checked_scalar_sub(&ct, 2);

assert!(ct_res.is_ok());

let ct_res = ct_res.unwrap();
let clear_res = cks.decrypt(&ct_res);
assert_eq!(clear_res, 3);

Computes homomorphically a subtraction of a ciphertext by a scalar.

If the operation is possible, the result is stored in the input ciphertext. Otherwise CheckError::CarryFull is returned and the ciphertext is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt a message:
let mut ct = cks.encrypt(5);

// Compute homomorphically a scalar subtraction:
let res = sks.checked_scalar_sub_assign(&mut ct, 2);

assert!(res.is_ok());

let clear_res = cks.decrypt(&ct);
assert_eq!(clear_res, 3);

Computes homomorphically a subtraction of a ciphertext by a scalar.

The result is returned in a new ciphertext.

This checks that the scalar subtraction is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 3;
let scalar = 3;

let mut ct = cks.encrypt(msg);

// Compute homomorphically a scalar multiplication:
let ct_res = sks.smart_scalar_sub(&mut ct, scalar);

// The input ciphertext content is not changed
assert_eq!(cks.decrypt(&ct), msg);

// Our result is what we expect
let clear = cks.decrypt(&ct_res);

assert_eq!(msg - scalar as u64, clear);

Computes homomorphically a subtraction of a ciphertext by a scalar.

The result is stored in the ct ciphertext.

This checks that the scalar subtraction is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 5;
let scalar = 3;

let mut ct = cks.encrypt(msg);

// Compute homomorphically a scalar multiplication:
sks.smart_scalar_sub_assign(&mut ct, scalar);

// Our result is what we expect
let clear = cks.decrypt(&ct);
assert_eq!(msg - scalar as u64, clear);

Computes homomorphically a right shift of the bits without checks.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 2;
let ct = cks.encrypt(msg);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

// Compute homomorphically a right shift
let shift: u8 = 1;
let ct_res = sks.unchecked_scalar_right_shift(&ct, shift);
// |      ct_res     |
// | carry | message |
// |-------|---------|
// |  0 0  |   0 1   |

// Decrypt:
let dec = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(msg >> shift, dec);

Computes homomorphically a right shift of the bits without checks.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 2;
let mut ct = cks.encrypt(msg);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

// Compute homomorphically a right shift
let shift: u8 = 1;
sks.unchecked_scalar_right_shift_assign(&mut ct, shift);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   0 1   |

// Decrypt:
let dec = cks.decrypt(&ct);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(msg >> shift, dec);

Computes homomorphically a left shift of the bits without checks.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 2;

let ct = cks.encrypt(msg);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

// Compute homomorphically a left shift
let shift: u8 = 1;
let ct_res = sks.unchecked_scalar_left_shift(&ct, shift);
// |      ct_res     |
// | carry | message |
// |-------|---------|
// |  0 1  |   0 0   |

// Decrypt:
let msg_and_carry = cks.decrypt_message_and_carry(&ct_res);
let msg_only = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;

assert_eq!(msg << shift, msg_and_carry);
assert_eq!((msg << shift) % modulus, msg_only);

Computes homomorphically a left shift of the bits without checks

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 2;
let mut ct = cks.encrypt(msg);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

// Compute homomorphically a left shift
let shift: u8 = 1;
sks.unchecked_scalar_left_shift_assign(&mut ct, shift);
// |      ct     |
// | carry | message |
// |-------|---------|
// |  0 1  |   0 0   |

// Decrypt:
let msg_and_carry = cks.decrypt_message_and_carry(&ct);
let msg_only = cks.decrypt(&ct);
let modulus = cks.parameters.message_modulus.0 as u64;

assert_eq!(msg << shift, msg_and_carry);
assert_eq!((msg << shift) % modulus, msg_only);

Checks if the left shift operation can be applied.

Example
 use concrete_shortint::{gen_keys, Parameters};

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(Parameters::default());

 let msg = 2;
 let shift = 5;
 let ct1 = cks.encrypt(msg);

 // Check if we can perform an addition
 let res = sks.is_scalar_left_shift_possible(&ct1, shift);

 assert_eq!(false, res);

Computes homomorphically a left shift of the bits.

If the operation can be performed, a new ciphertext with the result is returned. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 2;

let ct1 = cks.encrypt(msg);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

// Shifting 3 times is not ok, as it exceeds the carry buffer
let ct_res = sks.checked_scalar_left_shift(&ct1, 3);
assert!(ct_res.is_err());

// Shifting 2 times is ok
let shift = 2;
let ct_res = sks.checked_scalar_left_shift(&ct1, shift);
assert!(ct_res.is_ok());
let ct_res = ct_res.unwrap();
// |      ct_res     |
// | carry | message |
// |-------|---------|
// |  1 0  |   0 0   |

// Decrypt:
let msg_and_carry = cks.decrypt_message_and_carry(&ct_res);
let msg_only = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;

assert_eq!(msg << shift, msg_and_carry);
assert_eq!((msg << shift) % modulus, msg_only);

Computes homomorphically a left shift of the bits

This checks that the operation is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 2;
let mut ct = cks.encrypt(msg);
// |       ct        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

let shift: u8 = 1;
let ct_res = sks.smart_scalar_left_shift(&mut ct, shift);
// |      ct_res     |
// | carry | message |
// |-------|---------|
// |  0 1  |   0 0   |

// Decrypt:
let msg_and_carry = cks.decrypt_message_and_carry(&ct_res);
let msg_only = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;

assert_eq!(msg << shift, msg_and_carry);
assert_eq!((msg << shift) % modulus, msg_only);

Homomorphically subtracts ct_right to ct_left.

The result is returned in a new ciphertext.

This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let ct_1 = cks.encrypt(2);
let ct_2 = cks.encrypt(1);

// Compute homomorphically a subtraction:
let ct_res = sks.unchecked_sub(&ct_1, &ct_2);

// Decrypt:
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(cks.decrypt(&ct_res), 2 - 1);

Homomorphically subtracts ct_right to ct_left.

The result is assigned in the ct_left ciphertext.

This function computes the subtraction without checking if it exceeds the capacity of the ciphertext.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let mut ct_1 = cks.encrypt(2);
let ct_2 = cks.encrypt(1);

// Compute homomorphically a subtraction:
sks.unchecked_sub_assign(&mut ct_1, &ct_2);

// Decrypt:
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(cks.decrypt(&ct_1) % modulus, 1);

Verifies if ct_right can be subtracted to ct_left.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let msg = 2;

 // Encrypt two messages:
 let ct_1 = cks.encrypt(msg);
 let ct_2 = cks.encrypt(msg);

 // Check if we can perform an subtraction
 let can_be_subtracted = sks.is_sub_possible(&ct_1, &ct_2);

 assert_eq!(true, can_be_subtracted);

Computes homomorphically a subtraction between two ciphertexts encrypting integer values.

If the operation can be performed, the result is returned a new ciphertext. Otherwise CheckError::CarryFull is returned.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let ct_1 = cks.encrypt(3);
let ct_2 = cks.encrypt(1);

// Compute homomorphically a subtraction:
let ct_res = sks.checked_sub(&ct_1, &ct_2);

assert!(ct_res.is_ok());
let modulus = cks.parameters.message_modulus.0 as u64;
let clear_res = cks.decrypt(&ct_res.unwrap());
assert_eq!(clear_res % modulus, 2);

Computes homomorphically a subtraction between two ciphertexts.

If the operation can be performed, the result is stored in the ct_left ciphertext. Otherwise CheckError::CarryFull is returned, and ct_left is not modified.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let mut ct_1 = cks.encrypt(3);
let ct_2 = cks.encrypt(1);

// Compute homomorphically a subtraction:
let res = sks.checked_sub_assign(&mut ct_1, &ct_2);

assert!(res.is_ok());
let modulus = cks.parameters.message_modulus.0 as u64;
let clear_res = cks.decrypt(&ct_1);
assert_eq!(clear_res % modulus, 2);

Computes homomorphically a subtraction between two ciphertexts.

This checks that the subtraction is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let mut ct_1 = cks.encrypt(3);
let mut ct_2 = cks.encrypt(1);

// Compute homomorphically a subtraction:
let ct_res = sks.smart_sub(&mut ct_1, &mut ct_2);

let clear_res = cks.decrypt(&ct_res);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(clear_res % modulus, 2);

Computes homomorphically a subtraction between two ciphertexts.

This checks that the subtraction is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Encrypt two messages:
let mut ct_1 = cks.encrypt(3);
let mut ct_2 = cks.encrypt(1);

// Compute homomorphically a subtraction:
sks.smart_sub_assign(&mut ct_1, &mut ct_2);
let modulus = cks.parameters.message_modulus.0 as u64;
assert_eq!(cks.decrypt(&ct_1) % modulus, 2);

Computes homomorphically a subtraction between two ciphertexts without checks, and returns a correcting term.

This checks that the subtraction is possible. In the case where the carry buffers are full, then it is automatically cleared to allow the operation.

Warning

This is an advanced functionality, needed for internal requirements.

Computes homomorphically a subtraction between two ciphertexts without checks, and returns a correcting term.

Warning

This is an advanced functionality, needed for internal requirements.

Computes homomorphically a subtraction between two ciphertexts without checks, and returns a correcting term.

Warning

This is an advanced functionality, needed for internal requirements.

Generates a server key.

Example
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;
use concrete_shortint::{gen_keys, ServerKey};

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

// Generate the server key:
let sks = ServerKey::new(&cks);

Generates a server key with a chosen maximum degree

Constructs the accumulator given a function as input.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 3;

let ct = cks.encrypt(msg);

// Generate the accumulator for the function f: x -> x^2 mod 2^2
let f = |x| x ^ 2 % 4;

let acc = sks.generate_accumulator(f);
let ct_res = sks.keyswitch_programmable_bootstrap(&ct, &acc);

let dec = cks.decrypt(&ct_res);
// 3^2 mod 4 = 1
assert_eq!(dec, f(msg));

Computes a keyswitch and a bootstrap, returning a new ciphertext with empty carry bits.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let mut ct1 = cks.encrypt(3);
// |      ct1        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 1   |
let mut ct2 = cks.encrypt(2);
// |      ct2        |
// | carry | message |
// |-------|---------|
// |  0 0  |   1 0   |

let ct_res = sks.smart_add(&mut ct1, &mut ct2);
// |     ct_res      |
// | carry | message |
// |-------|---------|
// |  0 1  |   0 1   |

// Get the carry
let ct_carry = sks.carry_extract(&ct_res);
let carry = cks.decrypt(&ct_carry);
assert_eq!(carry, 1);

let ct_res = sks.keyswitch_bootstrap(&ct_res);

let ct_carry = sks.carry_extract(&ct_res);
let carry = cks.decrypt(&ct_carry);
assert_eq!(carry, 0);

let clear = cks.decrypt(&ct_res);

assert_eq!(clear, (3 + 2) % 4);

Computes a keyswitch and programmable bootstrap.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg: u64 = 3;
let ct = cks.encrypt(msg);
let modulus = cks.parameters.message_modulus.0 as u64;

// Generate the accumulator for the function f: x -> x^3 mod 2^2
let acc = sks.generate_accumulator(|x| x * x * x % modulus);
let ct_res = sks.keyswitch_programmable_bootstrap(&ct, &acc);

let dec = cks.decrypt(&ct_res);
// 3^3 mod 4 = 3
assert_eq!(dec, (msg * msg * msg) % modulus);

Generic programmable bootstrap where messages are concatenated into one ciphertext to compute bivariate functions. This is used to apply many binary operations (comparisons, multiplications, division).

Verifies if a bivariate functional pbs can be applied on ct_left and ct_right.

Replace the input encrypted message by the value of its carry buffer.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear = 9;

 // Encrypt a message
 let mut ct = cks.unchecked_encrypt(clear);

 // |       ct        |
 // | carry | message |
 // |-------|---------|
 // |  1 0  |   0 1   |

 // Compute homomorphically carry extraction
 sks.carry_extract_assign(&mut ct);

 // |       ct        |
 // | carry | message |
 // |-------|---------|
 // |  0 0  |   1 0   |

 // Decrypt:
 let res = cks.decrypt_message_and_carry(&ct);
 assert_eq!(2, res);

Extracts a new ciphertext encrypting the input carry buffer.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear = 9;

 // Encrypt a message
 let ct = cks.unchecked_encrypt(clear);

 // |       ct        |
 // | carry | message |
 // |-------|---------|
 // |  1 0  |   0 1   |

 // Compute homomorphically carry extraction
 let ct_res = sks.carry_extract(&ct);

 // |     ct_res      |
 // | carry | message |
 // |-------|---------|
 // |  0 0  |   1 0   |

 // Decrypt:
 let res = cks.decrypt(&ct_res);
 assert_eq!(2, res);

Clears the carry buffer of the input ciphertext.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

 let clear = 9;

 // Encrypt a message
 let mut ct = cks.unchecked_encrypt(clear);

 // |       ct        |
 // | carry | message |
 // |-------|---------|
 // |  1 0  |   0 1   |

 // Compute homomorphically the message extraction
 sks.message_extract_assign(&mut ct);

 // |       ct        |
 // | carry | message |
 // |-------|---------|
 // |  0 0  |   0 1   |

 // Decrypt:
 let res = cks.decrypt(&ct);
 assert_eq!(1, res);

Extracts a new ciphertext containing only the message i.e., with a cleared carry buffer.

Example
 use concrete_shortint::gen_keys;
 use concrete_shortint::parameters::PARAM_MESSAGE_1_CARRY_1;

 // Generate the client key and the server key:
 let (cks, sks) = gen_keys(PARAM_MESSAGE_1_CARRY_1);

 let clear = 9;

 // Encrypt a message
 let ct = cks.unchecked_encrypt(clear);

 // |       ct        |
 // | carry | message |
 // |-------|---------|
 // |  1 0  |   0 1   |

 // Compute homomorphically the message extraction
 let ct_res = sks.message_extract(&ct);

 // |     ct_res      |
 // | carry | message |
 // |-------|---------|
 // |  0 0  |   0 1   |

 // Decrypt:
 let res = cks.decrypt(&ct_res);
 assert_eq!(1, res);

Computes a trivial shortint from a given value.

Example
use concrete_shortint::gen_keys;
use concrete_shortint::parameters::PARAM_MESSAGE_2_CARRY_2;

// Generate the client key and the server key:
let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

let msg = 1;

// Trivial encryption
let ct1 = sks.create_trivial(msg);

let ct_res = cks.decrypt(&ct1);
assert_eq!(1, ct_res);

Trait Implementations

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
Should always be Self
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.