concrete_core/backends/fft/implementation/engines/fft_serialization_engine/
deserialization.rs

1#![allow(clippy::missing_safety_doc)]
2
3use super::{FftSerializationEngine, FftSerializationError};
4use crate::backends::fft::private::crypto::bootstrap::FourierLweBootstrapKey;
5use crate::backends::fft::private::crypto::ggsw::FourierGgswCiphertext;
6use crate::prelude::{
7    EntityDeserializationEngine, EntityDeserializationError, FftFourierGgswCiphertext32,
8    FftFourierGgswCiphertext32Version, FftFourierGgswCiphertext64,
9    FftFourierGgswCiphertext64Version, FftFourierLweBootstrapKey32,
10    FftFourierLweBootstrapKey32Version, FftFourierLweBootstrapKey64,
11    FftFourierLweBootstrapKey64Version,
12};
13use aligned_vec::ABox;
14use concrete_fft::c64;
15use serde::Deserialize;
16
17/// # Description:
18/// Implementation of [`EntityDeserializationEngine`] for [`FftSerializationEngine`] that operates
19/// on 32 bits integers. It deserializes a GGSW ciphertext in the Fourier domain.
20impl EntityDeserializationEngine<&[u8], FftFourierGgswCiphertext32> for FftSerializationEngine {
21    /// # Example
22    /// ```
23    /// use concrete_core::prelude::{
24    ///     DecompositionBaseLog, DecompositionLevelCount, GlweDimension, LweDimension, PolynomialSize,
25    ///     Variance, *,
26    /// };
27    /// # use std::error::Error;
28    ///
29    /// # fn main() -> Result<(), Box<dyn Error>> {
30    /// // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
31    /// let glwe_dimension = GlweDimension(2);
32    /// let polynomial_size = PolynomialSize(256);
33    /// let level = DecompositionLevelCount(1);
34    /// let base_log = DecompositionBaseLog(4);
35    /// // Here a hard-set encoding is applied (shift by 20 bits)
36    /// let input = 3_u32 << 20;
37    /// let noise = Variance(2_f64.powf(-25.));
38    ///
39    /// // Unix seeder must be given a secret input.
40    /// // Here we just give it 0, which is totally unsafe.
41    /// const UNSAFE_SECRET: u128 = 0;
42    /// let mut default_engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
43    /// let mut fft_engine = FftEngine::new(())?;
44    /// let key: GlweSecretKey32 =
45    ///     default_engine.generate_new_glwe_secret_key(glwe_dimension, polynomial_size)?;
46    /// let plaintext = default_engine.create_plaintext_from(&input)?;
47    ///
48    /// // We encrypt a GGSW ciphertext in the standard domain
49    /// let ciphertext =
50    ///     default_engine.encrypt_scalar_ggsw_ciphertext(&key, &plaintext, noise, level, base_log)?;
51    ///
52    /// // Then we convert it to the Fourier domain.
53    /// let fourier_ciphertext: FftFourierGgswCiphertext32 =
54    ///     fft_engine.convert_ggsw_ciphertext(&ciphertext)?;
55    ///
56    /// let mut serialization_engine = FftSerializationEngine::new(())?;
57    /// let serialized = serialization_engine.serialize(&fourier_ciphertext)?;
58    /// let recovered = serialization_engine.deserialize(serialized.as_slice())?;
59    /// assert_eq!(fourier_ciphertext, recovered);
60    /// #
61    /// # Ok(())
62    /// # }
63    /// ```
64    fn deserialize(
65        &mut self,
66        serialized: &[u8],
67    ) -> Result<FftFourierGgswCiphertext32, EntityDeserializationError<Self::EngineError>> {
68        #[derive(Deserialize)]
69        struct SerializableFftFourierGgswCiphertext32 {
70            version: FftFourierGgswCiphertext32Version,
71            inner: FourierGgswCiphertext<ABox<[c64]>>,
72        }
73        let deserialized: SerializableFftFourierGgswCiphertext32 = bincode::deserialize(serialized)
74            .map_err(FftSerializationError::Deserialization)
75            .map_err(EntityDeserializationError::Engine)?;
76        match deserialized {
77            SerializableFftFourierGgswCiphertext32 {
78                version: FftFourierGgswCiphertext32Version::Unsupported,
79                ..
80            } => Err(EntityDeserializationError::Engine(
81                FftSerializationError::UnsupportedVersion,
82            )),
83            SerializableFftFourierGgswCiphertext32 {
84                version: FftFourierGgswCiphertext32Version::V0,
85                inner,
86            } => Ok(FftFourierGgswCiphertext32(inner)),
87        }
88    }
89
90    unsafe fn deserialize_unchecked(&mut self, serialized: &[u8]) -> FftFourierGgswCiphertext32 {
91        self.deserialize(serialized).unwrap()
92    }
93}
94
95/// # Description:
96/// Implementation of [`EntityDeserializationEngine`] for [`FftSerializationEngine`] that operates
97/// on 64 bits integers. It deserializes a GGSW ciphertext in the Fourier domain.
98impl EntityDeserializationEngine<&[u8], FftFourierGgswCiphertext64> for FftSerializationEngine {
99    /// # Example
100    /// ```
101    /// use concrete_core::prelude::{
102    ///     DecompositionBaseLog, DecompositionLevelCount, GlweDimension, LweDimension, PolynomialSize,
103    ///     Variance, *,
104    /// };
105    /// # use std::error::Error;
106    ///
107    /// # fn main() -> Result<(), Box<dyn Error>> {
108    /// // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
109    /// let glwe_dimension = GlweDimension(2);
110    /// let polynomial_size = PolynomialSize(256);
111    /// let level = DecompositionLevelCount(1);
112    /// let base_log = DecompositionBaseLog(4);
113    /// // Here a hard-set encoding is applied (shift by 50 bits)
114    /// let input = 3_u64 << 50;
115    /// let noise = Variance(2_f64.powf(-25.));
116    ///
117    /// // Unix seeder must be given a secret input.
118    /// // Here we just give it 0, which is totally unsafe.
119    /// const UNSAFE_SECRET: u128 = 0;
120    /// let mut default_engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
121    /// let mut fft_engine = FftEngine::new(())?;
122    /// let key: GlweSecretKey64 =
123    ///     default_engine.generate_new_glwe_secret_key(glwe_dimension, polynomial_size)?;
124    /// let plaintext = default_engine.create_plaintext_from(&input)?;
125    ///
126    /// // We encrypt a GGSW ciphertext in the standard domain
127    /// let ciphertext =
128    ///     default_engine.encrypt_scalar_ggsw_ciphertext(&key, &plaintext, noise, level, base_log)?;
129    ///
130    /// // Then we convert it to the Fourier domain.
131    /// let fourier_ciphertext: FftFourierGgswCiphertext64 =
132    ///     fft_engine.convert_ggsw_ciphertext(&ciphertext)?;
133    ///
134    /// let mut serialization_engine = FftSerializationEngine::new(())?;
135    /// let serialized = serialization_engine.serialize(&fourier_ciphertext)?;
136    /// let recovered = serialization_engine.deserialize(serialized.as_slice())?;
137    /// assert_eq!(fourier_ciphertext, recovered);
138    ///
139    /// #
140    /// # Ok(())
141    /// # }
142    /// ```
143    fn deserialize(
144        &mut self,
145        serialized: &[u8],
146    ) -> Result<FftFourierGgswCiphertext64, EntityDeserializationError<Self::EngineError>> {
147        #[derive(Deserialize)]
148        struct SerializableFftFourierGgswCiphertext64 {
149            version: FftFourierGgswCiphertext64Version,
150            inner: FourierGgswCiphertext<ABox<[c64]>>,
151        }
152        let deserialized: SerializableFftFourierGgswCiphertext64 = bincode::deserialize(serialized)
153            .map_err(FftSerializationError::Deserialization)
154            .map_err(EntityDeserializationError::Engine)?;
155        match deserialized {
156            SerializableFftFourierGgswCiphertext64 {
157                version: FftFourierGgswCiphertext64Version::Unsupported,
158                ..
159            } => Err(EntityDeserializationError::Engine(
160                FftSerializationError::UnsupportedVersion,
161            )),
162            SerializableFftFourierGgswCiphertext64 {
163                version: FftFourierGgswCiphertext64Version::V0,
164                inner,
165            } => Ok(FftFourierGgswCiphertext64(inner)),
166        }
167    }
168
169    unsafe fn deserialize_unchecked(&mut self, serialized: &[u8]) -> FftFourierGgswCiphertext64 {
170        self.deserialize(serialized).unwrap()
171    }
172}
173
174/// # Description:
175/// Implementation of [`EntityDeserializationEngine`] for [`FftSerializationEngine`] that operates
176/// on 32 bits integers. It deserializes an LWE bootstrap key in the Fourier domain.
177impl EntityDeserializationEngine<&[u8], FftFourierLweBootstrapKey32> for FftSerializationEngine {
178    /// # Example
179    /// ```
180    /// use concrete_core::prelude::{
181    ///     DecompositionBaseLog, DecompositionLevelCount, GlweDimension, LweDimension, PolynomialSize,
182    ///     Variance, *,
183    /// };
184    /// # use std::error::Error;
185    ///
186    /// # fn main() -> Result<(), Box<dyn Error>> {
187    /// // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
188    /// let (lwe_dim, glwe_dim, poly_size) = (LweDimension(4), GlweDimension(6), PolynomialSize(256));
189    /// let (dec_lc, dec_bl) = (DecompositionLevelCount(3), DecompositionBaseLog(5));
190    /// let noise = Variance(2_f64.powf(-25.));
191    ///
192    /// // Unix seeder must be given a secret input.
193    /// // Here we just give it 0, which is totally unsafe.
194    /// const UNSAFE_SECRET: u128 = 0;
195    /// let mut default_engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
196    /// let mut fft_engine = FftEngine::new(())?;
197    /// let lwe_sk: LweSecretKey32 = default_engine.generate_new_lwe_secret_key(lwe_dim)?;
198    /// let glwe_sk: GlweSecretKey32 =
199    ///     default_engine.generate_new_glwe_secret_key(glwe_dim, poly_size)?;
200    /// let bsk: LweBootstrapKey32 =
201    ///     default_engine.generate_new_lwe_bootstrap_key(&lwe_sk, &glwe_sk, dec_bl, dec_lc, noise)?;
202    ///
203    /// let fourier_bsk: FftFourierLweBootstrapKey32 = fft_engine.convert_lwe_bootstrap_key(&bsk)?;
204    ///
205    /// let mut serialization_engine = FftSerializationEngine::new(())?;
206    /// let serialized = serialization_engine.serialize(&fourier_bsk)?;
207    /// let recovered = serialization_engine.deserialize(serialized.as_slice())?;
208    /// assert_eq!(fourier_bsk, recovered);
209    ///
210    /// #
211    /// # Ok(())
212    /// # }
213    /// ```
214    fn deserialize(
215        &mut self,
216        serialized: &[u8],
217    ) -> Result<FftFourierLweBootstrapKey32, EntityDeserializationError<Self::EngineError>> {
218        #[derive(Deserialize)]
219        struct SerializableFftFourierLweBootstrapKey32 {
220            version: FftFourierLweBootstrapKey32Version,
221            inner: FourierLweBootstrapKey<ABox<[c64]>>,
222        }
223        let deserialized: SerializableFftFourierLweBootstrapKey32 =
224            bincode::deserialize(serialized)
225                .map_err(FftSerializationError::Deserialization)
226                .map_err(EntityDeserializationError::Engine)?;
227        match deserialized {
228            SerializableFftFourierLweBootstrapKey32 {
229                version: FftFourierLweBootstrapKey32Version::Unsupported,
230                ..
231            } => Err(EntityDeserializationError::Engine(
232                FftSerializationError::UnsupportedVersion,
233            )),
234            SerializableFftFourierLweBootstrapKey32 {
235                version: FftFourierLweBootstrapKey32Version::V0,
236                inner,
237            } => Ok(FftFourierLweBootstrapKey32(inner)),
238        }
239    }
240
241    unsafe fn deserialize_unchecked(&mut self, serialized: &[u8]) -> FftFourierLweBootstrapKey32 {
242        self.deserialize(serialized).unwrap()
243    }
244}
245
246/// # Description:
247/// Implementation of [`EntityDeserializationEngine`] for [`FftSerializationEngine`] that operates
248/// on 64 bits integers. It deserializes an LWE bootstrap key in the Fourier domain.
249impl EntityDeserializationEngine<&[u8], FftFourierLweBootstrapKey64> for FftSerializationEngine {
250    /// # Example
251    /// ```
252    /// use concrete_core::prelude::{
253    ///     DecompositionBaseLog, DecompositionLevelCount, GlweDimension, LweDimension, PolynomialSize,
254    ///     Variance, *,
255    /// };
256    /// # use std::error::Error;
257    ///
258    /// # fn main() -> Result<(), Box<dyn Error>> {
259    /// // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
260    /// let (lwe_dim, glwe_dim, poly_size) = (LweDimension(4), GlweDimension(6), PolynomialSize(256));
261    /// let (dec_lc, dec_bl) = (DecompositionLevelCount(3), DecompositionBaseLog(5));
262    /// let noise = Variance(2_f64.powf(-25.));
263    ///
264    /// // Unix seeder must be given a secret input.
265    /// // Here we just give it 0, which is totally unsafe.
266    /// const UNSAFE_SECRET: u128 = 0;
267    /// let mut default_engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
268    /// let mut fft_engine = FftEngine::new(())?;
269    /// let lwe_sk: LweSecretKey64 = default_engine.generate_new_lwe_secret_key(lwe_dim)?;
270    /// let glwe_sk: GlweSecretKey64 =
271    ///     default_engine.generate_new_glwe_secret_key(glwe_dim, poly_size)?;
272    /// let bsk: LweBootstrapKey64 =
273    ///     default_engine.generate_new_lwe_bootstrap_key(&lwe_sk, &glwe_sk, dec_bl, dec_lc, noise)?;
274    ///
275    /// let fourier_bsk: FftFourierLweBootstrapKey64 = fft_engine.convert_lwe_bootstrap_key(&bsk)?;
276    ///
277    /// let mut serialization_engine = FftSerializationEngine::new(())?;
278    /// let serialized = serialization_engine.serialize(&fourier_bsk)?;
279    /// let recovered = serialization_engine.deserialize(serialized.as_slice())?;
280    /// assert_eq!(fourier_bsk, recovered);
281    ///
282    /// #
283    /// # Ok(())
284    /// # }
285    /// ```
286    fn deserialize(
287        &mut self,
288        serialized: &[u8],
289    ) -> Result<FftFourierLweBootstrapKey64, EntityDeserializationError<Self::EngineError>> {
290        #[derive(Deserialize)]
291        struct SerializableFftFourierLweBootstrapKey64 {
292            version: FftFourierLweBootstrapKey64Version,
293            inner: FourierLweBootstrapKey<ABox<[c64]>>,
294        }
295        let deserialized: SerializableFftFourierLweBootstrapKey64 =
296            bincode::deserialize(serialized)
297                .map_err(FftSerializationError::Deserialization)
298                .map_err(EntityDeserializationError::Engine)?;
299        match deserialized {
300            SerializableFftFourierLweBootstrapKey64 {
301                version: FftFourierLweBootstrapKey64Version::Unsupported,
302                ..
303            } => Err(EntityDeserializationError::Engine(
304                FftSerializationError::UnsupportedVersion,
305            )),
306            SerializableFftFourierLweBootstrapKey64 {
307                version: FftFourierLweBootstrapKey64Version::V0,
308                inner,
309            } => Ok(FftFourierLweBootstrapKey64(inner)),
310        }
311    }
312
313    unsafe fn deserialize_unchecked(&mut self, serialized: &[u8]) -> FftFourierLweBootstrapKey64 {
314        self.deserialize(serialized).unwrap()
315    }
316}