Open gogo9th opened 1 month ago
Hi,
I figured out another more concrete issue: the noise budgets of PhantomFHE ciphertexts seem to be actually lower than those of SEAL ciphertexts, even under the same crypto parameter setup. I found this issue because my software using PhantomFHE does not generate correct results, while everything works correctly when using the original SEAL library.
Below I create the minimal reproducible example code for this issue:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stdlib.h>
using namespace std;
#ifdef SEAL
#include "seal/seal.h"
using namespace seal;
#elif defined(PHANTOM)
#include "phantom.h"
using namespace phantom;
using namespace phantom::arith;
using namespace phantom::util;
#endif
int main()
{
vector<int> coeff_mod_list = {60, 60, 60, 60, 60, 60};
EncryptionParameters parms(scheme_type::bfv);
vector<Modulus> mod_list;
//if (poly_modulus_degree == 16384)
mod_list = CoeffModulus::Create(16384, coeff_mod_list);
//else
// mod_list = CoeffModulus::BFVDefault(poly_modulus_degree);
parms.set_poly_modulus_degree(16384);
parms.set_coeff_modulus(mod_list);
parms.set_plain_modulus(PlainModulus::Batching(16384, 22));
#if defined(SEAL) || defined(SEAL_PHANTOM)
SEALContext context(parms);
SecretKey sk;
PublicKey pk;
RelinKeys relin_keys;
GaloisKeys gal_keys;
KeyGenerator keygen(context);
Evaluator evaluator(context);
BatchEncoder batch_encoder(context);
keygen.create_public_key(pk);
sk = keygen.secret_key();
stringstream relin_stream, gal_stream;
keygen.create_relin_keys().save(relin_stream);
keygen.create_galois_keys().save(gal_stream);
relin_keys.load(context, relin_stream);
gal_keys.load(context, gal_stream);
Encryptor encryptor(context, pk);
encryptor.set_secret_key(sk); // set it up in the SEAL context
Decryptor decryptor = Decryptor(context, sk);
#elif defined(PHANTOM)
PhantomContext context(parms);
PhantomSecretKey sk(context);
PhantomPublicKey pk = sk.gen_publickey(context);
PhantomRelinKey relin_keys(sk.gen_relinkey(context));
PhantomGaloisKey gal_keys = sk.create_galois_keys(context);
PhantomBatchEncoder batch_encoder = PhantomBatchEncoder(context);
#endif
vector<uint64_t> vec(16384, 0);
#if defined(PHANTOM)
PhantomPlaintext pt;
PhantomCiphertext ct;
batch_encoder.encode(context, vec, pt);
sk.encrypt_symmetric(context, pt, ct);
#elif defined(SEAL)
Plaintext pt;
Ciphertext ct;
batch_encoder.encode(vec, pt);
encryptor.encrypt_symmetric(pt, ct);
#endif
for (int i = 0; i < 4; i++)
{ cout << "Changing multiplicative chain index from " << i << " -> " << i + 1 << endl;
#if defined(PHANTOM)
multiply_inplace(context, ct, ct);
relinearize_inplace(context, ct, relin_keys);
mod_switch_to_next_inplace(context, ct);
#elif defined(SEAL)
evaluator.multiply_inplace(ct, ct);
evaluator.relinearize_inplace(ct, relin_keys);
evaluator.mod_switch_to_next_inplace(ct);
#endif
vector<uint64_t> ret_list;
//assert(this->is_debug);
#if defined(PHANTOM)
PhantomPlaintext pt;
sk.decrypt(context, ct, pt);
batch_encoder.decode(context, pt, ret_list);
#elif defined(SEAL)
Plaintext pt;
decryptor.decrypt(ct, pt);
batch_encoder.decode(pt, ret_list);
#endif
if (ret_list[0] != 0)
{ cout << "- A decryption error found at multiplicative chain index : " << i << endl;
exit(0);
}
}
cout << "4 multiplications done successfuly" << endl;
return 0;
}
I also attach the complete source code for this example: src.zip
This example assumes that you have installbed both SEAL and PhantomFHE libraries on your Ubuntu 22.04 (or higher) machine. You only need to run:
unzip src.zip
cd src/build
cmake .. --fresh -DSEAL=ON # To compile with the SEAL library
make -j
./main # The 5 consecutive cipher multiplications should work fine
cmake .. --fresh -DPHANTOM=ON # To compile with the PhantomFHE library
make -j
./main # Only 2 consecutive cipher multiplications will work and the results gets corrupted afterwards
It seems the code for evaluating the noise budget might be broken. I noticed this a while ago as well. I’ll work on fixing it soon.
Hi, I just got back from CCS 2024 and HE meetup, where Dan Boneh gave a keynote speech about the future of security, where he picked FHE as the first topic. There were also many papers on FHE. So your library is really important for the future of FHE.
Today I tested your update on secret key packing and it works fine. Thanks a lot. Now the only remaining issue is the noise budget issue... Now my application is good enough to demonstrate its speed enhancement by using PhantomFHE (although the correctness does not hold due to the noise budget issue). Hope this one can be also resolved soon :)
Thanks for testing the update. I’m glad to hear the secret key packing is working well.
I’m currently traveling for work and will be back early next month. I’ll fix the noise budget issue as soon as I return. In the meantime, my colleagues may be able to help.
Hi, I hope you had a wonderful trip. Just wonder if you had any chance to look into the bug fix...
Yes, I am working on this, the bug will be fixed soon (maybe today).
Hi,
At examples/serialization.cu:255, I inserted the following line:
cout << "Noise: " << secret_key.invariant_noise_budget(context, x_symmetric_cipher_load) << endl;
And if I run the example code, I get this output:
cipher noise budget is: 0
Actually, it seems that even for the unmodified serialization.cu file, the noise budgets are all 0:
Shouldn't we expect the noise budgets to be some positive numbers?