use crate::ciphertext::KeyId;
use crate::client_key::utils::i_crt;
use crate::CrtMultiCiphertext;
use concrete_shortint::parameters::MessageModulus;
use serde::{Deserialize, Serialize};
pub fn gen_key_id(id: &[usize]) -> Vec<KeyId> {
id.iter().copied().map(KeyId).collect()
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct CrtMultiClientKey {
pub(crate) keys: Vec<concrete_shortint::ClientKey>,
pub(crate) key_ids: Vec<KeyId>,
}
impl From<Vec<concrete_shortint::ClientKey>> for CrtMultiClientKey {
fn from(keys: Vec<concrete_shortint::ClientKey>) -> Self {
let key_ids = (0..keys.len()).map(KeyId).collect();
Self { keys, key_ids }
}
}
impl CrtMultiClientKey {
pub fn new_many_keys(
parameter_set: &[concrete_shortint::parameters::Parameters],
) -> CrtMultiClientKey {
let mut key = Vec::with_capacity(parameter_set.len());
let mut id = Vec::with_capacity(parameter_set.len());
for (i, param) in parameter_set.iter().enumerate() {
key.push(concrete_shortint::ClientKey::new(*param));
id.push(KeyId(i));
}
CrtMultiClientKey {
keys: key,
key_ids: id,
}
}
pub fn encrypt(
&self,
message: &u64,
base_vec: &[u64],
keys_id: &[KeyId],
) -> CrtMultiCiphertext {
let mut ctxt_vect: Vec<concrete_shortint::Ciphertext> = Vec::new();
let bv = base_vec.to_vec();
let keys = keys_id.to_vec();
for (modulus, id) in base_vec.iter().zip(keys_id.iter()) {
let ct = self.keys[id.0]
.encrypt_with_message_modulus(*message, MessageModulus(*modulus as usize));
ctxt_vect.push(ct);
}
CrtMultiCiphertext {
blocks: ctxt_vect,
moduli: bv,
key_ids: keys,
}
}
pub fn decrypt(&self, ctxt: &CrtMultiCiphertext) -> u64 {
let mut val: Vec<u64> = vec![];
for ((c_i, b_i), k_i) in ctxt
.blocks
.iter()
.zip(ctxt.moduli.iter())
.zip(ctxt.key_ids.iter())
{
val.push(self.keys[k_i.0].decrypt_message_and_carry(c_i) % b_i);
}
let result = i_crt(&ctxt.moduli, &val);
let whole_modulus: u64 = ctxt.moduli.iter().copied().product();
result % whole_modulus
}
}