arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/schemes/src/tfhe/blind_rotation/cggi_key.rs
schemes/src/tfhe/blind_rotation/cggi_key.rsRaw
  1use backend::hal::{
  2    api::{
  3        ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VmpPMatAlloc, VmpPMatPrepare, ZnxView, ZnxViewMut,
  4    },
  5    layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch},
  6};
  7use sampling::source::Source;
  8
  9use std::marker::PhantomData;
 10
 11use core::{
 12    Distribution,
 13    layouts::{
 14        GGSWCiphertext, LWESecret,
 15        compressed::GGSWCiphertextCompressed,
 16        prepared::{GGSWCiphertextPrepared, GLWESecretPrepared},
 17    },
 18    trait_families::GGSWEncryptSkFamily,
 19};
 20
 21use crate::tfhe::blind_rotation::{
 22    BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared,
 23    BlindRotationKeyPreparedAlloc, CGGI,
 24};
 25
 26impl BlindRotationKeyAlloc for BlindRotationKey<Vec<u8>, CGGI> {
 27    fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
 28        let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(n_lwe);
 29        (0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(n_gglwe, basek, k, rows, 1, rank)));
 30        Self {
 31            keys: data,
 32            dist: Distribution::NONE,
 33            _phantom: PhantomData,
 34        }
 35    }
 36}
 37
 38impl BlindRotationKey<Vec<u8>, CGGI> {
 39    pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
 40    where
 41        Module<B>: GGSWEncryptSkFamily<B>,
 42    {
 43        GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k, rank)
 44    }
 45}
 46
 47impl<D: DataMut, B: Backend> BlindRotationKeyEncryptSk<B> for BlindRotationKey<D, CGGI>
 48where
 49    Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace,
 50    Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
 51{
 52    fn encrypt_sk<DataSkGLWE, DataSkLWE>(
 53        &mut self,
 54        module: &Module<B>,
 55        sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
 56        sk_lwe: &LWESecret<DataSkLWE>,
 57        source_xa: &mut Source,
 58        source_xe: &mut Source,
 59        sigma: f64,
 60        scratch: &mut Scratch<B>,
 61    ) where
 62        DataSkGLWE: DataRef,
 63        DataSkLWE: DataRef,
 64    {
 65        #[cfg(debug_assertions)]
 66        {
 67            assert_eq!(self.keys.len(), sk_lwe.n());
 68            assert!(sk_glwe.n() <= module.n());
 69            assert_eq!(sk_glwe.rank(), self.keys[0].rank());
 70            match sk_lwe.dist() {
 71                Distribution::BinaryBlock(_)
 72                | Distribution::BinaryFixed(_)
 73                | Distribution::BinaryProb(_)
 74                | Distribution::ZERO => {}
 75                _ => panic!(
 76                    "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
 77                ),
 78            }
 79        }
 80
 81        self.dist = sk_lwe.dist();
 82
 83        let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1);
 84        let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
 85
 86        self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| {
 87            pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
 88            ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, sigma, scratch);
 89        });
 90    }
 91}
 92
 93impl<B: Backend> BlindRotationKeyPreparedAlloc<B> for BlindRotationKeyPrepared<Vec<u8>, CGGI, B>
 94where
 95    Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
 96{
 97    fn alloc(module: &Module<B>, n_glwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
 98        let mut data: Vec<GGSWCiphertextPrepared<Vec<u8>, B>> = Vec::with_capacity(n_lwe);
 99        (0..n_lwe).for_each(|_| {
100            data.push(GGSWCiphertextPrepared::alloc(
101                module, n_glwe, basek, k, rows, 1, rank,
102            ))
103        });
104        Self {
105            data,
106            dist: Distribution::NONE,
107            x_pow_a: None,
108            _phantom: PhantomData,
109        }
110    }
111}
112
113impl BlindRotationKeyCompressed<Vec<u8>, CGGI> {
114    pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
115        let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(n_lwe);
116        (0..n_lwe).for_each(|_| {
117            data.push(GGSWCiphertextCompressed::alloc(
118                n_gglwe, basek, k, rows, 1, rank,
119            ))
120        });
121        Self {
122            keys: data,
123            dist: Distribution::NONE,
124            _phantom: PhantomData,
125        }
126    }
127
128    pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
129    where
130        Module<B>: GGSWEncryptSkFamily<B>,
131    {
132        GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank)
133    }
134}
135
136impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> {
137    pub fn encrypt_sk<DataSkGLWE, DataSkLWE, B: Backend>(
138        &mut self,
139        module: &Module<B>,
140        sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
141        sk_lwe: &LWESecret<DataSkLWE>,
142        seed_xa: [u8; 32],
143        source_xe: &mut Source,
144        sigma: f64,
145        scratch: &mut Scratch<B>,
146    ) where
147        DataSkGLWE: DataRef,
148        DataSkLWE: DataRef,
149        Module<B>: GGSWEncryptSkFamily<B> + VecZnxAddScalarInplace,
150        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
151    {
152        #[cfg(debug_assertions)]
153        {
154            assert_eq!(self.keys.len(), sk_lwe.n());
155            assert!(sk_glwe.n() <= module.n());
156            assert_eq!(sk_glwe.rank(), self.keys[0].rank());
157            match sk_lwe.dist() {
158                Distribution::BinaryBlock(_)
159                | Distribution::BinaryFixed(_)
160                | Distribution::BinaryProb(_)
161                | Distribution::ZERO => {}
162                _ => panic!(
163                    "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
164                ),
165            }
166        }
167
168        self.dist = sk_lwe.dist();
169
170        let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1);
171        let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
172
173        let mut source_xa: Source = Source::new(seed_xa);
174
175        self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| {
176            pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
177            ggsw.encrypt_sk(
178                module,
179                &pt,
180                sk_glwe,
181                source_xa.new_seed(),
182                source_xe,
183                sigma,
184                scratch,
185            );
186        });
187    }
188}