Struct concrete_shortint::server_key::ServerKey
source · 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: LweKeyswitchKey64
bootstrapping_key: FftFourierLweBootstrapKey64
message_modulus: MessageModulus
carry_modulus: CarryModulus
max_degree: MaxDegree
Implementations
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_add(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_add(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_add_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_add_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn is_add_possible(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> bool
pub fn is_add_possible(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> bool
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);
sourcepub fn checked_add(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_add(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_add_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
pub fn checked_add_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
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);
sourcepub fn smart_add(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_add(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_add_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_add_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_bitand(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_bitand(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_bitand_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_bitand_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn checked_bitand(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_bitand(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_bitand_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
pub fn checked_bitand_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
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);
sourcepub fn smart_bitand(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_bitand(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_bitand_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_bitand_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
sourcepub fn unchecked_bitxor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_bitxor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_bitxor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_bitxor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn checked_bitxor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_bitxor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_bitxor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
pub fn checked_bitxor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
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);
sourcepub fn smart_bitxor(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_bitxor(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_bitxor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_bitxor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
sourcepub fn unchecked_bitor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_bitor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_bitor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_bitor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn checked_bitor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_bitor(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_bitor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
pub fn checked_bitor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
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);
sourcepub fn smart_bitor(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_bitor(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_bitor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_bitor_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_greater(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_greater(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn checked_greater(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_greater(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn smart_greater(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_greater(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_greater_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_greater_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_greater_or_equal(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_greater_or_equal(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn checked_greater_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_greater_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn unchecked_less(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_less(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn checked_less(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_less(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn smart_less(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_less(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_less_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_less_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn checked_less_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_less_or_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn smart_less_or_equal(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_less_or_equal(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn checked_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_equal(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn smart_equal(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_equal(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_scalar_equal(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
pub fn smart_scalar_equal(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn smart_scalar_greater_or_equal(
&self,
ct_left: &Ciphertext,
scalar: u8
) -> Ciphertext
pub fn smart_scalar_greater_or_equal(
&self,
ct_left: &Ciphertext,
scalar: u8
) -> Ciphertext
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);
sourcepub fn smart_scalar_less_or_equal(
&self,
ct_left: &Ciphertext,
scalar: u8
) -> Ciphertext
pub fn smart_scalar_less_or_equal(
&self,
ct_left: &Ciphertext,
scalar: u8
) -> Ciphertext
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);
sourcepub fn smart_scalar_greater(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
pub fn smart_scalar_greater(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn smart_scalar_less(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
pub fn smart_scalar_less(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_div(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_div(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_div_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_div_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn smart_div(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_div(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_div_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_div_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
sourcepub fn unchecked_scalar_div(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
pub fn unchecked_scalar_div(&self, ct_left: &Ciphertext, scalar: u8) -> Ciphertext
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);
pub fn unchecked_scalar_div_assign(&self, ct_left: &mut Ciphertext, scalar: u8)
sourcepub fn unchecked_scalar_mod(
&self,
ct_left: &Ciphertext,
modulus: u8
) -> Ciphertext
pub fn unchecked_scalar_mod(
&self,
ct_left: &Ciphertext,
modulus: u8
) -> Ciphertext
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);
pub fn unchecked_scalar_mod_assign(&self, ct_left: &mut Ciphertext, modulus: u8)
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_mul_lsb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_mul_lsb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_mul_lsb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_mul_lsb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn unchecked_mul_msb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_mul_msb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
pub fn unchecked_mul_msb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
sourcepub fn is_mul_possible(&self, ct1: &Ciphertext, ct2: &Ciphertext) -> bool
pub fn is_mul_possible(&self, ct1: &Ciphertext, ct2: &Ciphertext) -> bool
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);
sourcepub fn checked_mul_lsb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_mul_lsb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_mul_lsb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
pub fn checked_mul_lsb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
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);
sourcepub fn checked_mul_msb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_mul_msb(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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
);
sourcepub fn unchecked_mul_lsb_small_carry(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn unchecked_mul_lsb_small_carry(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
pub fn unchecked_mul_lsb_small_carry_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
sourcepub fn is_mul_small_carry_possible(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> bool
pub fn is_mul_small_carry_possible(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> bool
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);
sourcepub fn checked_mul_lsb_with_small_carry(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_mul_lsb_with_small_carry(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn smart_mul_lsb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_mul_lsb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
pub fn smart_mul_msb_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
sourcepub fn smart_mul_lsb(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_mul_lsb(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_mul_msb(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_mul_msb(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_neg(&self, ct: &Ciphertext) -> Ciphertext
pub fn unchecked_neg(&self, ct: &Ciphertext) -> Ciphertext
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);
pub fn unchecked_neg_with_z(&self, ct: &Ciphertext) -> (Ciphertext, u64)
sourcepub fn unchecked_neg_assign(&self, ct: &mut Ciphertext)
pub fn unchecked_neg_assign(&self, ct: &mut Ciphertext)
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));
pub fn unchecked_neg_assign_with_z(&self, ct: &mut Ciphertext) -> u64
sourcepub fn is_neg_possible(&self, ct: &Ciphertext) -> bool
pub fn is_neg_possible(&self, ct: &Ciphertext) -> bool
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);
sourcepub fn checked_neg(&self, ct: &Ciphertext) -> Result<Ciphertext, CheckError>
pub fn checked_neg(&self, ct: &Ciphertext) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_neg_assign(&self, ct: &mut Ciphertext) -> Result<(), CheckError>
pub fn checked_neg_assign(&self, ct: &mut Ciphertext) -> Result<(), CheckError>
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);
sourcepub fn smart_neg(&self, ct: &mut Ciphertext) -> Ciphertext
pub fn smart_neg(&self, ct: &mut Ciphertext) -> Ciphertext
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);
sourcepub fn smart_neg_assign(&self, ct: &mut Ciphertext)
pub fn smart_neg_assign(&self, ct: &mut Ciphertext)
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_scalar_add(&self, ct: &Ciphertext, scalar: u8) -> Ciphertext
pub fn unchecked_scalar_add(&self, ct: &Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn unchecked_scalar_add_assign(&self, ct: &mut Ciphertext, scalar: u8)
pub fn unchecked_scalar_add_assign(&self, ct: &mut Ciphertext, scalar: u8)
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);
pub fn unchecked_scalar_add_assign_crt(&self, ct: &mut Ciphertext, scalar: u8)
sourcepub fn is_scalar_add_possible(&self, ct: &Ciphertext, scalar: u8) -> bool
pub fn is_scalar_add_possible(&self, ct: &Ciphertext, scalar: u8) -> bool
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);
sourcepub fn checked_scalar_add(
&self,
ct: &Ciphertext,
scalar: u8
) -> Result<Ciphertext, CheckError>
pub fn checked_scalar_add(
&self,
ct: &Ciphertext,
scalar: u8
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_scalar_add_assign(
&self,
ct: &mut Ciphertext,
scalar: u8
) -> Result<(), CheckError>
pub fn checked_scalar_add_assign(
&self,
ct: &mut Ciphertext,
scalar: u8
) -> Result<(), CheckError>
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);
sourcepub fn smart_scalar_add(&self, ct: &mut Ciphertext, scalar: u8) -> Ciphertext
pub fn smart_scalar_add(&self, ct: &mut Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn smart_scalar_add_assign(&self, ct: &mut Ciphertext, scalar: u8)
pub fn smart_scalar_add_assign(&self, ct: &mut Ciphertext, scalar: u8)
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_scalar_mul(&self, ct: &Ciphertext, scalar: u8) -> Ciphertext
pub fn unchecked_scalar_mul(&self, ct: &Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn unchecked_scalar_mul_assign(&self, ct: &mut Ciphertext, scalar: u8)
pub fn unchecked_scalar_mul_assign(&self, ct: &mut Ciphertext, scalar: u8)
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);
sourcepub fn is_scalar_mul_possible(&self, ct: &Ciphertext, scalar: u8) -> bool
pub fn is_scalar_mul_possible(&self, ct: &Ciphertext, scalar: u8) -> bool
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);
sourcepub fn checked_scalar_mul(
&self,
ct: &Ciphertext,
scalar: u8
) -> Result<Ciphertext, CheckError>
pub fn checked_scalar_mul(
&self,
ct: &Ciphertext,
scalar: u8
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_scalar_mul_assign(
&self,
ct: &mut Ciphertext,
scalar: u8
) -> Result<(), CheckError>
pub fn checked_scalar_mul_assign(
&self,
ct: &mut Ciphertext,
scalar: u8
) -> Result<(), CheckError>
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);
sourcepub fn smart_scalar_mul(&self, ct: &mut Ciphertext, scalar: u8) -> Ciphertext
pub fn smart_scalar_mul(&self, ct: &mut Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn smart_scalar_mul_assign(&self, ct: &mut Ciphertext, scalar: u8)
pub fn smart_scalar_mul_assign(&self, ct: &mut Ciphertext, scalar: u8)
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_scalar_sub(&self, ct: &Ciphertext, scalar: u8) -> Ciphertext
pub fn unchecked_scalar_sub(&self, ct: &Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn unchecked_scalar_sub_assign(&self, ct: &mut Ciphertext, scalar: u8)
pub fn unchecked_scalar_sub_assign(&self, ct: &mut Ciphertext, scalar: u8)
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);
sourcepub fn is_scalar_sub_possible(&self, ct: &Ciphertext, scalar: u8) -> bool
pub fn is_scalar_sub_possible(&self, ct: &Ciphertext, scalar: u8) -> bool
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);
sourcepub fn checked_scalar_sub(
&self,
ct: &Ciphertext,
scalar: u8
) -> Result<Ciphertext, CheckError>
pub fn checked_scalar_sub(
&self,
ct: &Ciphertext,
scalar: u8
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_scalar_sub_assign(
&self,
ct: &mut Ciphertext,
scalar: u8
) -> Result<(), CheckError>
pub fn checked_scalar_sub_assign(
&self,
ct: &mut Ciphertext,
scalar: u8
) -> Result<(), CheckError>
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);
sourcepub fn smart_scalar_sub(&self, ct: &mut Ciphertext, scalar: u8) -> Ciphertext
pub fn smart_scalar_sub(&self, ct: &mut Ciphertext, scalar: u8) -> Ciphertext
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);
sourcepub fn smart_scalar_sub_assign(&self, ct: &mut Ciphertext, scalar: u8)
pub fn smart_scalar_sub_assign(&self, ct: &mut Ciphertext, scalar: u8)
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);
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_scalar_right_shift(
&self,
ct: &Ciphertext,
shift: u8
) -> Ciphertext
pub fn unchecked_scalar_right_shift(
&self,
ct: &Ciphertext,
shift: u8
) -> Ciphertext
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);
sourcepub fn unchecked_scalar_right_shift_assign(&self, ct: &mut Ciphertext, shift: u8)
pub fn unchecked_scalar_right_shift_assign(&self, ct: &mut Ciphertext, shift: u8)
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);
sourcepub fn unchecked_scalar_left_shift(
&self,
ct: &Ciphertext,
shift: u8
) -> Ciphertext
pub fn unchecked_scalar_left_shift(
&self,
ct: &Ciphertext,
shift: u8
) -> Ciphertext
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);
sourcepub fn unchecked_scalar_left_shift_assign(&self, ct: &mut Ciphertext, shift: u8)
pub fn unchecked_scalar_left_shift_assign(&self, ct: &mut Ciphertext, shift: u8)
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);
sourcepub fn is_scalar_left_shift_possible(&self, ct1: &Ciphertext, shift: u8) -> bool
pub fn is_scalar_left_shift_possible(&self, ct1: &Ciphertext, shift: u8) -> bool
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);
sourcepub fn checked_scalar_left_shift(
&self,
ct: &Ciphertext,
shift: u8
) -> Result<Ciphertext, CheckError>
pub fn checked_scalar_left_shift(
&self,
ct: &Ciphertext,
shift: u8
) -> Result<Ciphertext, CheckError>
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);
pub fn checked_scalar_left_shift_assign(
&self,
ct: &mut Ciphertext,
shift: u8
) -> Result<(), CheckError>
sourcepub fn smart_scalar_left_shift(
&self,
ct: &mut Ciphertext,
shift: u8
) -> Ciphertext
pub fn smart_scalar_left_shift(
&self,
ct: &mut Ciphertext,
shift: u8
) -> Ciphertext
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);
pub fn smart_scalar_left_shift_assign(&self, ct: &mut Ciphertext, shift: u8)
sourceimpl ServerKey
impl ServerKey
sourcepub fn unchecked_sub(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
pub fn unchecked_sub(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Ciphertext
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);
sourcepub fn unchecked_sub_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
pub fn unchecked_sub_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
)
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);
sourcepub fn is_sub_possible(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> bool
pub fn is_sub_possible(&self, ct_left: &Ciphertext, ct_right: &Ciphertext) -> bool
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);
sourcepub fn checked_sub(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
pub fn checked_sub(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> Result<Ciphertext, CheckError>
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);
sourcepub fn checked_sub_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
pub fn checked_sub_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> Result<(), CheckError>
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);
sourcepub fn smart_sub(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
pub fn smart_sub(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> Ciphertext
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);
sourcepub fn smart_sub_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
pub fn smart_sub_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
)
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);
sourcepub fn unchecked_sub_with_correcting_term(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> (Ciphertext, u64)
pub fn unchecked_sub_with_correcting_term(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext
) -> (Ciphertext, u64)
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.
sourcepub fn unchecked_sub_with_correcting_term_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> u64
pub fn unchecked_sub_with_correcting_term_assign(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext
) -> u64
Computes homomorphically a subtraction between two ciphertexts without checks, and returns a correcting term.
Warning
This is an advanced functionality, needed for internal requirements.
sourcepub fn smart_sub_with_correcting_term(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> (Ciphertext, u64)
pub fn smart_sub_with_correcting_term(
&self,
ct_left: &mut Ciphertext,
ct_right: &mut Ciphertext
) -> (Ciphertext, u64)
Computes homomorphically a subtraction between two ciphertexts without checks, and returns a correcting term.
Warning
This is an advanced functionality, needed for internal requirements.
sourceimpl ServerKey
impl ServerKey
sourcepub fn new(cks: &ClientKey) -> ServerKey
pub fn new(cks: &ClientKey) -> ServerKey
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);
sourcepub fn new_with_max_degree(cks: &ClientKey, max_degree: MaxDegree) -> ServerKey
pub fn new_with_max_degree(cks: &ClientKey, max_degree: MaxDegree) -> ServerKey
Generates a server key with a chosen maximum degree
sourcepub fn generate_accumulator<F>(&self, f: F) -> GlweCiphertext64where
F: Fn(u64) -> u64,
pub fn generate_accumulator<F>(&self, f: F) -> GlweCiphertext64where
F: Fn(u64) -> u64,
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));
sourcepub fn keyswitch_bootstrap(&self, ct_in: &Ciphertext) -> Ciphertext
pub fn keyswitch_bootstrap(&self, ct_in: &Ciphertext) -> Ciphertext
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);
pub fn keyswitch_bootstrap_assign(&self, ct_in: &mut Ciphertext)
sourcepub fn keyswitch_programmable_bootstrap(
&self,
ct_in: &Ciphertext,
acc: &GlweCiphertext64
) -> Ciphertext
pub fn keyswitch_programmable_bootstrap(
&self,
ct_in: &Ciphertext,
acc: &GlweCiphertext64
) -> Ciphertext
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);
pub fn keyswitch_programmable_bootstrap_assign(
&self,
ct_in: &mut Ciphertext,
acc: &GlweCiphertext64
)
sourcepub fn unchecked_functional_bivariate_pbs<F>(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext,
f: F
) -> Ciphertextwhere
F: Fn(u64) -> u64,
pub fn unchecked_functional_bivariate_pbs<F>(
&self,
ct_left: &Ciphertext,
ct_right: &Ciphertext,
f: F
) -> Ciphertextwhere
F: Fn(u64) -> u64,
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).
pub fn unchecked_functional_bivariate_pbs_assign<F>(
&self,
ct_left: &mut Ciphertext,
ct_right: &Ciphertext,
f: F
)where
F: Fn(u64) -> u64,
sourcepub fn is_functional_bivariate_pbs_possible(
&self,
ct1: &Ciphertext,
ct2: &Ciphertext
) -> bool
pub fn is_functional_bivariate_pbs_possible(
&self,
ct1: &Ciphertext,
ct2: &Ciphertext
) -> bool
Verifies if a bivariate functional pbs can be applied on ct_left and ct_right.
sourcepub fn carry_extract_assign(&self, ct: &mut Ciphertext)
pub fn carry_extract_assign(&self, ct: &mut Ciphertext)
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);
sourcepub fn carry_extract(&self, ct: &Ciphertext) -> Ciphertext
pub fn carry_extract(&self, ct: &Ciphertext) -> Ciphertext
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);
sourcepub fn message_extract_assign(&self, ct: &mut Ciphertext)
pub fn message_extract_assign(&self, ct: &mut Ciphertext)
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);
sourcepub fn message_extract(&self, ct: &Ciphertext) -> Ciphertext
pub fn message_extract(&self, ct: &Ciphertext) -> Ciphertext
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);
sourcepub fn create_trivial(&self, value: u8) -> Ciphertext
pub fn create_trivial(&self, value: u8) -> Ciphertext
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);