Collective key switching

Hello,

I am currently experimenting with the re-encryption in a multi party setup using CKKS scheme, the idea is to re-encrypt the ciphertext which was encrypted using the shared public key. The setup is the following:

Parties 1 and 2 and their corresponding secret shares of key pairs kp1 and kp2 are used to create the shared public key (SharedPubKey). The ciphertext ct1 is encrypted using the shared public key. The receiver has the key pair kp3 and provides its public key for the re-encryption process.

I tried to perform a re-encryption in a following way:

// Ciphertext
ct1 = cc->Encrypt(SharedPubKey, plaintext);

// Party 1
evalKey1 = cc->ReKeyGen(kp1.secretKey, kp3.publicKey);
REct1 = cc->ReEncrypt(ct1, evalKey1);

// Party 2
evalKey2 = cc->ReKeyGen(kp2.secretKey, kp3.publicKey);
REct2 = cc->ReEncrypt(REct1, evalKey2);

//Receiver
cc->Decrypt(kp3.secretKey, REct2, &Result);

but this results with an error saying that decryption cannot be done due to the high approximation error[1], which probably means that the procedure is not correct.

The crypto context parameters are: multDepth = 1, scaleFactorBits = 50 and batchSize = 64. Following functionalities are enabled: PKE, KEYSWITCH, PRE, LEVELEDSHE, ADVANCEDSHE, MULTIPARTY. I went through a similar post on this topic (proxy re-encryption using ckks) and unit tests for multi party, ckks and multiHopPRE.

I would appreciate any feedback on this matter.

Thanks

[1] src/pke/lib/encoding/ckkspackedencoding.cpp:515 The decryption failed because the approximation error is too high. Check the parameters.

EDIT:

just found in src/pke/include/cryptocontext.h:2368 MultipartyKeyGen(const PublicKey<Element> publicKey, bool makeSparse = false, bool fresh = false)
when creating keypair kp2 for the party 2, ‘fresh’ parameter should be set to true, in order for re-encryption to work in a multi party setup. Then, only party 2 would need to do the following:

// Party 2
evalKey2 = cc->ReKeyGen(kp2.secretKey, kp3.publicKey);
REct2 = cc->ReEncrypt(ct1, evalKey2);

// Receiver
cc->Decrypt(kp3.secretKey, REct2, &Result);

It is however then also possible to decrypt the ct1 using only kp2.secretKey.

@mpuskaric

Sounds like your issue/question was resolved based on your edit? I might be wrong. Can you confirm if that’s the case and if not I’ll float it to other members to see if they can help

@iquah
Thanks for the feedback, the issue regarding re-encryption has been resolved with the follow-up part.

However, I’m still wondering whether it is possible to perform a re-encryption process in the same way as a multi-party decryption, where each party computes a partial re-encryption, and fusion of the partial re-encryptions is done in the last step.

Would you mind making a new post for that question? That way it’ll ping the relevant people from the openfhe team :slight_smile:

Thank you!

@mpuskaric Could you clarify which of the following two scenarios you are asking about?

  1. Do re-encryption only (without refreshing the noise - switch from the shared key to another key)
  2. Do interactive bootstrapping (reset the noise and do key switching).

@ypolyakov I actually had the first scenario in mind when I wrote the post. Thanks

Hi @mpuskaric

Theoretically it is possible to do re-encryption using secret shares, but this is not currently supported by OpenFHE.

I am wondering why you prefer this approach over proxy re-encryption. In the PRE case, the distributed process is needed only during the generation of the re-encryption key (i.e., offline). Then the re-encryption of a ciphertext can be done using a single re-encryption operation (like key switching), i.e., the parties do not need to interact.

thanks @ypolyakov for the clarification.

I was trying to implement a workflow for the distributed re-encryption key generation, but so far without success. In case of a multi party setup, where KeyPair1 and KeyPair2 are used for generating shared keys, how the workflow for generating the re-encryption key should look like?
My understanding is that the first step is for both parties to run the RunKeyGen function using respective private keys and the receiver’s public key, but then there should be an additional step for creating a joint key, like with summation keys.
So far, I’ve looked in the UnitTestMultihopPRE.cpp, UnitTestPRE.cpp and UnitTestMultiparty.cpp files for possible answers. I am using a CKKS scheme.

I would appreciate any hint or a suggestion.

I believe you are asking about MultiAddEvalKeys. This function adds two evaluation keys, where the first polynomials are the same, and the second ones get added. Please search for examples with MultiAddEvalKeys, e.g., in threshold-fhe.cpp

Hi,

In threshold-fhe.cpp, party A generates key pair with KeyGen() then the other party uses MultipartyKeyGen(patyA.publickey) for generating joint public key .

Can i run KeyGen() algorithm for all party and then generate joint public key? I read the documantation but i could not find.
I tried this idea but i couldnt perform any operation on the parties’ public key.

Thank you.

The example in this post should help you achieve what you want.