arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/encryption/compressed/gglwe_ksk.rs
poulpy-core/src/encryption/compressed/gglwe_ksk.rsRaw
  1use poulpy_hal::{
  2    api::{ScratchAvailable, SvpPPolBytesOf, SvpPrepare, VecZnxDftBytesOf, VecZnxNormalizeTmpBytes, VecZnxSwitchRing},
  3    layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
  4    source::Source,
  5};
  6
  7use crate::{
  8    encryption::compressed::gglwe_ct::GGLWECompressedEncryptSk,
  9    layouts::{
 10        GGLWE, GGLWEInfos, GLWEInfos, GLWESecret, GLWESecretToRef, LWEInfos, RingDegree,
 11        compressed::{GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedToMut},
 12        prepared::GLWESecretPrepared,
 13    },
 14};
 15
 16impl GLWESwitchingKeyCompressed<Vec<u8>> {
 17    pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
 18    where
 19        A: GGLWEInfos,
 20        Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + SvpPPolBytesOf,
 21    {
 22        (GGLWE::encrypt_sk_tmp_bytes(module, infos) | ScalarZnx::bytes_of(module.n(), 1))
 23            + ScalarZnx::bytes_of(module.n(), infos.rank_in().into())
 24            + GLWESecretPrepared::bytes_of(module, infos.rank_out())
 25    }
 26}
 27
 28impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
 29    #[allow(clippy::too_many_arguments)]
 30    pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>(
 31        &mut self,
 32        module: &Module<B>,
 33        sk_in: &GLWESecret<DataSkIn>,
 34        sk_out: &GLWESecret<DataSkOut>,
 35        seed_xa: [u8; 32],
 36        source_xe: &mut Source,
 37        scratch: &mut Scratch<B>,
 38    ) where
 39        Module<B>: GGLWEKeyCompressedEncryptSk<B>,
 40    {
 41        module.gglwe_key_compressed_encrypt_sk(self, sk_in, sk_out, seed_xa, source_xe, scratch);
 42    }
 43}
 44
 45pub trait GGLWEKeyCompressedEncryptSk<B: Backend> {
 46    fn gglwe_key_compressed_encrypt_sk<R, SI, SO>(
 47        &self,
 48        res: &mut R,
 49        sk_in: &SI,
 50        sk_out: &SO,
 51        seed_xa: [u8; 32],
 52        source_xe: &mut Source,
 53        scratch: &mut Scratch<B>,
 54    ) where
 55        R: GLWESwitchingKeyCompressedToMut,
 56        SI: GLWESecretToRef,
 57        SO: GLWESecretToRef;
 58}
 59
 60impl<B: Backend> GGLWEKeyCompressedEncryptSk<B> for Module<B>
 61where
 62    Module<B>: GGLWECompressedEncryptSk<B>
 63        + SvpPPolBytesOf
 64        + VecZnxNormalizeTmpBytes
 65        + VecZnxDftBytesOf
 66        + VecZnxSwitchRing
 67        + SvpPrepare<B>,
 68    Scratch<B>: ScratchAvailable,
 69{
 70    fn gglwe_key_compressed_encrypt_sk<R, SI, SO>(
 71        &self,
 72        res: &mut R,
 73        sk_in: &SI,
 74        sk_out: &SO,
 75        seed_xa: [u8; 32],
 76        source_xe: &mut Source,
 77        scratch: &mut Scratch<B>,
 78    ) where
 79        R: GLWESwitchingKeyCompressedToMut,
 80        SI: GLWESecretToRef,
 81        SO: GLWESecretToRef,
 82    {
 83        let res: &mut GLWESwitchingKeyCompressed<&mut [u8]> = &mut res.to_mut();
 84        let sk_in: &GLWESecret<&[u8]> = &sk_in.to_ref();
 85        let sk_out: &GLWESecret<&[u8]> = &sk_out.to_ref();
 86
 87        #[cfg(debug_assertions)]
 88        {
 89            use crate::layouts::GLWESwitchingKey;
 90
 91            assert!(sk_in.n().0 <= self.n() as u32);
 92            assert!(sk_out.n().0 <= self.n() as u32);
 93            assert!(
 94                scratch.available() >= GLWESwitchingKey::encrypt_sk_tmp_bytes(self, res),
 95                "scratch.available()={} < GLWESwitchingKey::encrypt_sk_tmp_bytes={}",
 96                scratch.available(),
 97                GLWESwitchingKey::encrypt_sk_tmp_bytes(self, res)
 98            )
 99        }
100
101        let n: usize = sk_in.n().max(sk_out.n()).into();
102
103        let (mut sk_in_tmp, scratch_1) = scratch.take_scalar_znx(n, sk_in.rank().into());
104        (0..sk_in.rank().into()).for_each(|i| {
105            self.vec_znx_switch_ring(
106                &mut sk_in_tmp.as_vec_znx_mut(),
107                i,
108                &sk_in.data.as_vec_znx(),
109                i,
110            );
111        });
112
113        let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(RingDegree(n as u32), sk_out.rank());
114        {
115            let (mut tmp, _) = scratch_2.take_scalar_znx(n, 1);
116            (0..sk_out.rank().into()).for_each(|i| {
117                self.vec_znx_switch_ring(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
118                self.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
119            });
120        }
121
122        self.gglwe_compressed_encrypt_sk(
123            &mut res.key,
124            &sk_in_tmp,
125            &sk_out_tmp,
126            seed_xa,
127            source_xe,
128            scratch_2,
129        );
130        res.sk_in_n = sk_in.n().into();
131        res.sk_out_n = sk_out.n().into();
132    }
133}