1 // @file cryptocontext.cpp -- Control for encryption operations.
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 #include "cryptocontext.h"
25 #include "utils/serial.h"
26
27 namespace lbcrypto {
28
29 // Initialize global config variable
30 bool SERIALIZE_PRECOMPUTE = true;
31
32 template <typename Element>
EvalMultKeyGen(const LPPrivateKey<Element> key)33 void CryptoContextImpl<Element>::EvalMultKeyGen(
34 const LPPrivateKey<Element> key) {
35 if (key == nullptr || Mismatched(key->GetCryptoContext()))
36 PALISADE_THROW(config_error,
37 "Key passed to EvalMultKeyGen were not generated with this "
38 "crypto context");
39
40 LPEvalKey<Element> k = GetEncryptionAlgorithm()->EvalMultKeyGen(key);
41
42 GetAllEvalMultKeys()[k->GetKeyTag()] = {k};
43 }
44
45 template <typename Element>
EvalMultKeysGen(const LPPrivateKey<Element> key)46 void CryptoContextImpl<Element>::EvalMultKeysGen(
47 const LPPrivateKey<Element> key) {
48 if (key == nullptr || Mismatched(key->GetCryptoContext()))
49 PALISADE_THROW(config_error,
50 "Key passed to EvalMultsKeyGen were not generated with this "
51 "crypto context");
52
53 const vector<LPEvalKey<Element>>& evalKeys =
54 GetEncryptionAlgorithm()->EvalMultKeysGen(key);
55
56 GetAllEvalMultKeys()[evalKeys[0]->GetKeyTag()] = evalKeys;
57 }
58
59 template <typename Element>
60 const vector<LPEvalKey<Element>>&
GetEvalMultKeyVector(const string & keyID)61 CryptoContextImpl<Element>::GetEvalMultKeyVector(const string& keyID) {
62 auto ekv = GetAllEvalMultKeys().find(keyID);
63 if (ekv == GetAllEvalMultKeys().end())
64 PALISADE_THROW(not_available_error,
65 "You need to use EvalMultKeyGen so that you have an "
66 "EvalMultKey available for this ID");
67 return ekv->second;
68 }
69
70 template <typename Element>
71 std::map<string, std::vector<LPEvalKey<Element>>>&
GetAllEvalMultKeys()72 CryptoContextImpl<Element>::GetAllEvalMultKeys() {
73 return evalMultKeyMap();
74 }
75
76 template <typename Element>
ClearEvalMultKeys()77 void CryptoContextImpl<Element>::ClearEvalMultKeys() {
78 GetAllEvalMultKeys().clear();
79 }
80
81 /**
82 * ClearEvalMultKeys - flush EvalMultKey cache for a given id
83 * @param id
84 */
85 template <typename Element>
ClearEvalMultKeys(const string & id)86 void CryptoContextImpl<Element>::ClearEvalMultKeys(const string& id) {
87 auto kd = GetAllEvalMultKeys().find(id);
88 if (kd != GetAllEvalMultKeys().end()) GetAllEvalMultKeys().erase(kd);
89 }
90
91 /**
92 * ClearEvalMultKeys - flush EvalMultKey cache for a given context
93 * @param cc
94 */
95 template <typename Element>
ClearEvalMultKeys(const CryptoContext<Element> cc)96 void CryptoContextImpl<Element>::ClearEvalMultKeys(
97 const CryptoContext<Element> cc) {
98 for (auto it = GetAllEvalMultKeys().begin();
99 it != GetAllEvalMultKeys().end();) {
100 if (it->second[0]->GetCryptoContext() == cc) {
101 it = GetAllEvalMultKeys().erase(it);
102 } else {
103 ++it;
104 }
105 }
106 }
107
108 template <typename Element>
InsertEvalMultKey(const std::vector<LPEvalKey<Element>> & vectorToInsert)109 void CryptoContextImpl<Element>::InsertEvalMultKey(
110 const std::vector<LPEvalKey<Element>>& vectorToInsert) {
111 GetAllEvalMultKeys()[vectorToInsert[0]->GetKeyTag()] = vectorToInsert;
112 }
113
114 template <typename Element>
EvalSumKeyGen(const LPPrivateKey<Element> privateKey,const LPPublicKey<Element> publicKey)115 void CryptoContextImpl<Element>::EvalSumKeyGen(
116 const LPPrivateKey<Element> privateKey,
117 const LPPublicKey<Element> publicKey) {
118 if (privateKey == nullptr || Mismatched(privateKey->GetCryptoContext())) {
119 PALISADE_THROW(config_error,
120 "Private key passed to EvalSumKeyGen were not generated "
121 "with this crypto context");
122 }
123
124 if (publicKey != nullptr &&
125 privateKey->GetKeyTag() != publicKey->GetKeyTag()) {
126 PALISADE_THROW(
127 config_error,
128 "Public key passed to EvalSumKeyGen does not match private key");
129 }
130
131 auto evalKeys =
132 GetEncryptionAlgorithm()->EvalSumKeyGen(privateKey, publicKey);
133
134 GetAllEvalSumKeys()[privateKey->GetKeyTag()] = evalKeys;
135 }
136
137 template <typename Element>
138 shared_ptr<std::map<usint, LPEvalKey<Element>>>
EvalSumRowsKeyGen(const LPPrivateKey<Element> privateKey,const LPPublicKey<Element> publicKey,usint rowSize,usint subringDim)139 CryptoContextImpl<Element>::EvalSumRowsKeyGen(
140 const LPPrivateKey<Element> privateKey,
141 const LPPublicKey<Element> publicKey, usint rowSize, usint subringDim) {
142 if (privateKey == nullptr || Mismatched(privateKey->GetCryptoContext())) {
143 PALISADE_THROW(config_error,
144 "Private key passed to EvalSumKeyGen were not generated "
145 "with this crypto context");
146 }
147
148 if (publicKey != nullptr &&
149 privateKey->GetKeyTag() != publicKey->GetKeyTag()) {
150 PALISADE_THROW(
151 config_error,
152 "Public key passed to EvalSumKeyGen does not match private key");
153 }
154
155 auto evalKeys = GetEncryptionAlgorithm()->EvalSumRowsKeyGen(
156 privateKey, publicKey, rowSize, subringDim);
157
158 return evalKeys;
159 }
160
161 template <typename Element>
162 shared_ptr<std::map<usint, LPEvalKey<Element>>>
EvalSumColsKeyGen(const LPPrivateKey<Element> privateKey,const LPPublicKey<Element> publicKey)163 CryptoContextImpl<Element>::EvalSumColsKeyGen(
164 const LPPrivateKey<Element> privateKey,
165 const LPPublicKey<Element> publicKey) {
166 if (privateKey == nullptr || Mismatched(privateKey->GetCryptoContext())) {
167 PALISADE_THROW(config_error,
168 "Private key passed to EvalSumKeyGen were not generated "
169 "with this crypto context");
170 }
171
172 if (publicKey != nullptr &&
173 privateKey->GetKeyTag() != publicKey->GetKeyTag()) {
174 PALISADE_THROW(
175 config_error,
176 "Public key passed to EvalSumKeyGen does not match private key");
177 }
178
179 auto evalKeys =
180 GetEncryptionAlgorithm()->EvalSumColsKeyGen(privateKey, publicKey);
181
182 return evalKeys;
183 }
184
185 template <typename Element>
186 const std::map<usint, LPEvalKey<Element>>&
GetEvalSumKeyMap(const string & keyID)187 CryptoContextImpl<Element>::GetEvalSumKeyMap(const string& keyID) {
188 auto ekv = GetAllEvalSumKeys().find(keyID);
189 if (ekv == GetAllEvalSumKeys().end())
190 PALISADE_THROW(not_available_error,
191 "You need to use EvalSumKeyGen so that you have EvalSumKeys "
192 "available for this ID");
193 return *ekv->second;
194 }
195
196 template <typename Element>
197 std::map<string, shared_ptr<std::map<usint, LPEvalKey<Element>>>>&
GetAllEvalSumKeys()198 CryptoContextImpl<Element>::GetAllEvalSumKeys() {
199 return evalSumKeyMap();
200 }
201
202 template <typename Element>
ClearEvalSumKeys()203 void CryptoContextImpl<Element>::ClearEvalSumKeys() {
204 GetAllEvalSumKeys().clear();
205 }
206
207 /**
208 * ClearEvalMultKeys - flush EvalMultKey cache for a given id
209 * @param id
210 */
211 template <typename Element>
ClearEvalSumKeys(const string & id)212 void CryptoContextImpl<Element>::ClearEvalSumKeys(const string& id) {
213 auto kd = GetAllEvalSumKeys().find(id);
214 if (kd != GetAllEvalSumKeys().end()) GetAllEvalSumKeys().erase(kd);
215 }
216
217 /**
218 * ClearEvalMultKeys - flush EvalMultKey cache for a given context
219 * @param cc
220 */
221 template <typename Element>
ClearEvalSumKeys(const CryptoContext<Element> cc)222 void CryptoContextImpl<Element>::ClearEvalSumKeys(
223 const CryptoContext<Element> cc) {
224 for (auto it = GetAllEvalSumKeys().begin();
225 it != GetAllEvalSumKeys().end();) {
226 if (it->second->begin()->second->GetCryptoContext() == cc) {
227 it = GetAllEvalSumKeys().erase(it);
228 } else {
229 ++it;
230 }
231 }
232 }
233
234 template <typename Element>
InsertEvalSumKey(const shared_ptr<std::map<usint,LPEvalKey<Element>>> mapToInsert)235 void CryptoContextImpl<Element>::InsertEvalSumKey(
236 const shared_ptr<std::map<usint, LPEvalKey<Element>>> mapToInsert) {
237 // find the tag
238 if (!mapToInsert->empty()) {
239 auto onekey = mapToInsert->begin();
240 GetAllEvalSumKeys()[onekey->second->GetKeyTag()] = mapToInsert;
241 }
242 }
243
244 template <typename Element>
EvalAtIndexKeyGen(const LPPrivateKey<Element> privateKey,const std::vector<int32_t> & indexList,const LPPublicKey<Element> publicKey)245 void CryptoContextImpl<Element>::EvalAtIndexKeyGen(
246 const LPPrivateKey<Element> privateKey,
247 const std::vector<int32_t>& indexList,
248 const LPPublicKey<Element> publicKey) {
249 if (privateKey == nullptr || Mismatched(privateKey->GetCryptoContext())) {
250 PALISADE_THROW(config_error,
251 "Private key passed to EvalAtIndexKeyGen were not generated "
252 "with this crypto context");
253 }
254
255 if (publicKey != nullptr &&
256 privateKey->GetKeyTag() != publicKey->GetKeyTag()) {
257 PALISADE_THROW(
258 config_error,
259 "Public key passed to EvalAtIndexKeyGen does not match private key");
260 }
261
262 auto evalKeys = GetEncryptionAlgorithm()->EvalAtIndexKeyGen(
263 publicKey, privateKey, indexList);
264
265 evalAutomorphismKeyMap()[privateKey->GetKeyTag()] = evalKeys;
266 }
267
268 template <typename Element>
269 const std::map<usint, LPEvalKey<Element>>&
GetEvalAutomorphismKeyMap(const string & keyID)270 CryptoContextImpl<Element>::GetEvalAutomorphismKeyMap(const string& keyID) {
271 auto ekv = evalAutomorphismKeyMap().find(keyID);
272 if (ekv == evalAutomorphismKeyMap().end())
273 PALISADE_THROW(not_available_error,
274 "You need to use EvalAutomorphismKeyGen so that you have "
275 "EvalAutomorphismKeys available for this ID");
276 return *ekv->second;
277 }
278
279 template <typename Element>
280 std::map<string, shared_ptr<std::map<usint, LPEvalKey<Element>>>>&
GetAllEvalAutomorphismKeys()281 CryptoContextImpl<Element>::GetAllEvalAutomorphismKeys() {
282 return evalAutomorphismKeyMap();
283 }
284
285 template <typename Element>
ClearEvalAutomorphismKeys()286 void CryptoContextImpl<Element>::ClearEvalAutomorphismKeys() {
287 evalAutomorphismKeyMap().clear();
288 }
289
290 /**
291 * ClearEvalAutomorphismKeys - flush EvalAutomorphismKey cache for a given id
292 * @param id
293 */
294 template <typename Element>
ClearEvalAutomorphismKeys(const string & id)295 void CryptoContextImpl<Element>::ClearEvalAutomorphismKeys(const string& id) {
296 auto kd = evalAutomorphismKeyMap().find(id);
297 if (kd != evalAutomorphismKeyMap().end()) evalAutomorphismKeyMap().erase(kd);
298 }
299
300 /**
301 * ClearEvalAutomorphismKeys - flush EvalAutomorphismKey cache for a given
302 * context
303 * @param cc
304 */
305 template <typename Element>
ClearEvalAutomorphismKeys(const CryptoContext<Element> cc)306 void CryptoContextImpl<Element>::ClearEvalAutomorphismKeys(
307 const CryptoContext<Element> cc) {
308 for (auto it = evalAutomorphismKeyMap().begin();
309 it != evalAutomorphismKeyMap().end();) {
310 if (it->second->begin()->second->GetCryptoContext() == cc) {
311 it = evalAutomorphismKeyMap().erase(it);
312 } else {
313 ++it;
314 }
315 }
316 }
317
318 template <typename Element>
InsertEvalAutomorphismKey(const shared_ptr<std::map<usint,LPEvalKey<Element>>> mapToInsert)319 void CryptoContextImpl<Element>::InsertEvalAutomorphismKey(
320 const shared_ptr<std::map<usint, LPEvalKey<Element>>> mapToInsert) {
321 // find the tag
322 auto onekey = mapToInsert->begin();
323 evalAutomorphismKeyMap()[onekey->second->GetKeyTag()] = mapToInsert;
324 }
325
326 template <typename Element>
EvalSum(ConstCiphertext<Element> ciphertext,usint batchSize) const327 Ciphertext<Element> CryptoContextImpl<Element>::EvalSum(
328 ConstCiphertext<Element> ciphertext, usint batchSize) const {
329 if (ciphertext == nullptr || Mismatched(ciphertext->GetCryptoContext()))
330 PALISADE_THROW(config_error,
331 "Information passed to EvalSum was not generated with this "
332 "crypto context");
333
334 auto evalSumKeys =
335 CryptoContextImpl<Element>::GetEvalSumKeyMap(ciphertext->GetKeyTag());
336 auto rv =
337 GetEncryptionAlgorithm()->EvalSum(ciphertext, batchSize, evalSumKeys);
338 return rv;
339 }
340
341 template <typename Element>
EvalSumRows(ConstCiphertext<Element> ciphertext,usint rowSize,const std::map<usint,LPEvalKey<Element>> & evalSumKeys,usint subringDim) const342 Ciphertext<Element> CryptoContextImpl<Element>::EvalSumRows(
343 ConstCiphertext<Element> ciphertext, usint rowSize,
344 const std::map<usint, LPEvalKey<Element>>& evalSumKeys,
345 usint subringDim) const {
346 if (ciphertext == nullptr || Mismatched(ciphertext->GetCryptoContext()))
347 PALISADE_THROW(config_error,
348 "Information passed to EvalSum was not generated with this "
349 "crypto context");
350
351 auto rv = GetEncryptionAlgorithm()->EvalSumRows(ciphertext, rowSize,
352 evalSumKeys, subringDim);
353 return rv;
354 }
355
356 template <typename Element>
EvalSumCols(ConstCiphertext<Element> ciphertext,usint rowSize,const std::map<usint,LPEvalKey<Element>> & evalSumKeysRight) const357 Ciphertext<Element> CryptoContextImpl<Element>::EvalSumCols(
358 ConstCiphertext<Element> ciphertext, usint rowSize,
359 const std::map<usint, LPEvalKey<Element>>& evalSumKeysRight) const {
360 if (ciphertext == nullptr || Mismatched(ciphertext->GetCryptoContext()))
361 PALISADE_THROW(config_error,
362 "Information passed to EvalSum was not generated with this "
363 "crypto context");
364
365 auto evalSumKeys =
366 CryptoContextImpl<Element>::GetEvalSumKeyMap(ciphertext->GetKeyTag());
367
368 auto rv = GetEncryptionAlgorithm()->EvalSumCols(
369 ciphertext, rowSize, evalSumKeys, evalSumKeysRight);
370 return rv;
371 }
372
373 template <typename Element>
EvalAtIndex(ConstCiphertext<Element> ciphertext,int32_t index) const374 Ciphertext<Element> CryptoContextImpl<Element>::EvalAtIndex(
375 ConstCiphertext<Element> ciphertext, int32_t index) const {
376 if (ciphertext == nullptr || Mismatched(ciphertext->GetCryptoContext()))
377 PALISADE_THROW(config_error,
378 "Information passed to EvalAtIndex was not generated with "
379 "this crypto context");
380
381 // If the index is zero, no rotation is needed, copy the ciphertext and return
382 // This is done after the keyMap so that it is protected if there's not a valid key.
383 if (0 == index) {
384 auto rv = ciphertext->Clone();
385 return rv;
386 }
387
388 auto evalAutomorphismKeys =
389 CryptoContextImpl<Element>::GetEvalAutomorphismKeyMap(
390 ciphertext->GetKeyTag());
391
392 auto rv = GetEncryptionAlgorithm()->EvalAtIndex(ciphertext, index,
393 evalAutomorphismKeys);
394 return rv;
395 }
396
397 template <typename Element>
EvalMerge(const vector<Ciphertext<Element>> & ciphertextVector) const398 Ciphertext<Element> CryptoContextImpl<Element>::EvalMerge(
399 const vector<Ciphertext<Element>>& ciphertextVector) const {
400 if (ciphertextVector[0] == nullptr ||
401 Mismatched(ciphertextVector[0]->GetCryptoContext()))
402 PALISADE_THROW(config_error,
403 "Information passed to EvalMerge was not generated with "
404 "this crypto context");
405
406 auto evalAutomorphismKeys =
407 CryptoContextImpl<Element>::GetEvalAutomorphismKeyMap(
408 ciphertextVector[0]->GetKeyTag());
409
410 auto rv = GetEncryptionAlgorithm()->EvalMerge(ciphertextVector,
411 evalAutomorphismKeys);
412
413 return rv;
414 }
415
416 template <typename Element>
EvalInnerProduct(ConstCiphertext<Element> ct1,ConstCiphertext<Element> ct2,usint batchSize) const417 Ciphertext<Element> CryptoContextImpl<Element>::EvalInnerProduct(
418 ConstCiphertext<Element> ct1, ConstCiphertext<Element> ct2,
419 usint batchSize) const {
420 if (ct1 == nullptr || ct2 == nullptr ||
421 ct1->GetKeyTag() != ct2->GetKeyTag() ||
422 Mismatched(ct1->GetCryptoContext()))
423 PALISADE_THROW(config_error,
424 "Information passed to EvalInnerProduct was not generated "
425 "with this crypto context");
426
427 auto evalSumKeys =
428 CryptoContextImpl<Element>::GetEvalSumKeyMap(ct1->GetKeyTag());
429 auto ek = GetEvalMultKeyVector(ct1->GetKeyTag());
430
431 auto rv = GetEncryptionAlgorithm()->EvalInnerProduct(ct1, ct2, batchSize,
432 evalSumKeys, ek[0]);
433 return rv;
434 }
435
436 template <typename Element>
EvalInnerProduct(ConstCiphertext<Element> ct1,ConstPlaintext ct2,usint batchSize) const437 Ciphertext<Element> CryptoContextImpl<Element>::EvalInnerProduct(
438 ConstCiphertext<Element> ct1, ConstPlaintext ct2, usint batchSize) const {
439 if (ct1 == nullptr || ct2 == nullptr || Mismatched(ct1->GetCryptoContext()))
440 PALISADE_THROW(config_error,
441 "Information passed to EvalInnerProduct was not generated "
442 "with this crypto context");
443
444 auto evalSumKeys =
445 CryptoContextImpl<Element>::GetEvalSumKeyMap(ct1->GetKeyTag());
446
447 auto rv = GetEncryptionAlgorithm()->EvalInnerProduct(ct1, ct2, batchSize,
448 evalSumKeys);
449 return rv;
450 }
451
452 template <typename Element>
GetPlaintextForDecrypt(PlaintextEncodings pte,shared_ptr<ParmType> evp,EncodingParams ep)453 Plaintext CryptoContextImpl<Element>::GetPlaintextForDecrypt(
454 PlaintextEncodings pte, shared_ptr<ParmType> evp, EncodingParams ep) {
455 auto vp = std::make_shared<typename NativePoly::Params>(
456 evp->GetCyclotomicOrder(), ep->GetPlaintextModulus(), 1);
457
458 if (pte == CKKSPacked) return PlaintextFactory::MakePlaintext(pte, evp, ep);
459
460 return PlaintextFactory::MakePlaintext(pte, vp, ep);
461 }
462
463 template <typename Element>
Decrypt(const LPPrivateKey<Element> privateKey,ConstCiphertext<Element> ciphertext,Plaintext * plaintext)464 DecryptResult CryptoContextImpl<Element>::Decrypt(
465 const LPPrivateKey<Element> privateKey, ConstCiphertext<Element> ciphertext,
466 Plaintext* plaintext) {
467 if (ciphertext == nullptr)
468 PALISADE_THROW(config_error, "ciphertext passed to Decrypt is empty");
469 if (plaintext == nullptr)
470 PALISADE_THROW(config_error, "plaintext passed to Decrypt is empty");
471 if (privateKey == nullptr || Mismatched(privateKey->GetCryptoContext()))
472 PALISADE_THROW(config_error,
473 "Information passed to Decrypt was not generated with "
474 "this crypto context");
475
476 // determine which type of plaintext that you need to decrypt into
477 // Plaintext decrypted =
478 // GetPlaintextForDecrypt(ciphertext->GetEncodingType(),
479 // this->GetElementParams(), this->GetEncodingParams());
480 Plaintext decrypted = GetPlaintextForDecrypt(
481 ciphertext->GetEncodingType(), ciphertext->GetElements()[0].GetParams(),
482 this->GetEncodingParams());
483
484 DecryptResult result;
485
486 if ((ciphertext->GetEncodingType() == CKKSPacked) &&
487 (typeid(Element) != typeid(NativePoly))) {
488 result = GetEncryptionAlgorithm()->Decrypt(privateKey, ciphertext,
489 &decrypted->GetElement<Poly>());
490 } else {
491 result = GetEncryptionAlgorithm()->Decrypt(
492 privateKey, ciphertext, &decrypted->GetElement<NativePoly>());
493 }
494
495 if (result.isValid == false) return result;
496
497 if (ciphertext->GetEncodingType() == CKKSPacked) {
498 auto decryptedCKKS =
499 std::static_pointer_cast<CKKSPackedEncoding>(decrypted);
500 decryptedCKKS->SetDepth(ciphertext->GetDepth());
501 decryptedCKKS->SetLevel(ciphertext->GetLevel());
502 decryptedCKKS->SetScalingFactor(ciphertext->GetScalingFactor());
503
504 const auto cryptoParamsCKKS =
505 std::dynamic_pointer_cast<LPCryptoParametersCKKS<DCRTPoly>>(
506 this->GetCryptoParameters());
507
508 decryptedCKKS->Decode(ciphertext->GetDepth(),
509 ciphertext->GetScalingFactor(),
510 cryptoParamsCKKS->GetRescalingTechnique());
511
512 } else {
513 decrypted->Decode();
514 }
515
516 *plaintext = std::move(decrypted);
517 return result;
518 }
519
520 template <typename Element>
MultipartyDecryptFusion(const vector<Ciphertext<Element>> & partialCiphertextVec,Plaintext * plaintext) const521 DecryptResult CryptoContextImpl<Element>::MultipartyDecryptFusion(
522 const vector<Ciphertext<Element>>& partialCiphertextVec,
523 Plaintext* plaintext) const {
524 DecryptResult result;
525
526 // Make sure we're processing ciphertexts.
527 size_t last_ciphertext = partialCiphertextVec.size();
528 if (last_ciphertext < 1) return result;
529
530 for (size_t i = 0; i < last_ciphertext; i++) {
531 if (partialCiphertextVec[i] == nullptr ||
532 Mismatched(partialCiphertextVec[i]->GetCryptoContext()))
533 PALISADE_THROW(config_error,
534 "A ciphertext passed to MultipartyDecryptFusion was not "
535 "generated with this crypto context");
536 if (partialCiphertextVec[i]->GetEncodingType() !=
537 partialCiphertextVec[0]->GetEncodingType())
538 PALISADE_THROW(type_error,
539 "Ciphertexts passed to MultipartyDecryptFusion have "
540 "mismatched encoding types");
541 }
542
543 // determine which type of plaintext that you need to decrypt into
544 Plaintext decrypted = GetPlaintextForDecrypt(
545 partialCiphertextVec[0]->GetEncodingType(),
546 partialCiphertextVec[0]->GetElements()[0].GetParams(),
547 this->GetEncodingParams());
548
549 if ((partialCiphertextVec[0]->GetEncodingType() == CKKSPacked) &&
550 (typeid(Element) != typeid(NativePoly)))
551 result = GetEncryptionAlgorithm()->MultipartyDecryptFusion(
552 partialCiphertextVec, &decrypted->GetElement<Poly>());
553 else
554 result = GetEncryptionAlgorithm()->MultipartyDecryptFusion(
555 partialCiphertextVec, &decrypted->GetElement<NativePoly>());
556
557 if (result.isValid == false) return result;
558
559 if (partialCiphertextVec[0]->GetEncodingType() == CKKSPacked) {
560 auto decryptedCKKS =
561 std::static_pointer_cast<CKKSPackedEncoding>(decrypted);
562 const auto cryptoParamsCKKS =
563 std::dynamic_pointer_cast<LPCryptoParametersCKKS<DCRTPoly>>(
564 this->GetCryptoParameters());
565 decryptedCKKS->Decode(partialCiphertextVec[0]->GetDepth(),
566 partialCiphertextVec[0]->GetScalingFactor(),
567 cryptoParamsCKKS->GetRescalingTechnique());
568 } else {
569 decrypted->Decode();
570 }
571
572 *plaintext = std::move(decrypted);
573
574 return result;
575 }
576
577 } // namespace lbcrypto
578