// 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;
}
}
}