@@ -9,14 +9,14 @@ pub(crate) mod secret_encryption_key;
9
9
pub ( crate ) mod utils;
10
10
11
11
use super :: backward_compatibility:: client_key:: ClientKeyVersions ;
12
- use super :: block_decomposition:: { DecomposableInto , RecomposableFrom } ;
13
12
use super :: ciphertext:: {
14
13
CompressedRadixCiphertext , CompressedSignedRadixCiphertext , RadixCiphertext ,
15
14
SignedRadixCiphertext ,
16
15
} ;
17
- use crate :: core_crypto:: prelude:: { CastFrom , SignedNumeric , UnsignedNumeric } ;
18
- use crate :: integer:: bigint:: static_signed:: StaticSignedBigInt ;
19
- use crate :: integer:: block_decomposition:: BlockRecomposer ;
16
+ use crate :: core_crypto:: prelude:: { SignedNumeric , UnsignedNumeric } ;
17
+ use crate :: integer:: block_decomposition:: {
18
+ BlockRecomposer , DecomposableInto , RecomposableFrom , RecomposableSignedInteger ,
19
+ } ;
20
20
use crate :: integer:: ciphertext:: boolean_value:: BooleanBlock ;
21
21
use crate :: integer:: ciphertext:: { CompressedCrtCiphertext , CrtCiphertext } ;
22
22
use crate :: integer:: client_key:: utils:: i_crt;
@@ -33,53 +33,6 @@ use secret_encryption_key::SecretEncryptionKeyView;
33
33
use serde:: { Deserialize , Serialize } ;
34
34
use tfhe_versionable:: Versionize ;
35
35
36
- pub trait RecomposableSignedInteger :
37
- RecomposableFrom < u64 >
38
- + std:: ops:: Neg < Output = Self >
39
- + std:: ops:: Shr < u32 , Output = Self >
40
- + std:: ops:: BitOrAssign < Self >
41
- + std:: ops:: BitOr < Self , Output = Self >
42
- + std:: ops:: Mul < Self , Output = Self >
43
- + CastFrom < Self >
44
- + SignedNumeric
45
- {
46
- }
47
-
48
- impl RecomposableSignedInteger for i8 { }
49
- impl RecomposableSignedInteger for i16 { }
50
- impl RecomposableSignedInteger for i32 { }
51
- impl RecomposableSignedInteger for i64 { }
52
- impl RecomposableSignedInteger for i128 { }
53
-
54
- impl < const N : usize > RecomposableSignedInteger for StaticSignedBigInt < N > { }
55
-
56
- /// This function takes a signed integer of type `T` for which `num_bits_set`
57
- /// have been set.
58
- ///
59
- /// It will set the most significant bits to the value of the bit
60
- /// at pos `num_bits_set - 1`.
61
- ///
62
- /// This is used to correctly decrypt a signed radix ciphertext into a clear type
63
- /// that has more bits than the original ciphertext.
64
- ///
65
- /// This is like doing i8 as i16, i16 as i64, i6 as i8, etc
66
- pub ( in crate :: integer) fn sign_extend_partial_number < T > ( unpadded_value : T , num_bits_set : u32 ) -> T
67
- where
68
- T : RecomposableSignedInteger ,
69
- {
70
- if num_bits_set >= T :: BITS as u32 {
71
- return unpadded_value;
72
- }
73
- let sign_bit_pos = num_bits_set - 1 ;
74
- let sign_bit = ( unpadded_value >> sign_bit_pos) & T :: ONE ;
75
-
76
- // Creates a padding mask
77
- // where bits above num_bits_set
78
- // are 1s if sign bit is `1` else `0`
79
- let padding = ( T :: MAX * sign_bit) << num_bits_set;
80
- padding | unpadded_value
81
- }
82
-
83
36
/// A structure containing the client key, which must be kept secret.
84
37
///
85
38
/// This key can be used to encrypt both in Radix and CRT
@@ -381,18 +334,8 @@ impl ClientKey {
381
334
}
382
335
383
336
let bits_in_block = self . key . parameters . message_modulus ( ) . 0 . ilog2 ( ) ;
384
- let mut recomposer = BlockRecomposer :: < T > :: new ( bits_in_block) ;
385
-
386
- for encrypted_block in blocks {
387
- let decrypted_block = decrypt_block ( & self . key , encrypted_block) ;
388
- if !recomposer. add_unmasked ( decrypted_block) {
389
- // End of T::BITS reached no need to try more
390
- // recomposition
391
- break ;
392
- }
393
- }
394
-
395
- recomposer. value ( )
337
+ let decrypted_block_iter = blocks. iter ( ) . map ( |block| decrypt_block ( & self . key , block) ) ;
338
+ BlockRecomposer :: recompose_unsigned ( decrypted_block_iter, bits_in_block)
396
339
}
397
340
398
341
pub fn encrypt_signed_radix < T > ( & self , message : T , num_blocks : usize ) -> SignedRadixCiphertext
@@ -470,15 +413,16 @@ impl ClientKey {
470
413
let message_modulus = self . parameters ( ) . message_modulus ( ) . 0 ;
471
414
assert ! ( message_modulus. is_power_of_two( ) ) ;
472
415
473
- // Decrypting a signed value is the same as decrypting an unsigned value
474
- // but, in the signed case,
475
- // we have to take care of the case when the clear type T has more bits
476
- // than what the ciphertext encrypts.
477
- let unpadded_value = self . decrypt_radix_impl ( & ctxt. blocks , decrypt_block) ;
416
+ if ctxt. blocks . is_empty ( ) {
417
+ return T :: ZERO ;
418
+ }
478
419
479
- let num_bits_in_message = message_modulus. ilog2 ( ) ;
480
- let num_bits_in_ctxt = num_bits_in_message * ctxt. blocks . len ( ) as u32 ;
481
- sign_extend_partial_number ( unpadded_value, num_bits_in_ctxt)
420
+ let bits_in_block = self . key . parameters . message_modulus ( ) . 0 . ilog2 ( ) ;
421
+ let decrypted_block_iter = ctxt
422
+ . blocks
423
+ . iter ( )
424
+ . map ( |block| decrypt_block ( & self . key , block) ) ;
425
+ BlockRecomposer :: recompose_signed ( decrypted_block_iter, bits_in_block)
482
426
}
483
427
484
428
/// Encrypts one block.
0 commit comments