1 // @file bfv.h -- Operations for the BFV cryptoscheme.
2 // @author TPOC: contact@palisade-crypto.org
3 //
4 // @copyright Copyright (c) 2019, New Jersey Institute of Technology (NJIT)
5 // All rights reserved.
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution. THIS SOFTWARE IS
13 // PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
14 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16 // EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 
24 /*
25  *
26  * This code implements the Brakerski-Fan-Vercauteren (BFV) homomorphic
27  * encryption scheme.  This scheme is also referred to as the FV scheme. The BFV
28  * scheme is introduced here:
29  *   - Junfeng Fan and Frederik Vercauteren. Somewhat Practical Fully
30  * Homomorphic Encryption.  Cryptology ePrint Archive, Report 2012/144.
31  * (https://eprint.iacr.org/2012/144.pdf)
32  *
33  * Our implementation builds from the designs here:
34  *   - Lepoint T., Naehrig M. (2014) A Comparison of the Homomorphic Encryption
35  * Schemes FV and YASHE. In: Pointcheval D., Vergnaud D. (eds) Progress in
36  * Cryptology – AFRICACRYPT 2014. AFRICACRYPT 2014. Lecture Notes in Computer
37  * Science, vol 8469. Springer, Cham. (https://eprint.iacr.org/2014/062.pdf)
38  *
39  */
40 
41 #ifndef LBCRYPTO_CRYPTO_BFV_H
42 #define LBCRYPTO_CRYPTO_BFV_H
43 
44 #include <map>
45 #include <memory>
46 #include <string>
47 #include <vector>
48 
49 #include "palisade.h"
50 #include "utils/caller_info.h"
51 
52 namespace lbcrypto {
53 
54 /**
55  * @brief This is the parameters class for the BFV encryption scheme.  This
56  * scheme is also referred to as the FV scheme.
57  *
58  * The BFV scheme parameter guidelines are introduced here:
59  *   - Junfeng Fan and Frederik Vercauteren. Somewhat Practical Fully
60  * Homomorphic Encryption.  Cryptology ePrint Archive, Report 2012/144.
61  * (https://eprint.iacr.org/2012/144.pdf)
62  *
63  * We used the optimized parameter selection from the designs here:
64  *   - Lepoint T., Naehrig M. (2014) A Comparison of the Homomorphic Encryption
65  * Schemes FV and YASHE. In: Pointcheval D., Vergnaud D. (eds) Progress in
66  * Cryptology – AFRICACRYPT 2014. AFRICACRYPT 2014. Lecture Notes in Computer
67  * Science, vol 8469. Springer, Cham. (https://eprint.iacr.org/2014/062.pdf)
68  *
69  * @tparam Element a ring element type.
70  */
71 template <class Element>
72 class LPCryptoParametersBFV : public LPCryptoParametersRLWE<Element> {
73   using IntType = typename Element::Integer;
74   using ParmType = typename Element::Params;
75 
76  public:
77   /**
78    * Default constructor.
79    */
80   LPCryptoParametersBFV();
81 
82   /**
83    * Copy constructor.
84    * @param rhs - source
85    */
86   LPCryptoParametersBFV(const LPCryptoParametersBFV &rhs);
87 
88   /**
89    * Constructor that initializes values.  Note that it is possible to set
90    * parameters in a way that is overall infeasible for actual use.  There are
91    * fewer degrees of freedom than parameters provided.  Typically one chooses
92    * the basic noise, assurance and security parameters as the typical
93    * community-accepted values, then chooses the plaintext modulus and depth as
94    * needed.  The element parameters should then be choosen to provide
95    * correctness and security.  In some cases we would need to operate over
96    * already encrypted/provided ciphertext and the depth needs to be
97    * pre-computed for initial settings.
98    *
99    * @param &params Element parameters.  This will depend on the specific class
100    * of element being used.
101    * @param &plaintextModulus Plaintext modulus, typically denoted as p in most
102    * publications.
103    * @param distributionParameter Noise distribution parameter, typically
104    * denoted as /sigma in most publications.  Community standards typically call
105    * for a value of 3 to 6. Lower values provide more room for computation while
106    * larger values provide more security.
107    * @param assuranceMeasure Assurance level, typically denoted as w in most
108    * applications.  This is oftern perceived as a fudge factor in the
109    * literature, with a typical value of 9.
110    * @param securityLevel Security level as Root Hermite Factor.  We use the
111    * Root Hermite Factor representation of the security level to better conform
112    * with US ITAR and EAR export regulations.  This is typically represented as
113    * /delta in the literature.  Typically a Root Hermite Factor of 1.006 or less
114    * provides reasonable security for RLWE crypto schemes.
115    * @param relinWindow The size of the relinearization window.  This is
116    * relevant when using this scheme for proxy re-encryption, and the value is
117    * denoted as r in the literature.
118    * @param delta BFV-specific factor that is multiplied by the plaintext
119    * polynomial.
120    * @param mode mode for secret polynomial, defaults to RLWE.
121    * @param bigModulus modulus used in polynomial multiplications in EvalMult
122    * @param bigRootOfUnity root of unity for bigModulus
123    * @param bigModulusArb modulus used in polynomial multiplications in EvalMult
124    * (for arbitrary cyclotomics)
125    * @param bigRootOfUnityArb root of unity for bigModulus (for arbitrary
126    * cyclotomics)
127    * @param depth is the depth of computation circuit supported for these
128    * parameters (not used now; for future use).
129    * @param maxDepth the maximum power of secret key for which the
130    * relinearization key is generated
131    */
132   LPCryptoParametersBFV(shared_ptr<ParmType> params,
133                         const PlaintextModulus &plaintextModulus,
134                         float distributionParameter, float assuranceMeasure,
135                         float securityLevel, usint relinWindow,
136                         const IntType &delta = IntType(0), MODE mode = RLWE,
137                         const IntType &bigModulus = IntType(0),
138                         const IntType &bigRootOfUnity = IntType(0),
139                         const IntType &bigModulusArb = IntType(0),
140                         const IntType &bigRootOfUnityArb = IntType(0),
141                         int depth = 1, int maxDepth = 2);
142 
143   /**
144    * Constructor that initializes values.
145    *
146    * @param &params element parameters.
147    * @param &encodingParams plaintext space parameters.
148    * @param distributionParameter noise distribution parameter.
149    * @param assuranceMeasure assurance level. = BigInteger::ZERO
150    * @param securityLevel security level (root Hermite factor).
151    * @param relinWindow the size of the relinearization window.
152    * @param delta BFV-specific factor that is multiplied by the plaintext
153    * polynomial.
154    * @param mode mode for secret polynomial, defaults to RLWE.
155    * @param bigModulus modulus used in polynomial multiplications in EvalMult
156    * @param bigRootOfUnity root of unity for bigModulus
157    * @param bigModulusArb modulus used in polynomial multiplications in EvalMult
158    * (arbitrary cyclotomics)
159    * @param bigRootOfUnityArb root of unity for bigModulus (arbitrary
160    * cyclotomics)
161    * @param depth is the depth of computation circuit supported for these
162    * parameters (not used now; for future use).
163    * @param maxDepth the maximum power of secret key for which the
164    * relinearization key is generated
165    */
166   LPCryptoParametersBFV(shared_ptr<ParmType> params,
167                         EncodingParams encodingParams,
168                         float distributionParameter, float assuranceMeasure,
169                         float securityLevel, usint relinWindow,
170                         const IntType &delta = IntType(0), MODE mode = RLWE,
171                         const IntType &bigModulus = IntType(0),
172                         const IntType &bigRootOfUnity = IntType(0),
173                         const IntType &bigModulusArb = IntType(0),
174                         const IntType &bigRootOfUnityArb = IntType(0),
175                         int depth = 1, int maxDepth = 2);
176 
177   /**
178    * Constructor that initializes values.
179    *
180    * @param &params element parameters.
181    * @param &encodingParams plaintext space parameters.
182    * @param distributionParameter noise distribution parameter.
183    * @param assuranceMeasure assurance level. = BigInteger::ZERO
184    * @param securityLevel standard security level.
185    * @param relinWindow the size of the relinearization window.
186    * @param delta BFV-specific factor that is multiplied by the plaintext
187    * polynomial.
188    * @param mode mode for secret polynomial, defaults to RLWE.
189    * @param bigModulus modulus used in polynomial multiplications in EvalMult
190    * @param bigRootOfUnity root of unity for bigModulus
191    * @param bigModulusArb modulus used in polynomial multiplications in EvalMult
192    * (arbitrary cyclotomics)
193    * @param bigRootOfUnityArb root of unity for bigModulus (arbitrary
194    * cyclotomics)
195    * @param depth is the depth of computation circuit supported for these
196    * parameters (not used now; for future use).
197    * @param maxDepth the maximum power of secret key for which the
198    * relinearization key is generated
199    */
200   LPCryptoParametersBFV(shared_ptr<ParmType> params,
201                         EncodingParams encodingParams,
202                         float distributionParameter, float assuranceMeasure,
203                         SecurityLevel securityLevel, usint relinWindow,
204                         const IntType &delta = IntType(0), MODE mode = RLWE,
205                         const IntType &bigModulus = IntType(0),
206                         const IntType &bigRootOfUnity = IntType(0),
207                         const IntType &bigModulusArb = IntType(0),
208                         const IntType &bigRootOfUnityArb = IntType(0),
209                         int depth = 1, int maxDepth = 2);
210 
211   /**
212    * Destructor
213    */
214   virtual ~LPCryptoParametersBFV() {}
215 
216   /**
217    * Gets the value of the delta factor.
218    *
219    * @return the delta factor. It is an BFV-specific factor that is multiplied
220    * by the plaintext polynomial.
221    */
222   const IntType &GetDelta() const { return m_delta; }
223 
224   /**
225    * Gets the modulus used for polynomial multiplications in EvalMult
226    *
227    * @return the modulus value.
228    */
229   const IntType &GetBigModulus() const { return m_bigModulus; }
230 
231   /**
232    * Gets the primitive root of unity used for polynomial multiplications in
233    * EvalMult
234    *
235    * @return the primitive root of unity value.
236    */
237   const IntType &GetBigRootOfUnity() const { return m_bigRootOfUnity; }
238 
239   /**
240    * Gets the modulus used for polynomial multiplications in EvalMult (arbitrary
241    * cyclotomics)
242    *
243    * @return the modulus value.
244    */
245   const IntType &GetBigModulusArb() const { return m_bigModulusArb; }
246 
247   /**
248    * Gets the primitive root of unity used for polynomial multiplications in
249    * EvalMult (arbitrary cyclotomics)
250    *
251    * @return the primitive root of unity value.
252    */
253   const IntType &GetBigRootOfUnityArb() const { return m_bigRootOfUnityArb; }
254 
255   /**
256    * Sets the value of the delta factor
257    * @param &delta is the delta factor
258    */
259   void SetDelta(const IntType &delta) { m_delta = delta; }
260 
261   /**
262    * Sets the modulus used for polynomial multiplications in EvalMult
263    *
264    * @param &bigModulus the modulus value.
265    */
266   void SetBigModulus(const IntType &bigModulus) { m_bigModulus = bigModulus; }
267 
268   /**
269    * Sets primitive root of unity used for polynomial multiplications in
270    * EvalMult
271    * @param &bigRootOfUnity is the root of unity used for EvalMult operations.
272    */
273   void SetBigRootOfUnity(const IntType &bigRootOfUnity) {
274     m_bigRootOfUnity = bigRootOfUnity;
275   }
276 
277   /**
278    * Sets the modulus used for polynomial multiplications in EvalMult (arbitrary
279    * cyclotomics)
280    */
281   void SetBigModulusArb(const IntType &bigModulusArb) {
282     m_bigModulusArb = bigModulusArb;
283   }
284 
285   /**
286    * Sets primitive root of unity used for polynomial multiplications in
287    * EvalMult (arbitrary cyclotomics)
288    */
289   void SetBigRootOfUnityArb(const IntType &bigRootOfUnityArb) {
290     m_bigRootOfUnityArb = bigRootOfUnityArb;
291   }
292 
293   /**
294    * == operator to compare to this instance of LPCryptoParametersBFV object.
295    *
296    * @param &rhs LPCryptoParameters to check equality against.
297    */
298   bool operator==(const LPCryptoParameters<Element> &rhs) const {
299     const auto *el = dynamic_cast<const LPCryptoParametersBFV<Element> *>(&rhs);
300 
301     if (el == nullptr) return false;
302 
303     if (m_delta != el->m_delta) return false;
304     if (m_bigModulus != el->m_bigModulus) return false;
305     if (m_bigRootOfUnity != el->m_bigRootOfUnity) return false;
306     if (m_bigModulusArb != el->m_bigModulusArb) return false;
307     if (m_bigRootOfUnityArb != el->m_bigRootOfUnityArb) return false;
308 
309     return LPCryptoParametersRLWE<Element>::operator==(rhs);
310   }
311 
312   void PrintParameters(std::ostream &os) const {
313     LPCryptoParametersRLWE<Element>::PrintParameters(os);
314 
315     os << " delta: " << m_delta << " bigmodulus: " << m_bigModulus
316        << " bigrootofunity: " << m_bigRootOfUnity
317        << " bigmodulusarb: " << m_bigModulusArb
318        << " bigrootofunityarb: " << m_bigRootOfUnityArb;
319   }
320 
321   template <class Archive>
322   void save(Archive &ar, std::uint32_t const version) const {
323     ar(::cereal::base_class<LPCryptoParametersRLWE<Element>>(this));
324     ar(::cereal::make_nvp("d", m_delta));
325     ar(::cereal::make_nvp("bm", m_bigModulus));
326     ar(::cereal::make_nvp("br", m_bigRootOfUnity));
327     ar(::cereal::make_nvp("bma", m_bigModulusArb));
328     ar(::cereal::make_nvp("bra", m_bigRootOfUnityArb));
329   }
330 
331   template <class Archive>
332   void load(Archive &ar, std::uint32_t const version) {
333     if (version > SerializedVersion()) {
334       PALISADE_THROW(deserialize_error,
335                      "serialized object version " + std::to_string(version) +
336                          " is from a later version of the library");
337     }
338     ar(::cereal::base_class<LPCryptoParametersRLWE<Element>>(this));
339     ar(::cereal::make_nvp("d", m_delta));
340     ar(::cereal::make_nvp("bm", m_bigModulus));
341     ar(::cereal::make_nvp("br", m_bigRootOfUnity));
342     ar(::cereal::make_nvp("bma", m_bigModulusArb));
343     ar(::cereal::make_nvp("bra", m_bigRootOfUnityArb));
344   }
345 
346   std::string SerializedObjectName() const { return "BFVSchemeParameters"; }
347   static uint32_t SerializedVersion() { return 1; }
348 
349  private:
350   // factor delta = floor(q/p) that is multipled by the plaintext polynomial
351   // in BFV (most significant bit ranges are used to represent the message)
352   IntType m_delta;
353 
354   // larger modulus that is used in polynomial multiplications within EvalMult
355   // (before rounding is done)
356   IntType m_bigModulus;
357 
358   // primitive root of unity for m_bigModulus
359   IntType m_bigRootOfUnity;
360 
361   // Large modulus used for CRT with m_bigModulus
362   IntType m_bigModulusArb;
363 
364   // Primitive root of unity for m_bigModulusArb
365   IntType m_bigRootOfUnityArb;
366 };
367 
368 /**
369  * @brief Parameter generation for BFV.  This scheme is also referred to as the
370  * FV scheme.
371  *
372  * The BFV scheme parameter guidelines are introduced here:
373  *   - Junfeng Fan and Frederik Vercauteren. Somewhat Practical Fully
374  * Homomorphic Encryption.  Cryptology ePrint Archive, Report 2012/144.
375  * (https://eprint.iacr.org/2012/144.pdf)
376  *
377  * We used the optimized parameter selection from the designs here:
378  *   - Lepoint T., Naehrig M. (2014) A Comparison of the Homomorphic Encryption
379  * Schemes FV and YASHE. In: Pointcheval D., Vergnaud D. (eds) Progress in
380  * Cryptology – AFRICACRYPT 2014. AFRICACRYPT 2014. Lecture Notes in Computer
381  * Science, vol 8469. Springer, Cham. (https://eprint.iacr.org/2014/062.pdf)
382  *
383  * @tparam Element a ring element.
384  */
385 template <class Element>
386 class LPAlgorithmParamsGenBFV : public LPParameterGenerationAlgorithm<Element> {
387   using IntType = typename Element::Integer;
388   using ParmType = typename Element::Params;
389 
390  public:
391   /**
392    * Default constructor
393    */
394   LPAlgorithmParamsGenBFV() {}
395 
396   /**
397    * Method for computing all derived parameters based on chosen primitive
398    * parameters
399    *
400    * @param cryptoParams the crypto parameters object to be populated with
401    * parameters.
402    * @param evalAddCount number of EvalAdds assuming no EvalMult and KeySwitch
403    * operations are performed.
404    * @param evalMultCount number of EvalMults assuming no EvalAdd and KeySwitch
405    * operations are performed.
406    * @param keySwitchCount number of KeySwitch operations assuming no EvalAdd
407    * and EvalMult operations are performed.
408    * @param dcrtBits number of bits in each CRT modulus - NOT USED IN BFV
409    * @param n ring dimension in case the user wants to use a custom ring
410    * dimension
411    */
412   virtual bool ParamsGen(shared_ptr<LPCryptoParameters<Element>> cryptoParams,
413                          int32_t evalAddCount = 0, int32_t evalMultCount = 0,
414                          int32_t keySwitchCount = 0, size_t dcrtBits = 0,
415                          uint32_t n = 0) const;
416 
417   virtual ~LPAlgorithmParamsGenBFV() {}
418 };
419 
420 /**
421  * @brief Encryption algorithm implementation for BFV for the basic public key
422  * encrypt, decrypt and key generation methods for the BFV encryption scheme.
423  * This scheme is also referred to as the FV scheme.
424  *
425  * The BFV scheme parameter guidelines are introduced here:
426  *   - Junfeng Fan and Frederik Vercauteren. Somewhat Practical Fully
427  * Homomorphic Encryption.  Cryptology ePrint Archive, Report 2012/144.
428  * (https://eprint.iacr.org/2012/144.pdf)
429  *
430  * We used the optimized parameter selection from the designs here:
431  *   - Lepoint T., Naehrig M. (2014) A Comparison of the Homomorphic Encryption
432  * Schemes FV and YASHE. In: Pointcheval D., Vergnaud D. (eds) Progress in
433  * Cryptology – AFRICACRYPT 2014. AFRICACRYPT 2014. Lecture Notes in Computer
434  * Science, vol 8469. Springer, Cham. (https://eprint.iacr.org/2014/062.pdf)
435  *
436  * @tparam Element a ring element.
437  */
438 template <class Element>
439 class LPAlgorithmBFV : public LPEncryptionAlgorithm<Element> {
440   using IntType = typename Element::Integer;
441   using ParmType = typename Element::Params;
442   using DggType = typename Element::DggType;
443   using DugType = typename Element::DugType;
444   using TugType = typename Element::TugType;
445 
446  public:
447   /**
448    * Default constructor
449    */
450   LPAlgorithmBFV() {}
451 
452   virtual ~LPAlgorithmBFV() {}
453 
454   /**
455    * Method for encrypting plaintext using BFV.
456    *
457    * @param publicKey public key used for encryption.
458    * @param plaintext the plaintext input.
459    * @return ciphertext which results from encryption.
460    */
461   virtual Ciphertext<Element> Encrypt(const LPPublicKey<Element> publicKey,
462                                       Element plaintext) const;
463 
464   /**
465    * Method for encrypting plaintext with private key using BFV.
466    *
467    * @param privateKey private key used for encryption.
468    * @param plaintext the plaintext input.
469    * @return ciphertext which results from encryption.
470    */
471   virtual Ciphertext<Element> Encrypt(const LPPrivateKey<Element> privateKey,
472                                       Element plaintext) const;
473 
474   /**
475    * Method for decrypting using BFV. See the class description for citations on
476    * where the algorithms were taken from.
477    *
478    * @param privateKey private key used for decryption.
479    * @param ciphertext ciphertext to be decrypted.
480    * @param *plaintext the plaintext output.
481    * @return the decrypted plaintext returned.
482    */
483   virtual DecryptResult Decrypt(const LPPrivateKey<Element> privateKey,
484                                 ConstCiphertext<Element> ciphertext,
485                                 NativePoly *plaintext) const;
486 
487   /**
488    * Function to generate public and private keys. See the class description for
489    * citations on where the algorithms were taken from.
490    *
491    * @param cc cryptocontext for the keys to be generated.
492    * @param makeSparse set to true if ring reduce by a factor of 2 is to be
493    * used.  Generally this should always be false.
494    * @return key pair including the private and public key
495    */
496   LPKeyPair<Element> KeyGen(CryptoContext<Element> cc, bool makeSparse = false);
497 };
498 
499 /**
500  * @brief SHE algorithms implementation for BFV.  This scheme is also referred
501  * to as the FV scheme.
502  *
503  * The BFV scheme parameter guidelines are introduced here:
504  *   - Junfeng Fan and Frederik Vercauteren. Somewhat Practical Fully
505  * Homomorphic Encryption.  Cryptology ePrint Archive, Report 2012/144.
506  * (https://eprint.iacr.org/2012/144.pdf)
507  *
508  * We used the optimized parameter selection from the designs here:
509  *   - Lepoint T., Naehrig M. (2014) A Comparison of the Homomorphic Encryption
510  * Schemes FV and YASHE. In: Pointcheval D., Vergnaud D. (eds) Progress in
511  * Cryptology – AFRICACRYPT 2014. AFRICACRYPT 2014. Lecture Notes in Computer
512  * Science, vol 8469. Springer, Cham. (https://eprint.iacr.org/2014/062.pdf)
513  *
514  * @tparam Element a ring element.
515  */
516 template <class Element>
517 class LPAlgorithmSHEBFV : public LPSHEAlgorithm<Element> {
518   using IntType = typename Element::Integer;
519   using ParmType = typename Element::Params;
520   using DggType = typename Element::DggType;
521   using DugType = typename Element::DugType;
522   using TugType = typename Element::TugType;
523 
524  public:
525   /**
526    * Default constructor
527    */
528   LPAlgorithmSHEBFV() {}
529 
530   virtual ~LPAlgorithmSHEBFV() {}
531 
532   /**
533    * Function for in-place homomorphic addition of ciphertexts.
534    *
535    * @param ct1 first input/output ciphertext.
536    * @param ct2 second input ciphertext.
537    * @details \p ct1 stores the result of \p ct1 + \p ct2
538    */
539   void EvalAddInPlace(Ciphertext<Element>& ct1,
540                       ConstCiphertext<Element> ct2) const override;
541 
542   /**
543    * Function for homomorphic addition of ciphertext and plaintext.
544    *
545    * @param ct1 input ciphertext.
546    * @param pt  input ciphertext.
547    * @return new ciphertext.
548    */
549   Ciphertext<Element> EvalAdd(ConstCiphertext<Element> ct,
550                               ConstPlaintext pt) const override;
551 
552   /**
553    * Function for homomorphic subtraction of ciphertexts.
554    *
555    * @param ct1 first input ciphertext.
556    * @param ct2 second input ciphertext.
557    * @return new ciphertext.
558    */
559   Ciphertext<Element> EvalSub(ConstCiphertext<Element> ct1,
560                               ConstCiphertext<Element> ct2) const override;
561 
562   /**
563    * Function for homomorphic subtraction of ciphertext ans plaintext.
564    *
565    * @param ct input ciphertext.
566    * @param pt input ciphertext.
567    * @return new ciphertext.
568    */
569   Ciphertext<Element> EvalSub(ConstCiphertext<Element> ct1,
570                               ConstPlaintext pt) const override;
571 
572   /**
573    * Function for homomorphic evaluation of ciphertexts.
574    * The multiplication is supported for a fixed level without keyswitching
575    * requirement (default level=2). If the total depth of the ciphertexts
576    * exceeds the supported level, it throws an error.
577    *
578    * @param ciphertext1 first input ciphertext.
579    * @param ciphertext2 second input ciphertext.
580    * @return resulting EvalMult ciphertext.
581    */
582   Ciphertext<Element> EvalMult(ConstCiphertext<Element> ct1,
583                                ConstCiphertext<Element> ct2) const override;
584 
585   /**
586    * Function for multiplying ciphertext by plaintext.
587    *
588    * @param ciphertext input ciphertext.
589    * @param plaintext input plaintext embedded in the cryptocontext.
590    * @return result of the multiplication.
591    */
592   Ciphertext<Element> EvalMult(ConstCiphertext<Element> ciphertext,
593                                ConstPlaintext plaintext) const override;
594 
595   /**
596    * Function for evaluating multiplication on ciphertext followed by key
597    * switching operation. Currently it assumes that the input arguments are
598    * fresh ciphertexts (of depth 1). Support for the input ciphertexts of higher
599    * depths will be added later.
600    *
601    * @param ct1 first input ciphertext.
602    * @param ct2 second input ciphertext.
603    * @param ek is the evaluation key to make the newCiphertext
604    *  decryptable by the same secret key as that of ciphertext1 and ciphertext2.
605    * @return new ciphertext
606    */
607   Ciphertext<Element> EvalMult(ConstCiphertext<Element> ct1,
608                                ConstCiphertext<Element> ct,
609                                const LPEvalKey<Element> ek) const override;
610 
611   /**
612    * Function for evaluating multiplication on ciphertext followed by
613    * relinearization operation. It computes the multiplication in a binary tree
614    * manner. Also, it reduces the number of elements in the ciphertext to two
615    * after each multiplication. Currently it assumes that the consecutive two
616    * input arguments have total depth smaller than the supported depth.
617    * Otherwise, it throws an error.
618    *
619    * @param cipherTextList  is the ciphertext list.
620    * @param evalKeys is the evaluation key to make the newCiphertext
621    *  decryptable by the same secret key as that of ciphertext list.
622    * @return new ciphertext.
623    */
624   Ciphertext<Element> EvalMultMany(
625       const vector<Ciphertext<Element>> &cipherTextList,
626       const vector<LPEvalKey<Element>> &evalKeys) const override;
627 
628   /**
629    * Function for evaluating multiplication on ciphertext followed by
630    * relinearization operation. Currently it assumes that the input arguments
631    * have total depth smaller than the supported depth. Otherwise, it throws an
632    * error.
633    *
634    * @param ct1 first input ciphertext.
635    * @param ct2 second input ciphertext.
636    * @param ek is the evaluation key to make the newCiphertext
637    *  decryptable by the same secret key as that of ciphertext1 and ciphertext2.
638    * @return new ciphertext
639    */
640   Ciphertext<Element> EvalMultAndRelinearize(
641       ConstCiphertext<Element> ct1, ConstCiphertext<Element> ct,
642       const vector<LPEvalKey<Element>> &ek) const override;
643 
644   /**
645    * Function for homomorphic negation of ciphertexts.
646    *
647    * @param ct first input ciphertext.
648    * @return new ciphertext.
649    */
650   Ciphertext<Element> EvalNegate(ConstCiphertext<Element> ct) const override;
651 
652   /**
653    * Method for generating a KeySwitchHint using RLWE relinearization
654    *
655    * @param originalPrivateKey Original private key used for encryption.
656    * @param newPrivateKey New private key to generate the keyswitch hint.
657    * @return resulting keySwitchHint.
658    */
659   LPEvalKey<Element> KeySwitchGen(
660       const LPPrivateKey<Element> originalPrivateKey,
661       const LPPrivateKey<Element> newPrivateKey) const override;
662 
663   /**
664    * Method for in-place key switching based on a KeySwitchHint using RLWE
665    * relinearization
666    *
667    * @param keySwitchHint Hint required to perform the ciphertext switching.
668    * @param &cipherText Original ciphertext to perform in-place key switching
669    * on.
670    */
671   void KeySwitchInPlace(const LPEvalKey<Element> keySwitchHint,
672                         Ciphertext<Element> &cipherText) const override;
673 
674   /**
675    * Function to generate 1..log(q) encryptions for each bit of the square of
676    * the original private key
677    *
678    * @param k1 private key.
679    * @return evaluation key.
680    */
681   LPEvalKey<Element> EvalMultKeyGen(
682       const LPPrivateKey<Element> k1) const override;
683 
684   /**
685    * Function to generate 1..log(q) encryptions for each bit of the powers of
686    * the original private key. The number of the powers is determined by the
687    * depth. If we choose depth 4, it means we can decrypt ciphertexts with 5
688    * elements. For c[i] being the ciphertext elements, we compute
689    * \sum_{i=0}^{i<5} c[i]*s^i.
690    *
691    * @param k1 private key.
692    * @return evaluation key.
693    */
694   vector<LPEvalKey<Element>> EvalMultKeysGen(
695       const LPPrivateKey<Element> k1) const override;
696 
697   /**
698    * Function for evaluating automorphism of ciphertext at index i.
699    *
700    * @param ciphertext the input ciphertext.
701    * @param i automorphism index
702    * @param &evalKeys - reference to the map of evaluation keys generated by
703    * EvalAutomorphismKeyGen.
704    * @return resulting ciphertext
705    */
706   Ciphertext<Element> EvalAutomorphism(
707       ConstCiphertext<Element> ciphertext, usint i,
708       const std::map<usint, LPEvalKey<Element>> &evalKeys,
709       CALLER_INFO_ARGS_HDR) const override;
710 
711   /**
712    * Generate automophism keys for a given private key; Uses the private key for
713    * encryption
714    *
715    * @param privateKey private key.
716    * @param indexList list of automorphism indices to be computed
717    * @return returns the evaluation keys
718    */
719   shared_ptr<std::map<usint, LPEvalKey<Element>>> EvalAutomorphismKeyGen(
720       const LPPrivateKey<Element> privateKey,
721       const std::vector<usint> &indexList) const override;
722 
723   /**
724    * Generate automophism keys for a given private key; Uses the public key for
725    * encryption
726    *
727    * @param publicKey public key.
728    * @param privateKey private key.
729    * @param indexList list of automorphism indices to be computed
730    * @return returns the evaluation keys
731    */
732   shared_ptr<std::map<usint, LPEvalKey<Element>>> EvalAutomorphismKeyGen(
733       const LPPublicKey<Element> publicKey,
734       const LPPrivateKey<Element> privateKey,
735       const std::vector<usint> &indexList) const override {
736     std::string errMsg =
737         "LPAlgorithmSHEBFV::EvalAutomorphismKeyGen is not implemented for BFV "
738         "SHE Scheme.";
739     PALISADE_THROW(not_implemented_error, errMsg);
740   }
741 };
742 
743 /**
744  * @brief PRE scheme based on BFV. This functionality is currently DISABLED in
745  * LPPublicKeyEncryptionSchemeBFV because it needs more testing
746  * @tparam Element a ring element.
747  */
748 template <class Element>
749 class LPAlgorithmPREBFV : public LPPREAlgorithm<Element> {
750   using IntType = typename Element::Integer;
751   using ParmType = typename Element::Params;
752   using DggType = typename Element::DggType;
753   using TugType = typename Element::TugType;
754 
755  public:
756   /**
757    * Default constructor
758    */
759   LPAlgorithmPREBFV() {}
760 
761   /*
762    * DISABLED. Function to generate a re-encryption key as 1..log(q) encryptions
763    * for each bit of the original private key Variant that uses the new secret
764    * key directly.
765    *
766    * @param newKey new private key for the new ciphertext.
767    * @param origPrivateKey original private key used for decryption.
768    * @return evalKey the evaluation key for switching the ciphertext to be
769    * decryptable by new private key.
770    */
771   LPEvalKey<Element> ReKeyGen(const LPPrivateKey<Element> newKey,
772                               const LPPrivateKey<Element> origPrivateKey) const;
773 
774   /**
775    * The generation of re-encryption keys is based on the BG-PRE scheme
776    * described in Polyakov, et. al., "Fast proxy re-encryption for
777    * publish/subscribe systems".
778    *
779    * The above scheme was found to have a weakness in Cohen, "What about Bob?
780    * The inadequacy of CPA Security for proxy re-encryption". Section 5.1 shows
781    * an attack where given an original ciphertext c=(c0,c1) and a re-encrypted
782    * ciphertext c'=(c'0, c'1), the subscriber (Bob) can compute the secret key
783    * of the publisher (Alice).
784    *
785    * We fix this vulnerability by making re-encryption keys be encryptions of
786    * the s*(2^{i*r}) terms, instead of simple addition as previously defined.
787    * This makes retrieving the secret key using the above attack as hard as
788    * breaking the RLWE assumption.
789    *
790    * Our modification makes the scheme CPA-secure, but does not achieve
791    * HRA-security as it was defined in the Cohen paper above. Please look at the
792    * ReEncrypt method for an explanation of the two security definitions and how
793    * to achieve each in Palisade.
794    *
795    * @param newKey public key for the new private key.
796    * @param origPrivateKey original private key used for decryption.
797    * @return evalKey the evaluation key for switching the ciphertext to be
798    * decryptable by new private key.
799    */
800   LPEvalKey<Element> ReKeyGen(const LPPublicKey<Element> newKey,
801                               const LPPrivateKey<Element> origPrivateKey) const;
802 
803   /**
804    * This method implements re-encryption using the evaluation key generated by
805    * ReKeyGen.
806    *
807    * The PRE scheme used can achieve two different levels of security, based on
808    * the value supplied in the publicKey argument:
809    *
810    * If publicKey is nullptr, the PRE scheme is CPA-secure. If the publicKey of
811    * the recipient of the re-encrypted ciphertext is supplied, then the scheme
812    * is HRA- secure. Please refer to Cohen, "What about Bob? The inadequacy of
813    * CPA Security for proxy re-encryption", for more information on HRA
814    * security.
815    *
816    * The tradeoff of going for HRA is twofold: (1) performance is a little worst
817    * because we add one additional encryption and homomorphic addition to the
818    * result, and (2) more noise is added to the result because of the additional
819    * operations - in particular, the extra encryption draws noise from a
820    * distribution whose standard deviation is scaled by K, the number of digits
821    * in the PRE decomposition.
822    *
823    * @param evalKey the evaluation key.
824    * @param ciphertext the input ciphertext.
825    * @param publicKey the public key of the recipient of the re-encrypted
826    * ciphertext.
827    * @return resulting ciphertext after the re-encryption operation.
828    */
829   Ciphertext<Element> ReEncrypt(
830       const LPEvalKey<Element> evalKey, ConstCiphertext<Element> ciphertext,
831       const LPPublicKey<Element> publicKey = nullptr) const;
832 };
833 
834 /**
835  * @brief Concrete class for the FHE Multiparty algorithms on BFV.  A version of
836  * this multiparty scheme built on the BGV scheme is seen here:
837  *   - Asharov G., Jain A., López-Alt A., Tromer E., Vaikuntanathan V., Wichs D.
838  * (2012) Multiparty Computation with Low Communication, Computation and
839  * Interaction via Threshold FHE. In: Pointcheval D., Johansson T. (eds)
840  * Advances in Cryptology – EUROCRYPT 2012. EUROCRYPT 2012. Lecture Notes in
841  * Computer Science, vol 7237. Springer, Berlin, Heidelberg
842  *
843  * During offline key generation, this multiparty scheme relies on the clients
844  * coordinating their public key generation.  To do this, a single client
845  * generates a public-secret key pair. This public key is shared with other keys
846  * which use an element in the public key to generate their own public keys. The
847  * clients generate a shared key pair using a scheme-specific approach, then
848  * generate re-encryption keys.  Re-encryption keys are uploaded to the server.
849  * Clients encrypt data with their public keys and send the encrypted data
850  * server. The data is re-encrypted.  Computations are then run on the data. The
851  * result is sent to each of the clients. One client runs a "Leader" multiparty
852  * decryption operation with its own secret key.  All other clients run a
853  * regular "Main" multiparty decryption with their own secret key. The resulting
854  * partially decrypted ciphertext are then fully decrypted with the decryption
855  * fusion algorithms.
856  *
857  * @tparam Element a ring element.
858  */
859 template <class Element>
860 class LPAlgorithmMultipartyBFV : public LPMultipartyAlgorithm<Element> {
861   using IntType = typename Element::Integer;
862   using ParmType = typename Element::Params;
863   using DggType = typename Element::DggType;
864   using DugType = typename Element::DugType;
865   using TugType = typename Element::TugType;
866 
867  public:
868   /**
869    * Default constructor
870    */
871   LPAlgorithmMultipartyBFV() {}
872 
873   virtual ~LPAlgorithmMultipartyBFV() {}
874 
875   /**
876    * Threshold FHE: Generation of a public key derived
877    * from a previous joined public key (for prior secret shares) and the secret
878    * key share of the current party.
879    *
880    * @param cc cryptocontext for the keys to be generated.
881    * @param pk1 joined public key from prior parties.
882    * @param makeSparse set to true if ring reduce by a factor of 2 is to be
883    * used. NOT SUPPORTED BY ANY SCHEME ANYMORE.
884    * @param fresh set to true if proxy re-encryption is used in the multi-party
885    * protocol or star topology is used
886    * @return key pair including the secret share for the current party and
887    * joined public key
888    */
889   LPKeyPair<Element> MultipartyKeyGen(CryptoContext<Element> cc,
890                                       const LPPublicKey<Element> pk1,
891                                       bool makeSparse = false,
892                                       bool fresh = false) override;
893 
894   /**
895    * Threshold FHE: Generates a public key from a vector of secret shares.
896    * ONLY FOR DEBUGGIN PURPOSES. SHOULD NOT BE USED IN PRODUCTION.
897    *
898    * @param cc cryptocontext for the keys to be generated.
899    * @param secretkeys secrete key sahres.
900    * @param makeSparse set to true if ring reduce by a factor of 2 is to be
901    * used. NOT SUPPORTED BY ANY SCHEME ANYMORE.
902    * @return key pair including the private for the current party and joined
903    * public key
904    */
905   LPKeyPair<Element> MultipartyKeyGen(
906       CryptoContext<Element> cc,
907       const vector<LPPrivateKey<Element>> &secretKeys,
908       bool makeSparse = false) override;
909 
910   /**
911    * Threshold FHE: "Partial" decryption computed by all parties except for the
912    * lead one.
913    *
914    * @param privateKey secret key share used for decryption.
915    * @param ciphertext ciphertext that is being decrypted.
916    */
917   Ciphertext<Element> MultipartyDecryptMain(
918       const LPPrivateKey<Element> privateKey,
919       ConstCiphertext<Element> ciphertext) const override;
920 
921   /**
922    * Threshold FHE: Method for decryption operation run by the lead decryption
923    * client.
924    *
925    * @param privateKey secret key share used for decryption.
926    * @param ciphertext ciphertext id decrypted.
927    */
928   Ciphertext<Element> MultipartyDecryptLead(
929       const LPPrivateKey<Element> privateKey,
930       ConstCiphertext<Element> ciphertext) const override;
931 
932   /**
933    * Threshold FHE: Method for combining the partially decrypted ciphertexts
934    * and getting the final decryption in the clear as a NativePoly.
935    *
936    * @param &ciphertextVec vector of "partial" decryptions.
937    * @param *plaintext the plaintext output as a NativePoly.
938    * @return the decoding result.
939    */
940   DecryptResult MultipartyDecryptFusion(
941       const vector<Ciphertext<Element>> &ciphertextVec,
942       NativePoly *plaintext) const override;
943 
944   /**
945    * Threshold FHE: Generates a joined evaluation key
946    * from the current secret share and a prior joined
947    * evaluation key
948    *
949    * @param originalPrivateKey secret key transformed from.
950    * @param newPrivateKey secret key transformed to.
951    * @param ek the prior joined evaluation key.
952    * @return the new joined evaluation key.
953    */
954   LPEvalKey<Element> MultiKeySwitchGen(
955       const LPPrivateKey<Element> originalPrivateKey,
956       const LPPrivateKey<Element> newPrivateKey,
957       const LPEvalKey<Element> ek) const override;
958 
959   /**
960    * Threshold FHE: Generates joined automorphism keys
961    * from the current secret share and prior joined
962    * automorphism keys
963    *
964    * @param privateKey secret key share.
965    * @param eAuto a dictionary with prior joined automorphism keys.
966    * @param &indexList a vector of automorphism indices.
967    * @return a dictionary with new joined automorphism keys.
968    */
969   shared_ptr<std::map<usint, LPEvalKey<Element>>> MultiEvalAutomorphismKeyGen(
970       const LPPrivateKey<Element> privateKey,
971       const shared_ptr<std::map<usint, LPEvalKey<Element>>> eAuto,
972       const std::vector<usint> &indexList) const override;
973 
974   /**
975    * Threshold FHE: Generates joined summation evaluation keys
976    * from the current secret share and prior joined
977    * summation keys
978    *
979    * @param privateKey secret key share.
980    * @param eSum a dictionary with prior joined summation keys.
981    * @return new joined summation keys.
982    */
983   shared_ptr<std::map<usint, LPEvalKey<Element>>> MultiEvalSumKeyGen(
984       const LPPrivateKey<Element> privateKey,
985       const shared_ptr<std::map<usint, LPEvalKey<Element>>> eSum)
986       const override;
987 
988   /**
989    * Threshold FHE: Adds two prior evaluation keys
990    *
991    * @param evalKey1 first evaluation key.
992    * @param evalKey2 second evaluation key.
993    * @return the new joined key.
994    */
995   LPEvalKey<Element> MultiAddEvalKeys(
996       LPEvalKey<Element> evalKey1, LPEvalKey<Element> evalKey2) const override;
997 
998   /**
999    * Threshold FHE: Generates a partial evaluation key for homomorphic
1000    * multiplication based on the current secret share and an existing partial
1001    * evaluation key
1002    *
1003    * @param evalKey prior evaluation key.
1004    * @param sk current secret share.
1005    * @return the new joined key.
1006    */
1007   LPEvalKey<Element> MultiMultEvalKey(LPEvalKey<Element> evalKey,
1008                                       LPPrivateKey<Element> sk) const override;
1009 
1010   template <class Archive>
1011   void save(Archive &ar) const {
1012     ar(cereal::base_class<LPMultipartyAlgorithm<Element>>(this));
1013   }
1014 
1015   template <class Archive>
1016   void load(Archive &ar) {
1017     ar(cereal::base_class<LPMultipartyAlgorithm<Element>>(this));
1018   }
1019 
1020   std::string SerializedObjectName() const { return "BFVMultiparty"; }
1021 };
1022 
1023 /**
1024  * @brief Main public key encryption scheme for BFV implementation,
1025  * @tparam Element a ring element.
1026  */
1027 template <class Element>
1028 class LPPublicKeyEncryptionSchemeBFV
1029     : public LPPublicKeyEncryptionScheme<Element> {
1030   using IntType = typename Element::Integer;
1031   using ParmType = typename Element::Params;
1032   using DggType = typename Element::DggType;
1033   using TugType = typename Element::TugType;
1034 
1035  public:
1036   LPPublicKeyEncryptionSchemeBFV();
1037 
1038   bool operator==(
1039       const LPPublicKeyEncryptionScheme<Element> &sch) const override {
1040     return dynamic_cast<const LPPublicKeyEncryptionSchemeBFV<Element> *>(
1041                &sch) != nullptr;
1042   }
1043 
1044   void Enable(PKESchemeFeature feature) override;
1045 
1046   template <class Archive>
1047   void save(Archive &ar, std::uint32_t const version) const {
1048     ar(::cereal::base_class<LPPublicKeyEncryptionScheme<Element>>(this));
1049   }
1050 
1051   template <class Archive>
1052   void load(Archive &ar, std::uint32_t const version) {
1053     ar(::cereal::base_class<LPPublicKeyEncryptionScheme<Element>>(this));
1054   }
1055 
1056   std::string SerializedObjectName() const override { return "BFVScheme"; }
1057 };
1058 
1059 }  // namespace lbcrypto
1060 
1061 #endif
1062