arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/encryption/gglwe_ksk.rs
poulpy-core/src/encryption/gglwe_ksk.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft,
  4        VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply,
  5        VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub,
  6        VecZnxSubInplace, VecZnxSwitchRing,
  7    },
  8    layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
  9    source::Source,
 10};
 11
 12use crate::{
 13    TakeGLWESecretPrepared,
 14    layouts::{Degree, GGLWE, GGLWEInfos, GLWEInfos, GLWESecret, GLWESwitchingKey, LWEInfos, prepared::GLWESecretPrepared},
 15};
 16
 17impl GLWESwitchingKey<Vec<u8>> {
 18    pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
 19    where
 20        A: GGLWEInfos,
 21        Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
 22    {
 23        (GGLWE::encrypt_sk_scratch_space(module, infos) | ScalarZnx::bytes_of(module.n(), 1))
 24            + ScalarZnx::bytes_of(module.n(), infos.rank_in().into())
 25            + GLWESecretPrepared::bytes_of_from_infos(module, &infos.glwe_layout())
 26    }
 27
 28    pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize
 29    where
 30        A: GGLWEInfos,
 31    {
 32        GGLWE::encrypt_pk_scratch_space(module, _infos)
 33    }
 34}
 35
 36impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
 37    #[allow(clippy::too_many_arguments)]
 38    pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>(
 39        &mut self,
 40        module: &Module<B>,
 41        sk_in: &GLWESecret<DataSkIn>,
 42        sk_out: &GLWESecret<DataSkOut>,
 43        source_xa: &mut Source,
 44        source_xe: &mut Source,
 45        scratch: &mut Scratch<B>,
 46    ) where
 47        Module<B>: VecZnxAddScalarInplace
 48            + VecZnxDftAllocBytes
 49            + VecZnxBigNormalize<B>
 50            + VecZnxDftApply<B>
 51            + SvpApplyDftToDftInplace<B>
 52            + VecZnxIdftApplyConsume<B>
 53            + VecZnxNormalizeTmpBytes
 54            + VecZnxFillUniform
 55            + VecZnxSubInplace
 56            + VecZnxAddInplace
 57            + VecZnxNormalizeInplace<B>
 58            + VecZnxAddNormal
 59            + VecZnxNormalize<B>
 60            + VecZnxSub
 61            + SvpPrepare<B>
 62            + VecZnxSwitchRing
 63            + SvpPPolAllocBytes,
 64        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>,
 65    {
 66        #[cfg(debug_assertions)]
 67        {
 68            assert!(sk_in.n().0 <= module.n() as u32);
 69            assert!(sk_out.n().0 <= module.n() as u32);
 70            assert!(
 71                scratch.available() >= GLWESwitchingKey::encrypt_sk_scratch_space(module, self),
 72                "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}",
 73                scratch.available(),
 74                GLWESwitchingKey::encrypt_sk_scratch_space(module, self)
 75            )
 76        }
 77
 78        let n: usize = sk_in.n().max(sk_out.n()).into();
 79
 80        let (mut sk_in_tmp, scratch_1) = scratch.take_scalar_znx(n, sk_in.rank().into());
 81        (0..sk_in.rank().into()).for_each(|i| {
 82            module.vec_znx_switch_ring(
 83                &mut sk_in_tmp.as_vec_znx_mut(),
 84                i,
 85                &sk_in.data.as_vec_znx(),
 86                i,
 87            );
 88        });
 89
 90        let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(Degree(n as u32), sk_out.rank());
 91        {
 92            let (mut tmp, _) = scratch_2.take_scalar_znx(n, 1);
 93            (0..sk_out.rank().into()).for_each(|i| {
 94                module.vec_znx_switch_ring(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
 95                module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
 96            });
 97        }
 98
 99        self.key.encrypt_sk(
100            module,
101            &sk_in_tmp,
102            &sk_out_tmp,
103            source_xa,
104            source_xe,
105            scratch_2,
106        );
107        self.sk_in_n = sk_in.n().into();
108        self.sk_out_n = sk_out.n().into();
109    }
110}