use std::{cell::RefCell, sync::OnceLock}; use crate::{ backend::{ModularOpsU64, ModulusPowerOf2}, ntt::NttBackendU64, random::{DefaultSecureRng, NewWithSeed}, utils::{Global, WithLocal}, }; use super::{evaluator::*, keys::*, parameters::*}; thread_local! { static BOOL_EVALUATOR: RefCell>, NttBackendU64, ModularOpsU64>, ModulusPowerOf2>, ShoupServerKeyEvaluationDomain>>>>> = RefCell::new(None); } static BOOL_SERVER_KEY: OnceLock>>> = OnceLock::new(); static MULTI_PARTY_CRS: OnceLock> = OnceLock::new(); pub type ClientKey = super::keys::ClientKey<[u8; 32], u64>; pub enum ParameterSelector { MultiPartyLessThanOrEqualTo16, } pub fn set_parameter_set(select: ParameterSelector) { match select { ParameterSelector::MultiPartyLessThanOrEqualTo16 => { BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(SMALL_MP_BOOL_PARAMS))); } } } pub fn set_mp_seed(seed: [u8; 32]) { assert!( MULTI_PARTY_CRS.set(MultiPartyCrs { seed: seed }).is_ok(), "Attempted to set MP SEED twice." ) } fn set_server_key(key: ShoupServerKeyEvaluationDomain>>) { assert!( BOOL_SERVER_KEY.set(key).is_ok(), "Attempted to set server key twice." ); } pub(crate) fn gen_keys() -> ( ClientKey, SeededSinglePartyServerKey>, BoolParameters, [u8; 32]>, ) { BoolEvaluator::with_local_mut(|e| { let ck = e.client_key(); let sk = e.single_party_server_key(&ck); (ck, sk) }) } pub fn gen_client_key() -> ClientKey { BoolEvaluator::with_local(|e| e.client_key()) } pub fn gen_mp_keys_phase1( ck: &ClientKey, ) -> CommonReferenceSeededCollectivePublicKeyShare, [u8; 32], BoolParameters> { let seed = MultiPartyCrs::global().public_key_share_seed::(); BoolEvaluator::with_local(|e| { let pk_share = e.multi_party_public_key_share(seed, ck); pk_share }) } pub fn gen_mp_keys_phase2( ck: &ClientKey, pk: &PublicKey>, R, ModOp>, ) -> CommonReferenceSeededMultiPartyServerKeyShare>, BoolParameters, [u8; 32]> { let seed = MultiPartyCrs::global().server_key_share_seed::(); BoolEvaluator::with_local_mut(|e| { let server_key_share = e.multi_party_server_key_share(seed, pk.key(), ck); server_key_share }) } pub fn aggregate_public_key_shares( shares: &[CommonReferenceSeededCollectivePublicKeyShare< Vec, [u8; 32], BoolParameters, >], ) -> PublicKey>, DefaultSecureRng, ModularOpsU64>> { PublicKey::from(shares) } pub fn aggregate_server_key_shares( shares: &[CommonReferenceSeededMultiPartyServerKeyShare< Vec>, BoolParameters, [u8; 32], >], ) -> SeededMultiPartyServerKey>, [u8; 32], BoolParameters> { BoolEvaluator::with_local(|e| e.aggregate_multi_party_server_key_shares(shares)) } // SERVER KEY EVAL (/SHOUP) DOMAIN // impl SeededSinglePartyServerKey>, BoolParameters, [u8; 32]> { pub fn set_server_key(&self) { let eval = ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(self); set_server_key(ShoupServerKeyEvaluationDomain::from(eval)); } } impl SeededMultiPartyServerKey< Vec>, ::Seed, BoolParameters, > { pub fn set_server_key(&self) { set_server_key(ShoupServerKeyEvaluationDomain::from( ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(self), )) } } // MULTIPARTY CRS // impl Global for MultiPartyCrs<[u8; 32]> { fn global() -> &'static Self { MULTI_PARTY_CRS .get() .expect("Multi Party Common Reference String not set") } } // BOOL EVALUATOR // impl WithLocal for BoolEvaluator< Vec>, NttBackendU64, ModularOpsU64>, ModulusPowerOf2>, ShoupServerKeyEvaluationDomain>>, > { fn with_local(func: F) -> R where F: Fn(&Self) -> R, { BOOL_EVALUATOR.with_borrow(|s| func(s.as_ref().expect("Parameters not set"))) } fn with_local_mut(func: F) -> R where F: Fn(&mut Self) -> R, { BOOL_EVALUATOR.with_borrow_mut(|s| func(s.as_mut().expect("Parameters not set"))) } fn with_local_mut_mut(func: &mut F) -> R where F: FnMut(&mut Self) -> R, { BOOL_EVALUATOR.with_borrow_mut(|s| func(s.as_mut().expect("Parameters not set"))) } } pub(crate) type RuntimeServerKey = ShoupServerKeyEvaluationDomain>>; impl Global for RuntimeServerKey { fn global() -> &'static Self { BOOL_SERVER_KEY.get().expect("Server key not set!") } } mod impl_enc_dec { use crate::{ pbs::{sample_extract, PbsInfo}, rgsw::public_key_encrypt_rlwe, Decryptor, Encryptor, Matrix, MatrixEntity, MultiPartyDecryptor, RowEntity, }; use num_traits::Zero; use super::*; type Mat = Vec>; impl Encryptor> for super::super::keys::ClientKey<[u8; 32], E> { fn encrypt(&self, m: &bool) -> Vec { BoolEvaluator::with_local(|e| e.sk_encrypt(*m, self)) } } impl Decryptor> for super::super::keys::ClientKey<[u8; 32], E> { fn decrypt(&self, c: &Vec) -> bool { BoolEvaluator::with_local(|e| e.sk_decrypt(c, self)) } } impl MultiPartyDecryptor::R> for super::super::keys::ClientKey<[u8; 32], E> { type DecryptionShare = ::MatElement; fn gen_decryption_share(&self, c: &::R) -> Self::DecryptionShare { BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, self)) } fn aggregate_decryption_shares( &self, c: &::R, shares: &[Self::DecryptionShare], ) -> bool { BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c)) } } impl Encryptor<[bool], Mat> for PublicKey { fn encrypt(&self, m: &[bool]) -> Mat { BoolEvaluator::with_local(|e| { DefaultSecureRng::with_local_mut(|rng| { let parameters = e.parameters(); let mut rlwe_out = ::zeros(2, parameters.rlwe_n().0); assert!(m.len() <= parameters.rlwe_n().0); let mut message = vec![::MatElement::zero(); parameters.rlwe_n().0]; m.iter().enumerate().for_each(|(i, v)| { if *v { message[i] = parameters.rlwe_q().true_el() } else { message[i] = parameters.rlwe_q().false_el() } }); // e.pk_encrypt_batched(self.key(), m) public_key_encrypt_rlwe::<_, _, _, _, i32, _>( &mut rlwe_out, self.key(), &message, e.pbs_info().modop_rlweq(), e.pbs_info().nttop_rlweq(), rng, ); rlwe_out }) }) } } impl Encryptor::R> for PublicKey { fn encrypt(&self, m: &bool) -> ::R { let m = vec![*m]; let rlwe = self.encrypt(m.as_slice()); BoolEvaluator::with_local(|e| { let mut lwe = ::R::zeros(e.parameters().rlwe_n().0 + 1); sample_extract(&mut lwe, &rlwe, e.pbs_info().modop_rlweq(), 0); lwe }) } } }