microsoft / SEAL

Microsoft SEAL is an easy-to-use and powerful homomorphic encryption library.
https://www.microsoft.com/en-us/research/group/cryptography-research/
MIT License
3.62k stars 709 forks source link

Individual Galois Key Creation #613

Closed irskid5 closed 1 year ago

irskid5 commented 1 year ago

Hey guys,

I have a question regarding the GaloisKeys object. When galois keys are created in SEAL, a GaloisKeys object of full size is always created. Even though we have the option of specifying which Galois elements we want to create, they are always inserted in this giant vector of vectors of public keys which allocates a lot of empty space for no reason. Looking at how CKKS ciphertexts are rotated in SEAL, I acknowledge that when we want to rotate using a galois element that doesn't exist (for example, galois elt corresponding to a positive 7 step), the function searches through the GaloisKeys object to find existing elts that it can use instead (for example, +8 + (-1) = +7 assuming +8 and -1 corresponding galois elts exist). However, we can always just collect the keys into a GaloisKeys object when time comes to perform this operation.

I am wondering why a whole vector needs to be created every time? It is possible to create a std::map<size_t, std::vector<seal::PublicKey>> seal::KeyGenerator::create_galois_key_map(const std::vector<uint32_t> &galois_elts, bool save_seed)) function that can reuse a lot of the existing code from seal::KeyGenerator::create_galois_keys. Unfortunately, I can't create such a function without modifying the SEAL source code since the seal::KeyGenerator::generate_one_kswitch_key function is private.

Any help would be appreciated!

fionser commented 1 year ago

You are freely copy the whole generate_one_kswitch_key function in your project (which I really do). This function is basically calling seal::util::encrypt_zero_symmetric (seal/util/rlwe.h)

fionser commented 1 year ago

Also “in this giant vector of vectors of public keys which allocates a lot of empty space for no reason.” Should not be the case. An empty std::vector<seal::PublicKey> will not allocates too many RAM because the seal::PublicKey is allocated when it is really constructed