Skip to main content

tfhe/shortint/ciphertext/
compressed_modulus_switched_ciphertext.rs

1use tfhe_versionable::Versionize;
2
3use super::common::*;
4use crate::conformance::ParameterSetConformant;
5use crate::core_crypto::prelude::compressed_modulus_switched_lwe_ciphertext::CompressedModulusSwitchedLweCiphertext;
6use crate::core_crypto::prelude::compressed_modulus_switched_multi_bit_lwe_ciphertext::CompressedModulusSwitchedMultiBitLweCiphertext;
7use crate::core_crypto::prelude::CompressedModulusSwitchedLweCiphertextConformanceParams;
8use crate::shortint::backward_compatibility::ciphertext::{
9    CompressedModulusSwitchedCiphertextVersions,
10    InternalCompressedModulusSwitchedCiphertextVersions,
11};
12use crate::shortint::parameters::{AtomicPatternKind, CiphertextConformanceParams};
13use crate::shortint::{CarryModulus, MessageModulus};
14
15/// An object to store a ciphertext using less memory.
16/// Decompressing it requires a PBS
17///
18/// # Example
19///
20/// ```rust
21/// use tfhe::shortint::gen_keys;
22/// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
23///
24/// // Generate the client key and the server key:
25/// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
26///
27/// let clear = 3;
28///
29/// let ctxt = cks.unchecked_encrypt(clear);
30///
31/// // Can be serialized in a smaller buffer
32/// let compressed_ct = sks.switch_modulus_and_compress(&ctxt);
33///
34/// let decompressed_ct = sks.decompress(&compressed_ct);
35///
36/// let dec = cks.decrypt(&decompressed_ct);
37///
38/// assert_eq!(clear, dec);
39/// ```
40#[derive(Clone, serde::Serialize, serde::Deserialize, Versionize)]
41#[versionize(CompressedModulusSwitchedCiphertextVersions)]
42pub struct CompressedModulusSwitchedCiphertext {
43    pub(crate) compressed_modulus_switched_lwe_ciphertext:
44        InternalCompressedModulusSwitchedCiphertext,
45    pub(crate) degree: Degree,
46    pub(crate) message_modulus: MessageModulus,
47    pub(crate) carry_modulus: CarryModulus,
48    pub(crate) atomic_pattern: AtomicPatternKind,
49}
50
51#[derive(Copy, Clone)]
52pub struct CompressedModulusSwitchedCiphertextConformanceParams {
53    pub ct_params: CompressedModulusSwitchedLweCiphertextConformanceParams<u64>,
54    pub message_modulus: MessageModulus,
55    pub carry_modulus: CarryModulus,
56    pub degree: Degree,
57    pub atomic_pattern: AtomicPatternKind,
58}
59
60impl From<CompressedModulusSwitchedCiphertextConformanceParams> for CiphertextConformanceParams {
61    fn from(value: CompressedModulusSwitchedCiphertextConformanceParams) -> Self {
62        Self {
63            ct_params: value.ct_params.ct_params,
64            message_modulus: value.message_modulus,
65            carry_modulus: value.carry_modulus,
66            degree: value.degree,
67            noise_level: NoiseLevel::NOMINAL,
68            atomic_pattern: value.atomic_pattern,
69        }
70    }
71}
72
73impl ParameterSetConformant for CompressedModulusSwitchedCiphertext {
74    type ParameterSet = CompressedModulusSwitchedCiphertextConformanceParams;
75
76    fn is_conformant(&self, param: &CompressedModulusSwitchedCiphertextConformanceParams) -> bool {
77        let Self {
78            compressed_modulus_switched_lwe_ciphertext,
79            degree,
80            message_modulus,
81            carry_modulus,
82            atomic_pattern,
83        } = self;
84
85        let CompressedModulusSwitchedCiphertextConformanceParams {
86            ct_params,
87            message_modulus: param_message_modulus,
88            carry_modulus: param_carry_modulus,
89            degree: param_degree,
90            atomic_pattern: param_atomic_pattern,
91        } = param;
92
93        compressed_modulus_switched_lwe_ciphertext.is_conformant(ct_params)
94            && message_modulus == param_message_modulus
95            && carry_modulus == param_carry_modulus
96            && atomic_pattern == param_atomic_pattern
97            && degree == param_degree
98    }
99}
100
101#[derive(Clone, serde::Serialize, serde::Deserialize, Versionize)]
102#[versionize(InternalCompressedModulusSwitchedCiphertextVersions)]
103pub(crate) enum InternalCompressedModulusSwitchedCiphertext {
104    Classic(CompressedModulusSwitchedLweCiphertext<u64>),
105    MultiBit(CompressedModulusSwitchedMultiBitLweCiphertext<u64>),
106}
107
108impl ParameterSetConformant for InternalCompressedModulusSwitchedCiphertext {
109    type ParameterSet = CompressedModulusSwitchedLweCiphertextConformanceParams<u64>;
110
111    fn is_conformant(
112        &self,
113        param: &CompressedModulusSwitchedLweCiphertextConformanceParams<u64>,
114    ) -> bool {
115        match self {
116            Self::Classic(a) => a.is_conformant(param),
117            Self::MultiBit(a) => a.is_conformant(param),
118        }
119    }
120}