Proxy Re-Encryption (PRE) for BinFHE

I need to proxy re-encrypt the output of BinaryFHE in the following code. Can you help me understand how to do so?

auto cc = BinFHEContext();

cc.GenerateBinFHEContext(STD128);
auto sk = cc.KeyGen();
cc.BTKeyGen(sk);
auto output_to_be_proxy_reencrypted = cc.Encrypt(sk, c);

Is it even possible to proxy-reencrypt ciphertext form the BinFHE library?

Another way to ask this: is Key Switching enabled in the BinFHE library? If not, how can we implement this ourselves?

@lalalala Currently, we support PRE as a feature only for BGV, BFV, and CKKS. There, we repurpose the key switching functionality these schemes use for multiplication and rotations. It is correct that FHEW/TFHE bootstrapping can be used for PRE (as suggested in Gentry’s PhD dissertation on FHE) for the BinFHE schemes, but the API is not exposed to the user. It is a good idea. I will add an issue to add this functionality to OpenFHE v1.1.

Added the following issue: Add PRE for FHEW/TFHE · Issue #354 · openfheorg/openfhe-development · GitHub

I can see that the object LWEEncryptionScheme (in lwe-pke.cpp) implements key switching. I’ve exposed this library in my code.

However, when I attempt to perform key switching on one bit, I am failing to decrypt correctly. Is there an error in this library, or (more likely), can you see the error in my code?

BinFHEContext cc1 = BinFHEContext();
cc1.GenerateBinFHEContext(STD128);
LWEPrivateKey sk_alice = cc1.KeyGen();
cc1.BTKeyGen(sk_alice);

BinFHEContext cc2 = BinFHEContext();
cc2.GenerateBinFHEContext(STD128);
LWEPrivateKey sk_bob = cc2.KeyGen();

LWECiphertext original_ciphertext = cc1.Encrypt(sk_alice, 1);

LWEPlaintext attemptlalala;
cc1.Decrypt(sk_alice,original_ciphertext, &attemptlalala);
std::cout << "first lalala  = " << attemptlalala;

LWESwitchingKey switching_key = cc1.KeySwitchGen(sk_bob, sk_alice);

const std::shared_ptr<BinFHECryptoParams> binFHECryptoParams = cc1.GetParams();
const std::shared_ptr<LWECryptoParams> lwe_crypto_params = binFHECryptoParams->GetLWEParams();
const std::shared_ptr<LWEEncryptionScheme> lwe_encryption_scheme = cc1.GetLWEScheme();

LWECiphertext switched_ct = lwe_encryption_scheme->KeySwitch(lwe_crypto_params, switching_key, original_ciphertext);

My first question. Why are you creating two different binfhe cryptocontexts? This is unnecessary.

Currently KeySwitchGen and KeySwitch are tailored for the setup where we need to switch from N (RLWE ring dimension) to n (LWE lattice dimension). This behavior will need to be generalized to support key switching from any lattice dimension to any other lattice dimension (including the same one).

Note that PRE using key switching is not secure unless noise flooding is used (to erase prior error/secret key information). So extra noise would need to be added for this setup. I was referring to the bootstrapping-based approach that Gentry discussed in his PhD thesis.

I’ve added an issue to add PRE to FHEW/TFHE. I will let you know as soon as this change has been pushed to the dev branch.