tfhe/shortint/client_key/mod.rs
1//! Module with the definition of the ClientKey.
2
3pub mod atomic_pattern;
4pub(crate) mod secret_encryption_key;
5use atomic_pattern::{
6 AtomicPatternClientKey, EncryptionAtomicPattern, StandardAtomicPatternClientKey,
7};
8use tfhe_versionable::Versionize;
9
10use super::parameters::ShortintKeySwitchingParameters;
11use super::server_key::UnsupportedOperation;
12use super::{AtomicPatternParameters, PaddingBit, ShortintEncoding};
13use crate::core_crypto::entities::*;
14use crate::core_crypto::prelude::decrypt_lwe_ciphertext;
15use crate::shortint::backward_compatibility::client_key::ClientKeyVersions;
16use crate::shortint::ciphertext::{Ciphertext, CompressedCiphertext};
17use crate::shortint::engine::ShortintEngine;
18use crate::shortint::parameters::{DynamicDistribution, MessageModulus, ShortintParameterSet};
19use crate::shortint::CarryModulus;
20use secret_encryption_key::SecretEncryptionKeyView;
21use serde::{Deserialize, Serialize};
22use std::fmt::{Debug, Display};
23
24/// A structure containing the client key, which must be kept secret.
25///
26/// In more details, it contains:
27/// * `lwe_secret_key` - an LWE secret key, used to encrypt the inputs and decrypt the outputs. This
28/// secret key is also used in the generation of bootstrapping and key switching keys.
29/// * `glwe_secret_key` - a GLWE secret key, used to generate the bootstrapping keys and key
30/// switching keys.
31/// * `parameters` - the cryptographic parameter set.
32#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)]
33#[versionize(ClientKeyVersions)]
34pub struct GenericClientKey<AP> {
35 pub atomic_pattern: AP,
36}
37
38pub type ClientKey = GenericClientKey<AtomicPatternClientKey>;
39pub type StandardClientKey = GenericClientKey<StandardAtomicPatternClientKey>;
40pub type ClientKeyView<'key> = GenericClientKey<&'key AtomicPatternClientKey>;
41pub type StandardClientKeyView<'key> = GenericClientKey<&'key StandardAtomicPatternClientKey>;
42
43impl<'cks> From<&'cks ClientKey> for SecretEncryptionKeyView<'cks> {
44 fn from(value: &'cks ClientKey) -> Self {
45 Self {
46 lwe_secret_key: value.encryption_key(),
47 message_modulus: value.parameters().message_modulus(),
48 carry_modulus: value.parameters().carry_modulus(),
49 }
50 }
51}
52
53impl<'key> TryFrom<ClientKeyView<'key>> for StandardClientKeyView<'key> {
54 type Error = UnsupportedOperation;
55
56 fn try_from(value: ClientKeyView<'key>) -> Result<Self, Self::Error> {
57 let AtomicPatternClientKey::Standard(atomic_pattern) = value.atomic_pattern else {
58 return Err(UnsupportedOperation);
59 };
60
61 Ok(Self { atomic_pattern })
62 }
63}
64
65impl<AP> GenericClientKey<AP> {
66 pub fn as_view(&self) -> GenericClientKey<&AP> {
67 GenericClientKey {
68 atomic_pattern: &self.atomic_pattern,
69 }
70 }
71}
72
73impl ClientKey {
74 /// Generate a client key.
75 ///
76 /// # Example
77 ///
78 /// ```rust
79 /// use tfhe::shortint::client_key::ClientKey;
80 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
81 ///
82 /// // Generate the client key:
83 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
84 /// ```
85 pub fn new<P>(parameters: P) -> Self
86 where
87 P: TryInto<ShortintParameterSet>,
88 <P as TryInto<ShortintParameterSet>>::Error: Debug,
89 {
90 ShortintEngine::with_thread_local_mut(|engine| engine.new_client_key(parameters))
91 }
92
93 pub fn try_from_lwe_encryption_key<P>(
94 encryption_key: LweSecretKeyOwned<u64>,
95 parameters: P,
96 ) -> crate::Result<Self>
97 where
98 P: TryInto<AtomicPatternParameters>,
99 <P as TryInto<AtomicPatternParameters>>::Error: Display,
100 {
101 let parameters = parameters
102 .try_into()
103 .map_err(|err| crate::Error::new(format!("{err}")))?;
104
105 let atomic_pattern =
106 AtomicPatternClientKey::try_from_lwe_encryption_key(encryption_key, parameters)?;
107
108 Ok(Self { atomic_pattern })
109 }
110}
111
112impl<AP: EncryptionAtomicPattern> GenericClientKey<AP> {
113 pub fn parameters(&self) -> ShortintParameterSet {
114 self.atomic_pattern.parameters()
115 }
116
117 /// Returns a view of the key used for encryption
118 pub fn encryption_key(&self) -> LweSecretKeyView<'_, u64> {
119 self.atomic_pattern.encryption_key()
120 }
121
122 /// Returns a view to the encryption key and the corresponding noise distribution.
123 pub fn encryption_key_and_noise(
124 &self,
125 ) -> (LweSecretKeyView<'_, u64>, DynamicDistribution<u64>) {
126 self.atomic_pattern.encryption_key_and_noise()
127 }
128
129 #[cfg(test)]
130 pub fn create_trivial(&self, value: u64) -> Ciphertext {
131 let modular_value = value % self.parameters().message_modulus().0;
132 self.unchecked_create_trivial(modular_value)
133 }
134
135 #[cfg(test)]
136 pub fn unchecked_create_trivial(&self, value: u64) -> Ciphertext {
137 let params = self.parameters();
138
139 let lwe_size = params.encryption_lwe_dimension().to_lwe_size();
140
141 super::ciphertext::unchecked_create_trivial_with_lwe_size(
142 Cleartext(value),
143 lwe_size,
144 params.message_modulus(),
145 params.carry_modulus(),
146 params.atomic_pattern(),
147 params.ciphertext_modulus(),
148 )
149 }
150
151 /// Encrypt a small integer message using the client key.
152 ///
153 /// The input message is reduced to the encrypted message space modulus
154 ///
155 /// # Example
156 ///
157 /// ```rust
158 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
159 /// use tfhe::shortint::ClientKey;
160 ///
161 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
162 ///
163 /// // Encryption of one message that is within the encrypted message modulus:
164 /// let msg = 3;
165 /// let ct = cks.encrypt(msg);
166 ///
167 /// let dec = cks.decrypt(&ct);
168 /// assert_eq!(msg, dec);
169 ///
170 /// // Encryption of one message that is outside the encrypted message modulus:
171 /// let msg = 5;
172 /// let ct = cks.encrypt(msg);
173 ///
174 /// let dec = cks.decrypt(&ct);
175 /// let modulus = cks.parameters().message_modulus().0;
176 /// assert_eq!(msg % modulus, dec);
177 /// ```
178 pub fn encrypt(&self, message: u64) -> Ciphertext {
179 ShortintEngine::with_thread_local_mut(|engine| engine.encrypt(self, message))
180 }
181
182 /// Encrypt a integer message using the client key returning a compressed ciphertext.
183 ///
184 /// The input message is reduced to the encrypted message space modulus
185 ///
186 /// # Example
187 ///
188 /// ```rust
189 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
190 /// use tfhe::shortint::ClientKey;
191 ///
192 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
193 ///
194 /// // Encryption of one message that is within the encrypted message modulus:
195 /// let msg = 3;
196 /// let ct = cks.encrypt_compressed(msg);
197 ///
198 /// let ct = ct.decompress();
199 ///
200 /// let dec = cks.decrypt(&ct);
201 /// assert_eq!(msg, dec);
202 ///
203 /// // Encryption of one message that is outside the encrypted message modulus:
204 /// let msg = 5;
205 /// let ct = cks.encrypt_compressed(msg);
206 ///
207 /// let ct = ct.decompress();
208 ///
209 /// let dec = cks.decrypt(&ct);
210 /// let modulus = cks.parameters().message_modulus().0;
211 /// assert_eq!(msg % modulus, dec);
212 /// ```
213 pub fn encrypt_compressed(&self, message: u64) -> CompressedCiphertext {
214 ShortintEngine::with_thread_local_mut(|engine| engine.encrypt_compressed(self, message))
215 }
216
217 /// Encrypt a small integer message using the client key with a specific message modulus
218 ///
219 /// # Example
220 ///
221 /// ```rust
222 /// use tfhe::shortint::parameters::{MessageModulus, PARAM_MESSAGE_2_CARRY_2_KS_PBS};
223 /// use tfhe::shortint::ClientKey;
224 ///
225 /// // Generate the client key
226 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
227 ///
228 /// let msg = 3;
229 ///
230 /// // Encryption of one message:
231 /// let ct = cks.encrypt_with_message_modulus(msg, MessageModulus(6));
232 ///
233 /// // Decryption:
234 /// let dec = cks.decrypt(&ct);
235 /// assert_eq!(msg, dec);
236 /// ```
237 pub fn encrypt_with_message_modulus(
238 &self,
239 message: u64,
240 message_modulus: MessageModulus,
241 ) -> Ciphertext {
242 ShortintEngine::with_thread_local_mut(|engine| {
243 engine.encrypt_with_message_modulus(self, message, message_modulus)
244 })
245 }
246
247 /// Encrypt a small integer message using the client key with a specific message and carry
248 /// moduli.
249 ///
250 /// # Warning
251 /// Defining specific message AND carry moduli might lead to incorrect homomorphic
252 /// computations.
253 ///
254 /// # Example
255 ///
256 /// ```rust
257 /// use tfhe::shortint::parameters::{MessageModulus, PARAM_MESSAGE_2_CARRY_2};
258 /// use tfhe::shortint::{CarryModulus, ClientKey};
259 ///
260 /// // Generate the client key
261 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2);
262 ///
263 /// let msg = 3;
264 ///
265 /// // Encryption of one message with MessageModulus = 2 and CarryModulus = 2
266 /// // so that 6*2 < 2^(2 + 2) from the parameter set
267 /// let ct = cks.encrypt_with_message_and_carry_modulus(msg, MessageModulus(6), CarryModulus(2));
268 ///
269 /// // Decryption:
270 /// let dec = cks.decrypt(&ct);
271 /// assert_eq!(msg, dec);
272 /// ```
273 pub fn encrypt_with_message_and_carry_modulus(
274 &self,
275 message: u64,
276 message_modulus: MessageModulus,
277 carry_modulus: CarryModulus,
278 ) -> Ciphertext {
279 ShortintEngine::with_thread_local_mut(|engine| {
280 engine.encrypt_with_message_and_carry_modulus(
281 self,
282 message,
283 message_modulus,
284 carry_modulus,
285 )
286 })
287 }
288
289 /// Encrypt a small integer message using the client key with a specific message modulus
290 /// returning a compressed ciphertext
291 ///
292 /// # Example
293 ///
294 /// ```rust
295 /// use tfhe::shortint::parameters::{MessageModulus, PARAM_MESSAGE_2_CARRY_2_KS_PBS};
296 /// use tfhe::shortint::ClientKey;
297 ///
298 /// // Generate the client key
299 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
300 ///
301 /// let msg = 3;
302 ///
303 /// // Encryption of one message:
304 /// let ct = cks.encrypt_with_message_modulus_compressed(msg, MessageModulus(6));
305 ///
306 /// let ct = ct.decompress();
307 ///
308 /// // Decryption:
309 /// let dec = cks.decrypt(&ct);
310 /// assert_eq!(msg, dec);
311 /// ```
312 pub fn encrypt_with_message_modulus_compressed(
313 &self,
314 message: u64,
315 message_modulus: MessageModulus,
316 ) -> CompressedCiphertext {
317 ShortintEngine::with_thread_local_mut(|engine| {
318 engine.encrypt_with_message_modulus_compressed(self, message, message_modulus)
319 })
320 }
321
322 /// Encrypt an integer without reducing the input message modulus the message space
323 ///
324 /// # Example
325 ///
326 /// ```rust
327 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
328 /// use tfhe::shortint::ClientKey;
329 ///
330 /// // Generate the client key
331 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
332 ///
333 /// let msg = 7;
334 /// let ct = cks.unchecked_encrypt(msg);
335 /// // | ct |
336 /// // | carry | message |
337 /// // |-------|---------|
338 /// // | 0 1 | 1 1 |
339 ///
340 /// let dec = cks.decrypt_message_and_carry(&ct);
341 /// assert_eq!(msg, dec);
342 /// ```
343 pub fn unchecked_encrypt(&self, message: u64) -> Ciphertext {
344 ShortintEngine::with_thread_local_mut(|engine| engine.unchecked_encrypt(self, message))
345 }
346
347 /// Decrypt a ciphertext encrypting an integer message and carries using the client key.
348 ///
349 /// # Example
350 ///
351 /// ```rust
352 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
353 /// use tfhe::shortint::ClientKey;
354 ///
355 /// // Generate the client key
356 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
357 ///
358 /// let msg = 3;
359 ///
360 /// // Encryption of one message:
361 /// let ct = cks.encrypt(msg);
362 ///
363 /// // Decryption:
364 /// let dec = cks.decrypt_message_and_carry(&ct);
365 /// assert_eq!(msg, dec);
366 /// ```
367 pub fn decrypt_message_and_carry(&self, ct: &Ciphertext) -> u64 {
368 let decrypted_u64 = self.decrypt_no_decode(ct);
369
370 ShortintEncoding::from_parameters(self.parameters(), PaddingBit::Yes)
371 .decode(decrypted_u64)
372 .0
373 }
374
375 /// Decrypt a ciphertext encrypting a message using the client key.
376 ///
377 /// # Example
378 ///
379 /// ```rust
380 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
381 /// use tfhe::shortint::ClientKey;
382 ///
383 /// // Generate the client key
384 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
385 ///
386 /// let msg = 3;
387 ///
388 /// // Encryption of one message:
389 /// let ct = cks.encrypt(msg);
390 ///
391 /// // Decryption:
392 /// let dec = cks.decrypt(&ct);
393 /// assert_eq!(msg, dec);
394 /// ```
395 pub fn decrypt(&self, ct: &Ciphertext) -> u64 {
396 self.decrypt_message_and_carry(ct) % ct.message_modulus.0
397 }
398
399 /// Decrypt a ciphertext without decoding the message, using the client key.
400 ///
401 /// This can be used to extract noise values after doing some computations.
402 ///
403 /// # Example
404 ///
405 /// ```rust
406 /// use tfhe::shortint::gen_keys;
407 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
408 ///
409 /// // Generate the keys
410 /// let (cks, sks) = gen_keys(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
411 ///
412 /// let msg = 3;
413 ///
414 /// // Encryption of two messages:
415 /// let ct1 = cks.encrypt(msg);
416 /// let ct2 = cks.encrypt(msg);
417 ///
418 /// // Compute homomorphically an addition to generate a carry
419 /// let ct_res = sks.unchecked_add(&ct1, &ct2);
420 ///
421 /// // Decrypt:
422 /// let res = cks.decrypt_no_decode(&ct_res);
423 /// let expected_res = 3 + 3;
424 /// // Delta for params 2_2 with a padding bit
425 /// let delta = (1u64 << (u64::BITS - 1 - 1)) / 16 * 2;
426 /// let noise = res.0.wrapping_sub(expected_res * delta);
427 ///
428 /// assert!((noise as i64).abs() < delta as i64 / 2);
429 /// ```
430 pub fn decrypt_no_decode(&self, ct: &Ciphertext) -> Plaintext<u64> {
431 let lwe_decryption_key = self.encryption_key();
432
433 decrypt_lwe_ciphertext(&lwe_decryption_key, &ct.ct)
434 }
435
436 /// Encrypt a small integer message using the client key without padding bit.
437 ///
438 /// The input message is reduced to the encrypted message space modulus
439 ///
440 /// # Example
441 ///
442 /// ```rust
443 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
444 /// use tfhe::shortint::ClientKey;
445 ///
446 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
447 ///
448 /// // Encryption of one message that is within the encrypted message modulus:
449 /// let msg = 6;
450 /// let ct = cks.encrypt_without_padding(msg);
451 ///
452 /// let dec = cks.decrypt_message_and_carry_without_padding(&ct);
453 /// assert_eq!(msg, dec);
454 /// ```
455 pub fn encrypt_without_padding(&self, message: u64) -> Ciphertext {
456 ShortintEngine::with_thread_local_mut(|engine| {
457 engine.encrypt_without_padding(self, message)
458 })
459 }
460
461 /// Encrypt a small integer message using the client key without padding bit returning a
462 /// compressed message.
463 ///
464 /// The input message is reduced to the encrypted message space modulus
465 ///
466 /// # Example
467 ///
468 /// ```rust
469 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
470 /// use tfhe::shortint::ClientKey;
471 ///
472 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
473 ///
474 /// // Encryption of one message that is within the encrypted message modulus:
475 /// let msg = 6;
476 /// let ct = cks.encrypt_without_padding_compressed(msg);
477 ///
478 /// let ct = ct.decompress();
479 ///
480 /// let dec = cks.decrypt_message_and_carry_without_padding(&ct);
481 /// assert_eq!(msg, dec);
482 /// ```
483 pub fn encrypt_without_padding_compressed(&self, message: u64) -> CompressedCiphertext {
484 ShortintEngine::with_thread_local_mut(|engine| {
485 engine.encrypt_without_padding_compressed(self, message)
486 })
487 }
488
489 /// Decrypt a ciphertext encrypting an integer message and carries using the client key,
490 /// where the ciphertext is assumed to not have any padding bit.
491 ///
492 /// # Example
493 ///
494 /// ```rust
495 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
496 /// use tfhe::shortint::ClientKey;
497 ///
498 /// // Generate the client key
499 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
500 ///
501 /// let msg = 3;
502 ///
503 /// // Encryption of one message:
504 /// let ct = cks.encrypt_without_padding(msg);
505 ///
506 /// // Decryption:
507 /// let dec = cks.decrypt_message_and_carry_without_padding(&ct);
508 /// assert_eq!(msg, dec);
509 /// ```
510 pub fn decrypt_message_and_carry_without_padding(&self, ct: &Ciphertext) -> u64 {
511 let decrypted_u64 = self.decrypt_no_decode(ct);
512
513 ShortintEncoding::from_parameters(self.parameters(), PaddingBit::No)
514 .decode(decrypted_u64)
515 .0
516 }
517
518 /// Decrypt a ciphertext encrypting an integer message using the client key,
519 /// where the ciphertext is assumed to not have any padding bit.
520 ///
521 /// # Example
522 ///
523 /// ```rust
524 /// use tfhe::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
525 /// use tfhe::shortint::ClientKey;
526 ///
527 /// // Generate the client key
528 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
529 ///
530 /// let msg = 7;
531 /// let modulus = 4;
532 ///
533 /// // Encryption of one message:
534 /// let ct = cks.encrypt_without_padding(msg);
535 ///
536 /// // Decryption:
537 /// let dec = cks.decrypt_without_padding(&ct);
538 /// assert_eq!(msg % modulus, dec);
539 /// ```
540 pub fn decrypt_without_padding(&self, ct: &Ciphertext) -> u64 {
541 self.decrypt_message_and_carry_without_padding(ct) % ct.message_modulus.0
542 }
543
544 /// Encrypt a small integer message using the client key without padding bit with some modulus.
545 ///
546 /// The input message is reduced to the encrypted message space modulus
547 ///
548 /// # Example
549 ///
550 /// ```rust
551 /// use tfhe::shortint::parameters::{MessageModulus, PARAM_MESSAGE_2_CARRY_2_KS_PBS};
552 /// use tfhe::shortint::ClientKey;
553 ///
554 /// // Generate the client key
555 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
556 ///
557 /// let msg = 2;
558 /// let modulus = MessageModulus(3);
559 ///
560 /// // Encryption of one message:
561 /// let ct = cks.encrypt_native_crt(msg, modulus);
562 ///
563 /// // Decryption:
564 /// let dec = cks.decrypt_message_native_crt(&ct, modulus);
565 /// assert_eq!(msg, dec % modulus.0);
566 /// ```
567 pub fn encrypt_native_crt(&self, message: u64, message_modulus: MessageModulus) -> Ciphertext {
568 ShortintEngine::with_thread_local_mut(|engine| {
569 engine.encrypt_native_crt(self, message, message_modulus)
570 })
571 }
572
573 /// Encrypt a small integer message using the client key without padding bit with some modulus
574 /// returning a compressed ciphertext.
575 ///
576 /// The input message is reduced to the encrypted message space modulus
577 ///
578 /// # Example
579 ///
580 /// ```rust
581 /// use tfhe::shortint::parameters::{MessageModulus, PARAM_MESSAGE_2_CARRY_2_KS_PBS};
582 /// use tfhe::shortint::ClientKey;
583 ///
584 /// // Generate the client key
585 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
586 ///
587 /// let msg = 2;
588 /// let modulus = MessageModulus(3);
589 ///
590 /// // Encryption of one message:
591 /// let ct = cks.encrypt_native_crt_compressed(msg, modulus);
592 ///
593 /// let ct = ct.decompress();
594 ///
595 /// // Decryption:
596 /// let dec = cks.decrypt_message_native_crt(&ct, modulus);
597 /// assert_eq!(msg, dec % modulus.0);
598 /// ```
599 pub fn encrypt_native_crt_compressed(
600 &self,
601 message: u64,
602 message_modulus: MessageModulus,
603 ) -> CompressedCiphertext {
604 ShortintEngine::with_thread_local_mut(|engine| {
605 engine.encrypt_native_crt_compressed(self, message, message_modulus)
606 })
607 }
608
609 /// Decrypt a ciphertext encrypting an integer message using the client key,
610 /// where the ciphertext is assumed to not have any padding bit and is related to some modulus.
611 ///
612 /// # Example
613 ///
614 /// ```rust
615 /// use tfhe::shortint::parameters::{MessageModulus, PARAM_MESSAGE_2_CARRY_2_KS_PBS};
616 /// use tfhe::shortint::ClientKey;
617 ///
618 /// // Generate the client key
619 /// let cks = ClientKey::new(PARAM_MESSAGE_2_CARRY_2_KS_PBS);
620 ///
621 /// let msg = 1;
622 /// let modulus = MessageModulus(3);
623 ///
624 /// // Encryption of one message:
625 /// let ct = cks.encrypt_native_crt(msg, modulus);
626 ///
627 /// // Decryption:
628 /// let dec = cks.decrypt_message_native_crt(&ct, modulus);
629 /// assert_eq!(msg, dec % modulus.0);
630 /// ```
631 pub fn decrypt_message_native_crt(
632 &self,
633 ct: &Ciphertext,
634 message_modulus: MessageModulus,
635 ) -> u64 {
636 let basis = message_modulus.0;
637
638 let decrypted_u64: u64 = self.decrypt_no_decode(ct).0;
639
640 let mut result = decrypted_u64 as u128 * basis as u128;
641 result = result.wrapping_add((result & (1 << 63)) << 1) / (1 << 64);
642
643 result as u64 % basis
644 }
645}
646
647impl StandardClientKeyView<'_> {
648 /// Returns a view to the encryption key used for a keyswitch operation and the corresponding
649 /// noise distribution.
650 pub fn keyswitch_encryption_key_and_noise(
651 &self,
652 params: ShortintKeySwitchingParameters,
653 ) -> (LweSecretKeyView<'_, u64>, DynamicDistribution<u64>) {
654 self.atomic_pattern
655 .keyswitch_encryption_key_and_noise(params)
656 }
657}