// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.Research.SEAL.Tools; using System; using System.Collections.Generic; using System.Linq; namespace Microsoft.Research.SEAL { /// /// Generates matching secret key and public key. /// /// /// Generates matching secret key and public key. An existing KeyGenerator can /// also at any time be used to generate relinearization keys and Galois keys. /// Constructing a KeyGenerator requires only a SEALContext. /// public class KeyGenerator : NativeObject { /// /// Creates a KeyGenerator initialized with the specified SEALContext. /// /// /// Creates a KeyGenerator initialized with the specified . /// Dynamically allocated member variables are allocated from the global memory pool. /// /// The SEALContext /// if encryption parameters are not /// valid /// if context is null public KeyGenerator(SEALContext context) { if (null == context) throw new ArgumentNullException(nameof(context)); if (!context.ParametersSet) throw new ArgumentException("Encryption parameters are not set correctly"); NativeMethods.KeyGenerator_Create(context.NativePtr, out IntPtr ptr); NativePtr = ptr; } /// /// Creates an KeyGenerator instance initialized with the specified /// SEALContext and specified previously secret key. /// /// /// Creates an KeyGenerator instance initialized with the specified /// SEALContext and specified previously secret key. This can e.g. be used /// to increase the number of relinearization keys from what had earlier /// been generated, or to generate Galois keys in case they had not been /// generated earlier. /// /// The SEALContext /// A previously generated secret key /// if either context or secretKey /// are null /// if encryption parameters are not /// valid /// if secretKey or publicKey is not /// valid for encryption parameters public KeyGenerator(SEALContext context, SecretKey secretKey) { if (null == context) throw new ArgumentNullException(nameof(context)); if (null == secretKey) throw new ArgumentNullException(nameof(secretKey)); if (!context.ParametersSet) throw new ArgumentException("Encryption parameters are not set correctly"); if (!ValCheck.IsValidFor(secretKey, context)) throw new ArgumentException("Secret key is not valid for encryption parameters"); NativeMethods.KeyGenerator_Create(context.NativePtr, secretKey.NativePtr, out IntPtr ptr); NativePtr = ptr; } /// /// Generates and returns a public key. Every time this function is called, /// a new public key will be generated. /// public PublicKey PublicKey { get { NativeMethods.KeyGenerator_PublicKey(NativePtr, out IntPtr pubKeyPtr); PublicKey pubKey = new PublicKey(pubKeyPtr); return pubKey; } } /// /// Returns a copy of the secret key. /// public SecretKey SecretKey { get { NativeMethods.KeyGenerator_SecretKey(NativePtr, out IntPtr secretKeyPtr); SecretKey secretKey = new SecretKey(secretKeyPtr); return secretKey; } } /// /// Generates and returns relinearization keys. /// /// /// Generates and returns relinearization keys. This function returns /// relinearization keys in a fully expanded form and is meant to be used /// primarily for demo, testing, and debugging purposes. /// /// if the encryption /// parameters do not support keyswitching public RelinKeys RelinKeysLocal() { if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); NativeMethods.KeyGenerator_RelinKeys(NativePtr, false, out IntPtr relinKeysPtr); return new RelinKeys(relinKeysPtr); } /// /// Generates and returns relinearization keys as a serializable object. /// /// /// /// Generates and returns relinearization keys as a serializable object. /// /// /// Half of the key data is pseudo-randomly generated from a seed to reduce /// the object size. The resulting serializable object cannot be used /// directly and is meant to be serialized for the size reduction to have an /// impact. /// /// /// if the encryption /// parameters do not support keyswitching public Serializable RelinKeys() { if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); NativeMethods.KeyGenerator_RelinKeys(NativePtr, true, out IntPtr relinKeysPtr); RelinKeys relinKeys = new RelinKeys(relinKeysPtr); return new Serializable(relinKeys); } /// /// Generates and returns Galois keys. /// /// /// /// Generates and returns Galois keys. This function returns Galois keys in /// a fully expanded form and is meant to be used primarily for demo, testing, /// and debugging purposes. This function creates specific Galois keys that /// can be used to apply specific Galois automorphisms on encrypted data. The /// user needs to give as input a vector of Galois elements corresponding to /// the keys that are to be created. /// /// /// The Galois elements are odd integers in the interval [1, M-1], where /// M = 2*N, and N = PolyModulusDegree. Used with batching, a Galois element /// 3^i % M corresponds to a cyclic row rotation i steps to the left, and /// a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i /// steps to the right. The Galois element M-1 corresponds to a column rotation /// (row swap). In the polynomial view (not batching), a Galois automorphism by /// a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)). /// /// /// The Galois elements for which to generate keys /// if the encryption parameters /// do not support batching and scheme is SchemeType.BFV /// if the encryption /// parameters do not support keyswitching /// if the Galois elements are not valid public GaloisKeys GaloisKeysLocal(IEnumerable galoisElts) { if (null == galoisElts) throw new ArgumentNullException(nameof(galoisElts)); if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); uint[] galoisEltsArr = galoisElts.ToArray(); NativeMethods.KeyGenerator_GaloisKeysFromElts(NativePtr, (ulong)galoisEltsArr.Length, galoisEltsArr, false, out IntPtr galoisKeysPtr); return new GaloisKeys(galoisKeysPtr); } /// /// Generates and returns Galois keys as a serializable object. /// /// /// /// Generates and returns Galois keys as a serializable object. This function /// creates specific Galois keys that can be used to apply specific Galois /// automorphisms on encrypted data. The user needs to give as input a vector /// of Galois elements corresponding to the keys that are to be created. /// /// /// The Galois elements are odd integers in the interval [1, M-1], where /// M = 2*N, and N = PolyModulusDegree. Used with batching, a Galois element /// 3^i % M corresponds to a cyclic row rotation i steps to the left, and /// a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i /// steps to the right. The Galois element M-1 corresponds to a column rotation /// (row swap). In the polynomial view (not batching), a Galois automorphism by /// a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)). /// /// /// Half of the key data is pseudo-randomly generated from a seed to reduce /// the object size. The resulting serializable object cannot be used /// directly and is meant to be serialized for the size reduction to have an /// impact. /// /// /// The Galois elements for which to generate keys /// if galoisElts is null /// if the encryption parameters /// do not support batching and scheme is SchemeType.BFV /// if the encryption /// parameters do not support keyswitching /// if the Galois elements are not valid public Serializable GaloisKeys(IEnumerable galoisElts) { if (null == galoisElts) throw new ArgumentNullException(nameof(galoisElts)); if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); uint[] galoisEltsArr = galoisElts.ToArray(); NativeMethods.KeyGenerator_GaloisKeysFromElts(NativePtr, (ulong)galoisEltsArr.Length, galoisEltsArr, true, out IntPtr galoisKeysPtr); GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr); return new Serializable(galoisKeys); } /// /// Generates and returns Galois keys. /// /// /// Generates and returns Galois keys. This function returns Galois keys in /// a fully expanded form and is meant to be used primarily for demo, testing, /// and debugging purposes. The user needs to give as input a vector of desired /// Galois rotation step counts, where negative step counts correspond to /// rotations to the right and positive step counts correspond to rotations to /// the left. A step count of zero can be used to indicate a column rotation /// in the BFV scheme complex conjugation in the CKKS scheme. /// /// The rotation step counts for which to generate keys /// if steps is null /// if the encryption parameters /// do not support batching and scheme is SchemeType.BFV /// if the encryption /// parameters do not support keyswitching /// if the step counts are not valid public GaloisKeys GaloisKeysLocal(IEnumerable steps) { if (null == steps) throw new ArgumentNullException(nameof(steps)); if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); int[] stepsArr = steps.ToArray(); NativeMethods.KeyGenerator_GaloisKeysFromSteps(NativePtr, (ulong)stepsArr.Length, stepsArr, false, out IntPtr galoisKeysPtr); return new GaloisKeys(galoisKeysPtr); } /// /// Generates and returns Galois keys as a serializable object. /// /// /// /// Generates and returns Galois keys as a serializable object. This function /// creates specific Galois keys that can be used to apply specific Galois /// automorphisms on encrypted data. The user needs to give as input a vector /// of desired Galois rotation step counts, where negative step counts /// correspond to rotations to the right and positive step counts correspond /// to rotations to the left. A step count of zero can be used to indicate /// a column rotation in the BFV scheme complex conjugation in the CKKS scheme. /// /// /// Half of the key data is pseudo-randomly generated from a seed to reduce /// the object size. The resulting serializable object cannot be used /// directly and is meant to be serialized for the size reduction to have an /// impact. /// /// /// The rotation step counts for which to generate keys /// if steps is null /// if the encryption parameters /// do not support batching and scheme is SchemeType.BFV /// if the encryption /// parameters do not support keyswitching /// if the step counts are not valid public Serializable GaloisKeys(IEnumerable steps) { if (null == steps) throw new ArgumentNullException(nameof(steps)); if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); int[] stepsArr = steps.ToArray(); NativeMethods.KeyGenerator_GaloisKeysFromSteps(NativePtr, (ulong)stepsArr.Length, stepsArr, true, out IntPtr galoisKeysPtr); GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr); return new Serializable(galoisKeys); } /// /// Generates and returns Galois keys. /// /// /// Generates and returns Galois keys. This function returns Galois keys in /// a fully expanded form and is meant to be used primarily for demo, testing, /// and debugging purposes. This function creates logarithmically many (in /// degree of the polynomial modulus) Galois keys that is sufficient to apply /// any Galois automorphism (e.g. rotations) on encrypted data. Most users /// will want to use this overload of the function. /// /// if the encryption parameters /// do not support batching and scheme is SchemeType.BFV /// if the encryption /// parameters do not support keyswitching public GaloisKeys GaloisKeysLocal() { if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); NativeMethods.KeyGenerator_GaloisKeysAll(NativePtr, false, out IntPtr galoisKeysPtr); return new GaloisKeys(galoisKeysPtr); } /// /// Generates and returns Galois keys as a serializable object. /// /// /// /// Generates and returns Galois keys as a serializable object. This function /// creates logarithmically many (in degree of the polynomial modulus) Galois /// keys that is sufficient to apply any Galois automorphism (e.g. rotations) /// on encrypted data. Most users will want to use this overload of the function. /// /// /// Half of the key data is pseudo-randomly generated from a seed to reduce /// the object size. The resulting serializable object cannot be used /// directly and is meant to be serialized for the size reduction to have an /// impact. /// /// /// if the encryption parameters /// do not support batching and scheme is SchemeType.BFV /// if the encryption /// parameters do not support keyswitching public Serializable GaloisKeys() { if (!UsingKeyswitching()) throw new InvalidOperationException("Encryption parameters do not support keyswitching"); NativeMethods.KeyGenerator_GaloisKeysAll(NativePtr, true, out IntPtr galoisKeysPtr); GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr); return new Serializable(galoisKeys); } /// /// Destroy native object. /// protected override void DestroyNativeObject() { NativeMethods.KeyGenerator_Destroy(NativePtr); } internal bool UsingKeyswitching() { NativeMethods.KeyGenerator_ContextUsingKeyswitching(NativePtr, out bool result); return result; } } }