tfhe/shortint/parameters/
classic.rs

1use crate::core_crypto::prelude::{LweCiphertextConformanceParams, MsDecompressionType};
2use crate::shortint::backward_compatibility::parameters::ClassicPBSParametersVersions;
3use crate::shortint::parameters::{
4    AtomicPatternKind, CarryModulus, CiphertextConformanceParams, CiphertextModulus,
5    DecompositionBaseLog, DecompositionLevelCount, Degree, DynamicDistribution,
6    EncryptionKeyChoice, GlweDimension, LweDimension, MaxNoiseLevel, MessageModulus,
7    ModulusSwitchNoiseReductionParams, NoiseLevel, PBSOrder, PolynomialSize,
8};
9
10use serde::{Deserialize, Serialize};
11use tfhe_versionable::Versionize;
12
13/// A structure defining the set of cryptographic parameters for homomorphic integer circuit
14/// evaluation.
15///
16/// The choice of encryption key for (`shortint
17/// ciphertext`)[`crate::shortint::ciphertext::Ciphertext`].
18///
19/// * The `Big` choice means the big LWE key derived from the GLWE key is used to encrypt the input
20///   ciphertext. This offers better performance but the (`public
21///   key`)[`crate::shortint::public_key::PublicKey`] can be extremely large and in some cases may
22///   not fit in memory. When refreshing a ciphertext and/or evaluating a table lookup the keyswitch
23///   is computed first followed by a PBS, the keyswitch goes from the large key to the small key
24///   and the PBS goes from the small key to the large key.
25/// * The `Small` choice means the small LWE key is used to encrypt the input ciphertext.
26///   Performance is not as good as in the `Big` case but (`public
27///   key`)[`crate::shortint::public_key::PublicKey`] sizes are much more manageable and should
28///   always fit in memory. When refreshing a ciphertext and/or evaluating a table lookup the PBS is
29///   computed first followed by a keyswitch, the PBS goes from the small key to the large key and
30///   the keyswitch goes from the large key to the small key.
31#[derive(Serialize, Copy, Clone, Deserialize, Debug, PartialEq, Versionize)]
32#[versionize(ClassicPBSParametersVersions)]
33pub struct ClassicPBSParameters {
34    pub lwe_dimension: LweDimension,
35    pub glwe_dimension: GlweDimension,
36    pub polynomial_size: PolynomialSize,
37    pub lwe_noise_distribution: DynamicDistribution<u64>,
38    pub glwe_noise_distribution: DynamicDistribution<u64>,
39    pub pbs_base_log: DecompositionBaseLog,
40    pub pbs_level: DecompositionLevelCount,
41    pub ks_base_log: DecompositionBaseLog,
42    pub ks_level: DecompositionLevelCount,
43    pub message_modulus: MessageModulus,
44    pub carry_modulus: CarryModulus,
45    pub max_noise_level: MaxNoiseLevel,
46    pub log2_p_fail: f64,
47    pub ciphertext_modulus: CiphertextModulus,
48    pub encryption_key_choice: EncryptionKeyChoice,
49    pub modulus_switch_noise_reduction_params: Option<ModulusSwitchNoiseReductionParams>,
50}
51
52impl ClassicPBSParameters {
53    /// Constructs a new set of parameters for integer circuit evaluation.
54    ///
55    /// # Warning
56    ///
57    /// Failing to fix the parameters properly would yield incorrect and unsecure computation.
58    /// Unless you are a cryptographer who really knows the impact of each of those parameters, you
59    /// __must__ stick with the provided parameters.
60    #[allow(clippy::too_many_arguments)]
61    pub fn new(
62        lwe_dimension: LweDimension,
63        glwe_dimension: GlweDimension,
64        polynomial_size: PolynomialSize,
65        lwe_noise_distribution: DynamicDistribution<u64>,
66        glwe_noise_distribution: DynamicDistribution<u64>,
67        pbs_base_log: DecompositionBaseLog,
68        pbs_level: DecompositionLevelCount,
69        ks_base_log: DecompositionBaseLog,
70        ks_level: DecompositionLevelCount,
71        message_modulus: MessageModulus,
72        carry_modulus: CarryModulus,
73        max_noise_level: MaxNoiseLevel,
74        log2_p_fail: f64,
75        ciphertext_modulus: CiphertextModulus,
76        encryption_key_choice: EncryptionKeyChoice,
77        modulus_switch_noise_reduction_params: Option<ModulusSwitchNoiseReductionParams>,
78    ) -> Self {
79        Self {
80            lwe_dimension,
81            glwe_dimension,
82            polynomial_size,
83            lwe_noise_distribution,
84            glwe_noise_distribution,
85            pbs_base_log,
86            pbs_level,
87            ks_base_log,
88            ks_level,
89            message_modulus,
90            carry_modulus,
91            max_noise_level,
92            log2_p_fail,
93            ciphertext_modulus,
94            encryption_key_choice,
95            modulus_switch_noise_reduction_params,
96        }
97    }
98
99    pub fn to_shortint_conformance_param(&self) -> CiphertextConformanceParams {
100        let (atomic_pattern, expected_dim) = match self.encryption_key_choice {
101            EncryptionKeyChoice::Big => (
102                AtomicPatternKind::Standard(PBSOrder::KeyswitchBootstrap),
103                self.glwe_dimension
104                    .to_equivalent_lwe_dimension(self.polynomial_size),
105            ),
106            EncryptionKeyChoice::Small => (
107                AtomicPatternKind::Standard(PBSOrder::BootstrapKeyswitch),
108                self.lwe_dimension,
109            ),
110        };
111
112        let message_modulus = self.message_modulus;
113        let ciphertext_modulus = self.ciphertext_modulus;
114        let carry_modulus = self.carry_modulus;
115
116        let degree = Degree::new(message_modulus.0 - 1);
117
118        let noise_level = NoiseLevel::NOMINAL;
119
120        CiphertextConformanceParams {
121            ct_params: LweCiphertextConformanceParams {
122                lwe_dim: expected_dim,
123                ct_modulus: ciphertext_modulus,
124                ms_decompression_method: MsDecompressionType::ClassicPbs,
125            },
126            message_modulus,
127            carry_modulus,
128            atomic_pattern,
129            degree,
130            noise_level,
131        }
132    }
133}