Rekeying transform at the server?

I have what I think is a silly question - but I wanted to ask just to make sure my intuition was correct. I think the following is not possible but can you please confirm, or suggest an approach?

I have a client A that uses Server A to run FHE circuits. I have a client B that uses Server B to run FHE circuits. Is there a way to have FHE server use transform keys to convert client A data into something that client B can read with client B keys? Without decrypting? ie. allow client A and client B to communicate data via FHE server without sharing keys, and without server decrypting - but only transforming? I hope my question is clear?


Hello @ronhume.

Sorry for the delay, we missed a bit your question.

So, if I understand you well, you want to turn data encrypted by A into a data “as if it would have been encrypted by B”? Why would you want to do something like that? Or, in other words, if you want to transfer encrypted data between A and B, there are much simpler solutions!

But I guess, if you call F the function which does:

  • the decryption function in FHE
  • which uses skA FHE-encrypted by skB

then calling F on enc_skA(x) would return enc_skB(x), since:

  • F decrypts
  • the decryption key is skA, so enc_skA is removed
  • but as it is in the FHE world, results is not x but enc_skB(x)

That’s more or less a bootstrapping, but with input and output keys which are different.

Thank you for that. Let me describe what I’m doing a bit more. I have two sets of machines each owned by different groups. Group A has key A, and Group B has key B. All Group A machines can speak with server A using Key A and all Group B machines speak with Server B using Key B. So each network is autonomous. And all works well.

What I would like to do is be able to send some data from network A encrypted using Key A, to network B (who does not have Key A). …without decrypting. Basically do an FHE transform of some kind to allow Client B to read the info using KeyB.

I may be over complicating this. So open to advice.

But consider for example if I am doing audio summing (additive homomorphism) on network A. I am mixing at the server some linear audio samples together to make a conference call. All clients on network A can send their audio to server A, server A sums the audio using additive HE, and returns the result to each client. I would like to send the resulting stream of sums also to network B so they can listen (but maybe they are not trusted the same way as Network A clients, so they have Key B, not key A. (perhaps they are administered by groups who have limited trust between them). Could I do an FHE transform on the data to convert it under FHE so that clients with key B can decrypt it?
My main requirement is that none of the “servers” can decrypt the data. Only the clients can encrypt or decrypt. I have this working between all key A endpoints, and all key B endpoints, but having issues with cross network trust while avoiding the decrypt/re-encrypt cycle at the server. I want to not “trust” the server from a data leakage / eavesdropping perspective.
Does this make any sense? Or am I making this WAY too complicated?
Sorry for the long explanation.

Having said all of that, I’m not quite sure I followed your explanation. I see the general approach, but I am still a bit confused.

If I read your response correctly, you are saying to take my data and encrypt with key A, then encrypt with key B. Then decrypt with keyA resulting in (through the magic of FHE) data encrypted only with keyB while having never been decrypted back to cleartext. Correct?

Any assistance is greatly appreciated.


So, if you do that, any data which is encrypted by A will be transformable into a data encrypted by KeyB. So, any data which is encrypted by A will be decryptable by B, is this ok in your setting?

You don’t want to use conventional symmetric crypto to send messages between A and B? Like AES?

Maybe you could just share the private FHE key between A and B?

Yes I have the impression that you take FHE for something which it’s not made for. You could have much lighter/faster schemes to exchange between A and B. Or, sharing key, if really A and B trust each other and will be able to decrypt the messages of each other.

No that’s fine, happy to help, but sorry I’m a bit lost as well, since you look maybe to over-engineer something here.

I said that, it would be possible to replace the PBS key (which is normally an encryption with the sk of the message sk) by a new kind of key (which would be an encryption with skB of the message skA), and it would do what you want. But, I say it in term of maths. Unless you want to go deep in Concrete and change the library/compiler, it’s really not easy to do something like that as a user.

Last but not least, a cryptographer here at Zama gave me another solution for you: use a keyswitch instead of a bootstrap. But if A and B are different users, to not leak to key of A to B, we need B to expose a public key and the keyswitch must happen on A side. Thanks to him.

Hope it helps!

You have been so helpful - thank you.

Yes I could use AES, as follows. Send data from client A to Server. Server does FHE calculation. Return result to Client A. Then client A decrypts result, and then re-sends to Client B using AES or other normal method.

But what I was trying to do was to take FHE result at the Server and make that result readable by client B under key B somehow directly.

So maybe I should change my question slightly to remove a bunch of details which may not be relevant.

Could I send data from Client A to FHE server, perform a calculation, and then do two things.

  1. send result back to client A who can decrypt under key A (easy), and
  2. keyswitch somehow so that this same FHE result can be sent to a client who does not have key A but has key B instead. (???)

I think #2 looks to be possible using either the method you proposed or the one that the cryptographer proposed.

I understand that your solution is possible with the math - but maybe not with concrete today.

Is keyswitch an exposed operation? Could I perhaps get a simple example to do this?

For example, client A calls circuit

def sum(a,b)
    return a+b

and result is then keyswitched so that the result can be sent to client B who decrypts it with Key B?

My intuition initially was that this was not possible, and I expected a polite “no you cant do that” answer from you guys. But maybe it is possible?

If an example is not available - maybe just a pointer to the correct APIs, and I could go digging?

In any case - thank you again. I appreciate the support.


It appears that my proposal is unsecure: from bsk = enc_skB(skA) and skB, it would be possible to get skA.

Maybe better to simplify your prototocol! A could use B’s public key (which corresponds to skB), to directly encrypt things that B would be able to decrypt

Ok thank you. Yes I think that is best. I was trying to avoid it. Specifically trying to avoid decrypt/compute/encrypt cycle. But may be best to keep it simple rather than trying to do keyswitch without decrypt.

Once again - thank you for spending time on this.

All the best,

1 Like