1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT license.
3 
4 #pragma once
5 
6 #include "seal/ciphertext.h"
7 #include "seal/context.h"
8 #include "seal/encryptionparams.h"
9 #include "seal/memorymanager.h"
10 #include "seal/modulus.h"
11 #include "seal/plaintext.h"
12 #include "seal/randomgen.h"
13 #include "seal/secretkey.h"
14 #include "seal/util/defines.h"
15 #include "seal/util/iterator.h"
16 #include "seal/util/locks.h"
17 #include "seal/util/ntt.h"
18 #include "seal/util/rns.h"
19 
20 namespace seal
21 {
22     /**
23     Decrypts Ciphertext objects into Plaintext objects. Constructing a Decryptor
24     requires a SEALContext with valid encryption parameters, and the secret key.
25     The Decryptor is also used to compute the invariant noise budget in a given
26     ciphertext.
27 
28     @par Overloads
29     For the decrypt function we provide two overloads concerning the memory pool
30     used in allocations needed during the operation. In one overload the global
31     memory pool is used for this purpose, and in another overload the user can
32     supply a MemoryPoolHandle to be used instead. This is to allow one single
33     Decryptor to be used concurrently by several threads without running into
34     thread contention in allocations taking place during operations. For example,
35     one can share one single Decryptor across any number of threads, but in each
36     thread call the decrypt function by giving it a thread-local MemoryPoolHandle
37     to use. It is important for a developer to understand how this works to avoid
38     unnecessary performance bottlenecks.
39 
40 
41     @par NTT form
42     When using the BFV scheme (scheme_type::bfv), all plaintext and ciphertexts
43     should remain by default in the usual coefficient representation, i.e. not in
44     NTT form. When using the CKKS scheme (scheme_type::ckks), all plaintexts and
45     ciphertexts should remain by default in NTT form. We call these scheme-specific
46     NTT states the "default NTT form". Decryption requires the input ciphertexts
47     to be in the default NTT form, and will throw an exception if this is not the
48     case.
49     */
50     class Decryptor
51     {
52     public:
53         /**
54         Creates a Decryptor instance initialized with the specified SEALContext
55         and secret key.
56 
57         @param[in] context The SEALContext
58         @param[in] secret_key The secret key
59         @throws std::invalid_argument if the encryption parameters are not valid
60         @throws std::invalid_argument if secret_key is not valid
61         */
62         Decryptor(const SEALContext &context, const SecretKey &secret_key);
63 
64         /*
65         Decrypts a Ciphertext and stores the result in the destination parameter.
66 
67         @param[in] encrypted The ciphertext to decrypt
68         @param[out] destination The plaintext to overwrite with the decrypted
69         ciphertext
70         @throws std::invalid_argument if encrypted is not valid for the encryption
71         parameters
72         @throws std::invalid_argument if encrypted is not in the default NTT form
73         */
74         void decrypt(const Ciphertext &encrypted, Plaintext &destination);
75 
76         /*
77         Computes the invariant noise budget (in bits) of a ciphertext. The
78         invariant noise budget measures the amount of room there is for the noise
79         to grow while ensuring correct decryptions. This function works only with
80         the BFV scheme.
81 
82         @par Invariant Noise Budget
83         The invariant noise polynomial of a ciphertext is a rational coefficient
84         polynomial, such that a ciphertext decrypts correctly as long as the
85         coefficients of the invariantnoise polynomial are of absolute value less
86         than 1/2. Thus, we call the infinity-norm of the invariant noise polynomial
87         the invariant noise, and for correct decryption requireit to be less than
88         1/2. If v denotes the invariant noise, we define the invariant noise budget
89         as -log2(2v). Thus, the invariant noise budget starts from some initial
90         value, which depends on the encryption parameters, and decreases when
91         computations are performed. When the budget reaches zero, the ciphertext
92         becomes too noisy to decrypt correctly.
93 
94         @param[in] encrypted The ciphertext
95         @throws std::invalid_argument if the scheme is not BFV
96         @throws std::invalid_argument if encrypted is not valid for the encryption
97         parameters
98         @throws std::invalid_argument if encrypted is in NTT form
99         */
100         SEAL_NODISCARD int invariant_noise_budget(const Ciphertext &encrypted);
101 
102     private:
103         void bfv_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool);
104 
105         void ckks_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool);
106 
107         Decryptor(const Decryptor &copy) = delete;
108 
109         Decryptor(Decryptor &&source) = delete;
110 
111         Decryptor &operator=(const Decryptor &assign) = delete;
112 
113         Decryptor &operator=(Decryptor &&assign) = delete;
114 
115         void compute_secret_key_array(std::size_t max_power);
116 
117         // Compute c_0 + c_1 *s + ... + c_{count-1} * s^{count-1} mod q.
118         // Store result in destination in RNS form.
119         // destination has the size of an RNS polynomial.
120         void dot_product_ct_sk_array(const Ciphertext &encrypted, util::RNSIter destination, MemoryPoolHandle pool);
121 
122         // We use a fresh memory pool with `clear_on_destruction' enabled.
123         MemoryPoolHandle pool_ = MemoryManager::GetPool(mm_prof_opt::mm_force_new, true);
124 
125         SEALContext context_;
126 
127         std::size_t secret_key_array_size_ = 0;
128 
129         util::Pointer<std::uint64_t> secret_key_array_;
130 
131         mutable util::ReaderWriterLocker secret_key_array_locker_;
132     };
133 } // namespace seal
134