Hello, I am trying to use OpenFHE for a project that requires threshold FHE. In the current state of my prototype I have two programs.
- the first one generate the cryptocontext, the secret key shares and the joined public key and serialize them
- the second one simulate different third parties that wants to encrypt something using the joined public key and serialize the ciphertext in order to reuse it later
I am experimenting problems when I want to use the deserialized joined public key in my second program. The program is crashing with this error
terminate called after throwing an instance of 'lbcrypto::OpenFHEException'
what(): /usr/local/include/openfhe/pke/cryptocontext.h:l.429:ValidateKey<std::shared_ptr<lbcrypto::PublicKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<long unsigned int> > > > > >(): Ke
y was not generated with the same crypto context
Aborted (core dumped)
I am reusing the same cryptocontext (serialized then deserialized) as when I generated the key.
You will find my two source code below
generator.cpp
#include <openfhe.h>
#include "config.hpp"
using namespace lbcrypto;
int main() {
// Parse the configuration
auto config = Config("config.json");
std::cout << config;
// Generate and serialize cryptocontext
std::cout << "Generate cryptocontext" << std::endl;
CCParams<CryptoContextBFVRNS> parameters;
parameters.SetPlaintextModulus(65537);
parameters.SetSecurityLevel(lbcrypto::SecurityLevel::HEStd_128_classic);
parameters.SetStandardDeviation(3.2);
parameters.SetSecretKeyDist(UNIFORM_TERNARY);
parameters.SetMultiplicativeDepth(4);
parameters.SetBatchSize(16);
parameters.SetDigitSize(30);
parameters.SetScalingModSize(60);
parameters.SetMultiplicationTechnique(HPSPOVERQLEVELED);
CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);
cryptoContext->Enable(PKE);
cryptoContext->Enable(KEYSWITCH);
cryptoContext->Enable(LEVELEDSHE);
cryptoContext->Enable(ADVANCEDSHE);
cryptoContext->Enable(MULTIPARTY);
std::cout << "Generated cryptocontext" << std::endl;
// Perform Key Generation Operation
std::cout << "Perform Key Generation Operation" << std::endl;
std::vector<KeyPair<DCRTPoly>> keyPairs;
// generate the kp for all parties
for ( auto& party: config.parties ) {
KeyPair<DCRTPoly> kp;
if ( keyPairs.empty() ) {
kp = cryptoContext->KeyGen();
} else {
kp = cryptoContext->MultipartyKeyGen(keyPairs.back().publicKey);
}
if (!Serial::SerializeToFile(party.sk, kp.secretKey, SerType::BINARY)) {
std::cerr << "Error writing serialization of the secret key to "
<< party.sk
<< std::endl;
return 1;
}
std::cout << "The secret key for party " << party.id << " has been generated and serialized" << std::endl;
keyPairs.push_back(kp);
}
// Generate evalmult key
// Generate evalsum key
if (!Serial::SerializeToFile(config.cryptocontext, cryptoContext, SerType::BINARY)) {
std::cerr << "Error writing serialization of the crypto context to "
<< config.cryptocontext
<< std::endl;
return 1;
}
std::cout << "The cryptocontext has been serialized." << std::endl;
std::ofstream multKeyFile("test/multkey.txt", std::ios::out | std::ios::binary);
if (multKeyFile.is_open()) {
if (!cryptoContext->SerializeEvalMultKey(multKeyFile, SerType::BINARY)) {
std::cerr << "Error writing eval mult keys" << std::endl;
std::exit(1);
}
std::cout << "EvalMult/ relinearization keys have been serialized" << std::endl;
multKeyFile.close();
}
else {
std::cerr << "Error serializing EvalMult keys" << std::endl;
std::exit(1);
}
std::ofstream rotationKeyFile("test/rotkey.txt", std::ios::out | std::ios::binary);
if (rotationKeyFile.is_open()) {
if (!cryptoContext->SerializeEvalAutomorphismKey(rotationKeyFile, SerType::BINARY)) {
std::cerr << "Error writing rotation keys" << std::endl;
std::exit(1);
}
std::cout << "Rotation keys have been serialized" << std::endl;
}
else {
std::cerr << "Error serializing Rotation keys" << std::endl;
std::exit(1);
}
if (!Serial::SerializeToFile(config.pk, keyPairs.back().publicKey, SerType::BINARY)) {
std::cerr << "Error writing serialization of the joined public key to "
<< config.pk
<< std::endl;
return 1;
}
std::cout << "The joined public key has been serialized" << std::endl;
}
encryption.cpp
#include <openfhe.h>
#include "config.hpp"
using namespace lbcrypto;
int main() {
// Parse the configuration
auto config = Config("config.json");
std::cout << config;
// Run each party sequentially
for ( auto& party: config.parties ) {
std::cout << "Running party " << party.id << std::endl;
// Deserialize the cryptocontext
CryptoContext<DCRTPoly> cryptoContext;
if (!Serial::DeserializeFromFile(config.cryptocontext, cryptoContext, SerType::BINARY)) {
std::cerr << "I cannot read serialization from " << config.cryptocontext << std::endl;
return 1;
}
std::cout << "The cryptocontext has been deserialized." << std::endl;
std::ifstream multKeyIStream("test/multkey.txt", std::ios::in | std::ios::binary);
if (!multKeyIStream.is_open()) {
std::cerr << "Cannot read serialization from " << std::endl;
std::exit(1);
}
if (!cryptoContext->DeserializeEvalMultKey(multKeyIStream, SerType::BINARY)) {
std::cerr << "Could not deserialize eval mult key file" << std::endl;
std::exit(1);
}
std::cout << "Deserialized eval mult keys" << '\n' << std::endl;
std::ifstream rotKeyIStream("test/rotkey.txt", std::ios::in | std::ios::binary);
if (!rotKeyIStream.is_open()) {
std::cerr << "Cannot read serialization from " << std::endl;
std::exit(1);
}
if (!cryptoContext->DeserializeEvalAutomorphismKey(rotKeyIStream, SerType::BINARY)) {
std::cerr << "Could not deserialize eval rot key file" << std::endl;
std::exit(1);
}
PublicKey<DCRTPoly> pk;
if (Serial::DeserializeFromFile(config.pk, pk, SerType::BINARY) == false) {
std::cerr << "Could not read public key" << std::endl;
return 1;
}
std::cout << "The public key has been deserialized." << std::endl;
Plaintext pt = cryptoContext->MakePackedPlaintext(party.values);
Ciphertext<DCRTPoly> ct = cryptoContext->Encrypt(pk, pt);
std::cout << "The plaintexts have been encrypted." << std::endl;
if (!Serial::SerializeToFile(party.ct, ct, SerType::BINARY)) {
std::cerr << "Error writing serialization of ciphertext to " << party.ct << std::endl;
return 1;
}
std::cout << "The ciphertext has been serialized." << std::endl;
}
}
I do not encounter the error when I manually disable the check in OpenFHE and install the altered version.
patch
diff --git a/src/pke/include/cryptocontext.h b/src/pke/include/cryptocontext.h
index 4302a6a..bd08c64 100644
--- a/src/pke/include/cryptocontext.h
+++ b/src/pke/include/cryptocontext.h
@@ -424,6 +424,7 @@ protected:
std::string errorMsg(std::string("Key is nullptr") + CALLER_INFO);
OPENFHE_THROW(errorMsg);
}
+ return;
if (Mismatched(key->GetCryptoContext())) {
std::string errorMsg(std::string("Key was not generated with the same crypto context") + CALLER_INFO);
OPENFHE_THROW(errorMsg);
What do I do wrong?
Cheers,
Romain