Skip to main content

tfhe/high_level_api/keys/
client.rs

1//! This module defines ClientKey
2//!
3//! - [ClientKey] aggregates the keys used to encrypt/decrypt between normal and homomorphic types.
4
5use super::{CompressedServerKey, ServerKey};
6use crate::high_level_api::backward_compatibility::keys::ClientKeyVersions;
7use crate::high_level_api::config::Config;
8use crate::high_level_api::keys::{CompactPrivateKey, IntegerClientKey};
9use crate::high_level_api::SquashedNoiseCiphertextState;
10use crate::integer::ciphertext::NoiseSquashingCompressionPrivateKey;
11use crate::integer::compression_keys::CompressionPrivateKeys;
12use crate::integer::noise_squashing::{NoiseSquashingPrivateKey, NoiseSquashingPrivateKeyView};
13use crate::integer::oprf::OprfPrivateKey;
14use crate::named::Named;
15use crate::prelude::Tagged;
16use crate::shortint::parameters::ReRandomizationParameters;
17use crate::shortint::MessageModulus;
18use crate::Tag;
19use tfhe_csprng::seeders::Seed;
20use tfhe_versionable::Versionize;
21
22/// Key of the client
23///
24/// This struct contains the keys that are of interest to the user
25/// as they will allow to encrypt and decrypt data.
26///
27/// This key **MUST NOT** be sent to the server.
28#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
29#[versionize(ClientKeyVersions)]
30pub struct ClientKey {
31    pub(crate) key: IntegerClientKey,
32    pub(crate) tag: Tag,
33}
34
35impl ClientKey {
36    /// Generates a new key from the given config.
37    pub fn generate<C: Into<Config>>(config: C) -> Self {
38        let config: Config = config.into();
39        Self {
40            key: IntegerClientKey::from(config.inner),
41            tag: Tag::default(),
42        }
43    }
44
45    /// Generates a key from a config and uses a seed.
46    ///
47    /// Using the same seed between generations allows to regenerate the same key.
48    ///
49    /// ```rust
50    /// use tfhe::{ClientKey, ConfigBuilder, Seed};
51    ///
52    /// let builder = ConfigBuilder::default();
53    /// let config = builder.build();
54    ///
55    /// let cks1 = ClientKey::generate_with_seed(config, Seed(125));
56    /// let cks2 = ClientKey::generate(config);
57    /// let cks3 = ClientKey::generate_with_seed(config, Seed(125));
58    ///
59    /// // The keys created with the same seed are equal
60    /// assert_eq!(
61    ///     bincode::serialize(&cks1).unwrap(),
62    ///     bincode::serialize(&cks3).unwrap()
63    /// );
64    /// // Which is not the case for keys not created using the same seed
65    /// assert_ne!(
66    ///     bincode::serialize(&cks1).unwrap(),
67    ///     bincode::serialize(&cks2).unwrap()
68    /// );
69    /// ```
70    pub fn generate_with_seed<C: Into<Config>>(config: C, seed: Seed) -> Self {
71        let config: Config = config.into();
72        Self {
73            key: IntegerClientKey::with_seed(config.inner, seed),
74            tag: Tag::default(),
75        }
76    }
77
78    pub fn computation_parameters(&self) -> crate::shortint::AtomicPatternParameters {
79        self.key.block_parameters()
80    }
81
82    #[allow(clippy::type_complexity)]
83    pub fn into_raw_parts(
84        self,
85    ) -> (
86        crate::integer::ClientKey,
87        Option<CompactPrivateKey>,
88        Option<CompressionPrivateKeys>,
89        Option<NoiseSquashingPrivateKey>,
90        Option<NoiseSquashingCompressionPrivateKey>,
91        Option<ReRandomizationParameters>,
92        Option<OprfPrivateKey>,
93        Tag,
94    ) {
95        let (cks, cpk, cppk, nsk, nscpk, cpkrndp, oprf) = self.key.into_raw_parts();
96        (cks, cpk, cppk, nsk, nscpk, cpkrndp, oprf, self.tag)
97    }
98
99    #[allow(clippy::too_many_arguments)]
100    pub fn from_raw_parts(
101        key: crate::integer::ClientKey,
102        dedicated_compact_private_key: Option<(
103            crate::integer::CompactPrivateKey<Vec<u64>>,
104            crate::shortint::parameters::key_switching::ShortintKeySwitchingParameters,
105        )>,
106        compression_key: Option<CompressionPrivateKeys>,
107        noise_squashing_key: Option<NoiseSquashingPrivateKey>,
108        noise_squashing_compression_key: Option<NoiseSquashingCompressionPrivateKey>,
109        cpk_re_randomization_params: Option<ReRandomizationParameters>,
110        oprf_private_key: Option<OprfPrivateKey>,
111        tag: Tag,
112    ) -> Self {
113        Self {
114            key: IntegerClientKey::from_raw_parts(
115                key,
116                dedicated_compact_private_key,
117                compression_key,
118                noise_squashing_key,
119                noise_squashing_compression_key,
120                cpk_re_randomization_params,
121                oprf_private_key,
122            ),
123            tag,
124        }
125    }
126
127    /// Generates a new ServerKey
128    ///
129    /// The `ServerKey` generated is meant to be used to initialize the global state
130    /// using [crate::high_level_api::set_server_key].
131    pub fn generate_server_key(&self) -> ServerKey {
132        ServerKey::new(self)
133    }
134
135    /// Generates a new CompressedServerKey
136    pub fn generate_compressed_server_key(&self) -> CompressedServerKey {
137        CompressedServerKey::new(self)
138    }
139
140    pub(crate) fn message_modulus(&self) -> MessageModulus {
141        self.key.block_parameters().message_modulus()
142    }
143
144    /// Returns a view of the private key to be used to decrypt a squashed noise
145    /// ciphertext depending on its state
146    ///
147    /// # Panics
148    ///
149    /// Panics if the key supposed to be used for the given state cannot be found
150    pub(crate) fn private_noise_squashing_decryption_key(
151        &self,
152        state: SquashedNoiseCiphertextState,
153    ) -> NoiseSquashingPrivateKeyView<'_> {
154        match state {
155            SquashedNoiseCiphertextState::Normal => self
156                .key
157                .noise_squashing_private_key
158                .as_ref()
159                .map(|key| key.as_view())
160                .expect(
161                    "No noise squashing private key in your ClientKey, cannot decrypt. \
162                    Did you call `enable_noise_squashing` when creating your Config?",
163                ),
164            SquashedNoiseCiphertextState::PostDecompression => self
165                .key
166                .noise_squashing_compression_private_key
167                .as_ref()
168                .map(|key| key.private_key_view())
169                .expect(
170                    "No noise squashing private key in your ClientKey, cannot decrypt. \
171                    Did you call `enable_noise_squashing_compression` when creating your Config?",
172                ),
173        }
174    }
175}
176
177impl Tagged for ClientKey {
178    fn tag(&self) -> &Tag {
179        &self.tag
180    }
181
182    fn tag_mut(&mut self) -> &mut Tag {
183        &mut self.tag
184    }
185}
186
187impl AsRef<crate::integer::ClientKey> for ClientKey {
188    fn as_ref(&self) -> &crate::integer::ClientKey {
189        &self.key.key
190    }
191}
192
193impl Named for ClientKey {
194    const NAME: &'static str = "high_level_api::ClientKey";
195}