arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe/public_key.rs
core/src/glwe/public_key.rsRaw
  1use backend::hal::{
  2    api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftFromVecZnx},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, ReaderFrom, Scratch, ScratchOwned, VecZnx, VecZnxDft, WriterTo},
  4    oep::{ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxDftImpl, TakeVecZnxImpl},
  5};
  6use sampling::source::Source;
  7
  8use crate::{GLWECiphertext, GLWEEncryptSkFamily, GLWESecretExec, Infos, dist::Distribution};
  9
 10pub trait GLWEPublicKeyFamily<B: Backend> = GLWEEncryptSkFamily<B>;
 11
 12#[derive(PartialEq, Eq)]
 13pub struct GLWEPublicKey<D: Data> {
 14    pub(crate) data: VecZnx<D>,
 15    pub(crate) basek: usize,
 16    pub(crate) k: usize,
 17    pub(crate) dist: Distribution,
 18}
 19
 20impl GLWEPublicKey<Vec<u8>> {
 21    pub fn alloc(n: usize, basek: usize, k: usize, rank: usize) -> Self {
 22        Self {
 23            data: VecZnx::alloc(n, rank + 1, k.div_ceil(basek)),
 24            basek: basek,
 25            k: k,
 26            dist: Distribution::NONE,
 27        }
 28    }
 29
 30    pub fn bytes_of(n: usize, basek: usize, k: usize, rank: usize) -> usize {
 31        VecZnx::alloc_bytes(n, rank + 1, k.div_ceil(basek))
 32    }
 33}
 34
 35impl<D: Data> Infos for GLWEPublicKey<D> {
 36    type Inner = VecZnx<D>;
 37
 38    fn inner(&self) -> &Self::Inner {
 39        &self.data
 40    }
 41
 42    fn basek(&self) -> usize {
 43        self.basek
 44    }
 45
 46    fn k(&self) -> usize {
 47        self.k
 48    }
 49}
 50
 51impl<D: Data> GLWEPublicKey<D> {
 52    pub fn rank(&self) -> usize {
 53        self.cols() - 1
 54    }
 55}
 56
 57impl<D: DataMut> GLWEPublicKey<D> {
 58    pub fn generate_from_sk<S: DataRef, B: Backend>(
 59        &mut self,
 60        module: &Module<B>,
 61        sk: &GLWESecretExec<S, B>,
 62        source_xa: &mut Source,
 63        source_xe: &mut Source,
 64        sigma: f64,
 65    ) where
 66        Module<B>: GLWEPublicKeyFamily<B>,
 67        B: ScratchOwnedAllocImpl<B>
 68            + ScratchOwnedBorrowImpl<B>
 69            + TakeVecZnxDftImpl<B>
 70            + ScratchAvailableImpl<B>
 71            + TakeVecZnxImpl<B>,
 72    {
 73        #[cfg(debug_assertions)]
 74        {
 75            assert_eq!(self.n(), sk.n());
 76
 77            match sk.dist {
 78                Distribution::NONE => panic!("invalid sk: SecretDistribution::NONE"),
 79                _ => {}
 80            }
 81        }
 82
 83        // Its ok to allocate scratch space here since pk is usually generated only once.
 84        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::encrypt_sk_scratch_space(
 85            module,
 86            self.n(),
 87            self.basek(),
 88            self.k(),
 89        ));
 90
 91        let mut tmp: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(self.n(), self.basek(), self.k(), self.rank());
 92        tmp.encrypt_zero_sk(module, sk, source_xa, source_xe, sigma, scratch.borrow());
 93        self.dist = sk.dist;
 94    }
 95}
 96
 97use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 98
 99impl<D: DataMut> ReaderFrom for GLWEPublicKey<D> {
100    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
101        self.k = reader.read_u64::<LittleEndian>()? as usize;
102        self.basek = reader.read_u64::<LittleEndian>()? as usize;
103        match Distribution::read_from(reader) {
104            Ok(dist) => self.dist = dist,
105            Err(e) => return Err(e),
106        }
107        self.data.read_from(reader)
108    }
109}
110
111impl<D: DataRef> WriterTo for GLWEPublicKey<D> {
112    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
113        writer.write_u64::<LittleEndian>(self.k as u64)?;
114        writer.write_u64::<LittleEndian>(self.basek as u64)?;
115        match self.dist.write_to(writer) {
116            Ok(()) => {}
117            Err(e) => return Err(e),
118        }
119        self.data.write_to(writer)
120    }
121}
122
123#[derive(PartialEq, Eq)]
124pub struct GLWEPublicKeyExec<D: Data, B: Backend> {
125    pub(crate) data: VecZnxDft<D, B>,
126    pub(crate) basek: usize,
127    pub(crate) k: usize,
128    pub(crate) dist: Distribution,
129}
130
131impl<D: Data, B: Backend> Infos for GLWEPublicKeyExec<D, B> {
132    type Inner = VecZnxDft<D, B>;
133
134    fn inner(&self) -> &Self::Inner {
135        &self.data
136    }
137
138    fn basek(&self) -> usize {
139        self.basek
140    }
141
142    fn k(&self) -> usize {
143        self.k
144    }
145}
146
147impl<D: Data, B: Backend> GLWEPublicKeyExec<D, B> {
148    pub fn rank(&self) -> usize {
149        self.cols() - 1
150    }
151}
152
153impl<B: Backend> GLWEPublicKeyExec<Vec<u8>, B> {
154    pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> Self
155    where
156        Module<B>: VecZnxDftAlloc<B>,
157    {
158        Self {
159            data: module.vec_znx_dft_alloc(n, rank + 1, k.div_ceil(basek)),
160            basek: basek,
161            k: k,
162            dist: Distribution::NONE,
163        }
164    }
165
166    pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
167    where
168        Module<B>: VecZnxDftAllocBytes,
169    {
170        module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek))
171    }
172
173    pub fn from<DataOther>(module: &Module<B>, other: &GLWEPublicKey<DataOther>, scratch: &mut Scratch<B>) -> Self
174    where
175        DataOther: DataRef,
176        Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>,
177    {
178        let mut pk_exec: GLWEPublicKeyExec<Vec<u8>, B> =
179            GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank());
180        pk_exec.prepare(module, other, scratch);
181        pk_exec
182    }
183}
184
185impl<D: DataMut, B: Backend> GLWEPublicKeyExec<D, B> {
186    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEPublicKey<DataOther>, _scratch: &mut Scratch<B>)
187    where
188        DataOther: DataRef,
189        Module<B>: VecZnxDftFromVecZnx<B>,
190    {
191        #[cfg(debug_assertions)]
192        {
193            assert_eq!(self.n(), other.n());
194            assert_eq!(self.size(), other.size());
195        }
196
197        (0..self.cols()).for_each(|i| {
198            module.vec_znx_dft_from_vec_znx(1, 0, &mut self.data, i, &other.data, i);
199        });
200        self.k = other.k;
201        self.basek = other.basek;
202        self.dist = other.dist;
203    }
204}