|
@@ -1,91 +1,21 @@
|
|
|
-#include "openfhe/src/lib.rs.h"
|
|
|
+#include "CryptoContext.h"
|
|
|
|
|
|
#include "openfhe/pke/gen-cryptocontext.h"
|
|
|
+#include "openfhe/pke/scheme/bfvrns/gen-cryptocontext-bfvrns.h"
|
|
|
+#include "openfhe/pke/scheme/bgvrns/gen-cryptocontext-bgvrns.h"
|
|
|
+#include "openfhe/pke/scheme/ckksrns/gen-cryptocontext-ckksrns.h"
|
|
|
|
|
|
-// This inclusion is required for SerializeCryptoContextToFile
|
|
|
-// and DeserializeCryptoContextFromFile functions for calling
|
|
|
-// specialized versions of the corresponding functions.
|
|
|
-#include "openfhe/pke/cryptocontext-ser.h"
|
|
|
+#include "openfhe/src/lib.rs.h" // ComplexPair
|
|
|
|
|
|
-namespace openfhe
|
|
|
-{
|
|
|
-PublicKeyDCRTPoly::PublicKeyDCRTPoly()
|
|
|
- : m_publicKey(std::make_shared<PublicKeyImpl>())
|
|
|
-{ }
|
|
|
-std::shared_ptr<PublicKeyImpl> PublicKeyDCRTPoly::GetInternal() const
|
|
|
-{
|
|
|
- return m_publicKey;
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-KeyPairDCRTPoly::KeyPairDCRTPoly(lbcrypto::KeyPair<lbcrypto::DCRTPoly> keyPair)
|
|
|
- : m_publicKey(keyPair.publicKey)
|
|
|
- , m_privateKey(keyPair.secretKey)
|
|
|
-{ }
|
|
|
-std::shared_ptr<PublicKeyImpl> KeyPairDCRTPoly::GetPublicKey() const
|
|
|
-{
|
|
|
- return m_publicKey;
|
|
|
-}
|
|
|
-std::shared_ptr<PrivateKeyImpl> KeyPairDCRTPoly::GetPrivateKey() const
|
|
|
-{
|
|
|
- return m_privateKey;
|
|
|
-}
|
|
|
+#include "Ciphertext.h"
|
|
|
+#include "KeyPair.h"
|
|
|
+#include "Plaintext.h"
|
|
|
+#include "PublicKey.h"
|
|
|
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-Plaintext::Plaintext(std::shared_ptr<PlaintextImpl> plaintext)
|
|
|
- : m_plaintext(plaintext)
|
|
|
-{ }
|
|
|
-Plaintext& Plaintext::operator=(std::shared_ptr<PlaintextImpl> plaintext)
|
|
|
-{
|
|
|
- m_plaintext = plaintext;
|
|
|
- return *this;
|
|
|
-}
|
|
|
-std::shared_ptr<PlaintextImpl> Plaintext::GetInternal() const
|
|
|
-{
|
|
|
- return m_plaintext;
|
|
|
-}
|
|
|
-void Plaintext::SetLength(const size_t newSize) const
|
|
|
-{
|
|
|
- m_plaintext->SetLength(newSize);
|
|
|
-}
|
|
|
-double Plaintext::GetLogPrecision() const
|
|
|
-{
|
|
|
- return m_plaintext->GetLogPrecision();
|
|
|
-}
|
|
|
-rust::String Plaintext::GetString() const
|
|
|
-{
|
|
|
- std::stringstream stream;
|
|
|
- stream << *m_plaintext;
|
|
|
- return rust::String(stream.str());
|
|
|
-}
|
|
|
-std::unique_ptr<std::vector<ComplexPair>> Plaintext::GetCopyOfCKKSPackedValue() const
|
|
|
-{
|
|
|
- const std::vector<std::complex<double>>& v = m_plaintext->GetCKKSPackedValue();
|
|
|
- std::vector<ComplexPair> result;
|
|
|
- result.reserve(v.size());
|
|
|
- for (const std::complex<double>& elem : v)
|
|
|
- {
|
|
|
- result.push_back(ComplexPair{elem.real(), elem.imag()});
|
|
|
- }
|
|
|
- return std::make_unique<std::vector<ComplexPair>>(std::move(result));
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-CiphertextDCRTPoly::CiphertextDCRTPoly()
|
|
|
- : m_ciphertext(std::make_shared<CiphertextImpl>())
|
|
|
-{ }
|
|
|
-CiphertextDCRTPoly::CiphertextDCRTPoly(std::shared_ptr<CiphertextImpl> ciphertext)
|
|
|
- : m_ciphertext(ciphertext)
|
|
|
-{ }
|
|
|
-std::shared_ptr<CiphertextImpl> CiphertextDCRTPoly::GetInternal() const
|
|
|
+namespace openfhe
|
|
|
{
|
|
|
- return m_ciphertext;
|
|
|
-}
|
|
|
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
+using PlaintextImpl = lbcrypto::PlaintextImpl;
|
|
|
|
|
|
CryptoContextDCRTPoly::CryptoContextDCRTPoly(const ParamsBFVRNS& params)
|
|
|
: m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
|
|
@@ -561,44 +491,6 @@ std::unique_ptr<std::vector<uint32_t>> GetUniqueValues(const std::vector<uint32_
|
|
|
CryptoContextImpl::GetUniqueValues(oldValues, newValues));
|
|
|
}
|
|
|
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-std::unique_ptr<Params> GetParamsByScheme(const SCHEME scheme)
|
|
|
-{
|
|
|
- return std::make_unique<Params>(scheme);
|
|
|
-}
|
|
|
-std::unique_ptr<Params> GetParamsByVectorOfString(const std::vector<std::string>& vals)
|
|
|
-{
|
|
|
- return std::make_unique<Params>(vals);
|
|
|
-}
|
|
|
-std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNS()
|
|
|
-{
|
|
|
- return std::make_unique<ParamsBFVRNS>();
|
|
|
-}
|
|
|
-std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNSbyVectorOfString(const std::vector<std::string>& vals)
|
|
|
-{
|
|
|
- return std::make_unique<ParamsBFVRNS>(vals);
|
|
|
-}
|
|
|
-std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNS()
|
|
|
-{
|
|
|
- return std::make_unique<ParamsBGVRNS>();
|
|
|
-}
|
|
|
-std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNSbyVectorOfString(const std::vector<std::string>& vals)
|
|
|
-{
|
|
|
- return std::make_unique<ParamsBGVRNS>(vals);
|
|
|
-}
|
|
|
-std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNS()
|
|
|
-{
|
|
|
- return std::make_unique<ParamsCKKSRNS>();
|
|
|
-}
|
|
|
-std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNSbyVectorOfString(const std::vector<std::string>& vals)
|
|
|
-{
|
|
|
- return std::make_unique<ParamsCKKSRNS>(vals);
|
|
|
-}
|
|
|
-std::unique_ptr<Plaintext> GenEmptyPlainText()
|
|
|
-{
|
|
|
- return std::make_unique<Plaintext>();
|
|
|
-}
|
|
|
std::unique_ptr<CryptoContextDCRTPoly> GenEmptyCryptoContext()
|
|
|
{
|
|
|
return std::make_unique<CryptoContextDCRTPoly>();
|
|
@@ -615,296 +507,5 @@ std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsCKKSRNS(const Par
|
|
|
{
|
|
|
return std::make_unique<CryptoContextDCRTPoly>(params);
|
|
|
}
|
|
|
-std::unique_ptr<PublicKeyDCRTPoly> GenDefaultConstructedPublicKey()
|
|
|
-{
|
|
|
- return std::make_unique<PublicKeyDCRTPoly>();
|
|
|
-}
|
|
|
-std::unique_ptr<CiphertextDCRTPoly> GenDefaultConstructedCiphertext()
|
|
|
-{
|
|
|
- return std::make_unique<CiphertextDCRTPoly>();
|
|
|
-}
|
|
|
-
|
|
|
-///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
-bool SerializeCryptoContextToFile(const std::string& ccLocation,
|
|
|
- const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::SerializeToFile(ccLocation,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::SerializeToFile(ccLocation,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool DeserializeCryptoContextFromFile(const std::string& ccLocation,
|
|
|
- CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::DeserializeFromFile(ccLocation,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::DeserializeFromFile(ccLocation,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeEvalMultKeyToFile(const std::string& multKeyLocation,
|
|
|
- const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
|
|
|
- const std::unique_ptr<std::ofstream, decltype(close)> ofs(
|
|
|
- new std::ofstream(multKeyLocation, std::ios::out | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ofs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalMultKey(*ofs,
|
|
|
- lbcrypto::SerType::BINARY, cryptoContext.m_cryptoContextImplSharedPtr);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalMultKey(*ofs,
|
|
|
- lbcrypto::SerType::JSON, cryptoContext.m_cryptoContextImplSharedPtr);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeEvalMultKeyByIdToFile(const std::string& multKeyLocation,
|
|
|
- const SerialMode serialMode, const std::string& id)
|
|
|
-{
|
|
|
- const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
|
|
|
- const std::unique_ptr<std::ofstream, decltype(close)> ofs(
|
|
|
- new std::ofstream(multKeyLocation, std::ios::out | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ofs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalMultKey(*ofs, lbcrypto::SerType::BINARY, id);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalMultKey(*ofs, lbcrypto::SerType::JSON, id);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool DeserializeEvalMultKeyFromFile(const std::string& multKeyLocation,
|
|
|
- const SerialMode serialMode)
|
|
|
-{
|
|
|
- const auto close = [](std::ifstream* const ifs){ if (ifs->is_open()) { ifs->close(); } };
|
|
|
- const std::unique_ptr<std::ifstream, decltype(close)> ifs(
|
|
|
- new std::ifstream(multKeyLocation, std::ios::in | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ifs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::DeserializeEvalMultKey(*ifs, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::DeserializeEvalMultKey(*ifs, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeEvalSumKeyToFile(const std::string& sumKeyLocation,
|
|
|
- const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
|
|
|
- const std::unique_ptr<std::ofstream, decltype(close)> ofs(
|
|
|
- new std::ofstream(sumKeyLocation, std::ios::out | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ofs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalAutomorphismKey(*ofs, lbcrypto::SerType::BINARY,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalAutomorphismKey(*ofs, lbcrypto::SerType::JSON,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeEvalSumKeyByIdToFile(const std::string& sumKeyLocation,
|
|
|
- const SerialMode serialMode, const std::string& id)
|
|
|
-{
|
|
|
- const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
|
|
|
- const std::unique_ptr<std::ofstream, decltype(close)> ofs(
|
|
|
- new std::ofstream(sumKeyLocation, std::ios::out | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ofs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalSumKey(*ofs, lbcrypto::SerType::BINARY, id);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalSumKey(*ofs, lbcrypto::SerType::JSON, id);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool DeserializeEvalSumKeyFromFile(const std::string& sumKeyLocation, const SerialMode serialMode)
|
|
|
-{
|
|
|
- const auto close = [](std::ifstream* const ifs){ if (ifs->is_open()) { ifs->close(); } };
|
|
|
- const std::unique_ptr<std::ifstream, decltype(close)> ifs(
|
|
|
- new std::ifstream(sumKeyLocation, std::ios::in | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ifs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::DeserializeEvalAutomorphismKey(*ifs,
|
|
|
- lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::DeserializeEvalAutomorphismKey(*ifs,
|
|
|
- lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeEvalAutomorphismKeyToFile(const std::string& automorphismKeyLocation,
|
|
|
- const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
|
|
|
- const std::unique_ptr<std::ofstream, decltype(close)> ofs(
|
|
|
- new std::ofstream(automorphismKeyLocation, std::ios::out | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ofs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalAutomorphismKey(*ofs, lbcrypto::SerType::BINARY,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalAutomorphismKey(*ofs, lbcrypto::SerType::JSON,
|
|
|
- cryptoContext.m_cryptoContextImplSharedPtr);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeEvalAutomorphismKeyByIdToFile(const std::string& automorphismKeyLocation,
|
|
|
- const SerialMode serialMode, const std::string& id)
|
|
|
-{
|
|
|
- const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
|
|
|
- const std::unique_ptr<std::ofstream, decltype(close)> ofs(
|
|
|
- new std::ofstream(automorphismKeyLocation, std::ios::out | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ofs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalAutomorphismKey(*ofs, lbcrypto::SerType::BINARY,
|
|
|
- id);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::SerializeEvalAutomorphismKey(*ofs, lbcrypto::SerType::JSON,
|
|
|
- id);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool DeserializeEvalAutomorphismKeyFromFile(const std::string& automorphismKeyLocation,
|
|
|
- const SerialMode serialMode)
|
|
|
-{
|
|
|
- const auto close = [](std::ifstream* const ifs){ if (ifs->is_open()) { ifs->close(); } };
|
|
|
- const std::unique_ptr<std::ifstream, decltype(close)> ifs(
|
|
|
- new std::ifstream(automorphismKeyLocation, std::ios::in | std::ios::binary), close);
|
|
|
-
|
|
|
- if (ifs->is_open())
|
|
|
- {
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return CryptoContextImpl::DeserializeEvalAutomorphismKey(*ifs,
|
|
|
- lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return CryptoContextImpl::DeserializeEvalAutomorphismKey(*ifs,
|
|
|
- lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializeCiphertextToFile(const std::string& ciphertextLocation,
|
|
|
- const CiphertextDCRTPoly& ciphertext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::SerializeToFile(ciphertextLocation,
|
|
|
- ciphertext.m_ciphertext, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::SerializeToFile(ciphertextLocation,
|
|
|
- ciphertext.m_ciphertext, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool DeserializeCiphertextFromFile(const std::string& ciphertextLocation,
|
|
|
- CiphertextDCRTPoly& ciphertext, const SerialMode serialMode)
|
|
|
-{
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::DeserializeFromFile(ciphertextLocation,
|
|
|
- ciphertext.m_ciphertext, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::DeserializeFromFile(ciphertextLocation,
|
|
|
- ciphertext.m_ciphertext, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool SerializePublicKeyToFile(const std::string& publicKeyLocation,
|
|
|
- const PublicKeyDCRTPoly& publicKey, const SerialMode serialMode)
|
|
|
-{
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::SerializeToFile(publicKeyLocation,
|
|
|
- publicKey.m_publicKey, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::SerializeToFile(publicKeyLocation,
|
|
|
- publicKey.m_publicKey, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-bool DeserializePublicKeyFromFile(const std::string& publicKeyLocation,
|
|
|
- PublicKeyDCRTPoly& publicKey, const SerialMode serialMode)
|
|
|
-{
|
|
|
- if (serialMode == SerialMode::BINARY)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::DeserializeFromFile(publicKeyLocation,
|
|
|
- publicKey.m_publicKey, lbcrypto::SerType::BINARY);
|
|
|
- }
|
|
|
- if (serialMode == SerialMode::JSON)
|
|
|
- {
|
|
|
- return lbcrypto::Serial::DeserializeFromFile(publicKeyLocation,
|
|
|
- publicKey.m_publicKey, lbcrypto::SerType::JSON);
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
} // openfhe
|