Commit 1698a67c authored by Hoang Gia NGUYEN's avatar Hoang Gia NGUYEN
Browse files

testing

parent d8df7d47

Too many changes to show.

To preserve performance only 268 of 268+ files are displayed.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Text;
using Microsoft.Research.SEAL.Tools;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Stores a set of attributes (qualifiers) of a set of encryption parameters.
/// </summary>
///
/// <remarks>
/// Stores a set of attributes (qualifiers) of a set of encryption parameters.
/// These parameters are mainly used internally in various parts of the library,
/// e.g., to determine which algorithmic optimizations the current support.
/// The qualifiers are automatically created by the <see cref="SEALContext" />
/// class, silently passed on to classes such as <see cref="Encryptor" />,
/// <see cref="Evaluator" />, and <see cref="Decryptor" />, and the only way
/// to change them is by changing the encryption parameters themselves. In
/// other words, a user will never have to create their own instance of this
/// class, and in most cases never have to worry about it at all.
/// </remarks>
public class EncryptionParameterQualifiers : NativeObject
{
/// <summary>
/// Create a copy of an existing instance of EncryptionParameterQualifiers
/// </summary>
/// <param name="copy">Original object to copy</param>
public EncryptionParameterQualifiers(EncryptionParameterQualifiers copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.EPQ_Create(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Create an instance of EncryptionParameterQualifiers through a pointer to
/// a native object.
/// </summary>
/// <param name="ptr">Pointer to native EncryptionParameterQualifiers.</param>
/// <param name="owned">Whether this instance owns the native pointer.</param>
internal EncryptionParameterQualifiers(IntPtr ptr, bool owned = true)
: base(ptr, owned)
{
}
/// <summary>
/// If the encryption parameters are set in a way that is considered valid by SEAL,
/// the variable ParametersSet is set to true.
/// </summary>
public bool ParametersSet
{
get
{
NativeMethods.EPQ_ParametersSet(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// If the encryption parameters are set in a way that is considered valid by SEAL, return "success".
/// If the encryption parameters are set but not validated yet, return "none".
/// Otherwise, return a brief reason.
/// </summary>
public string ParametersErrorName()
{
NativeMethods.EPQ_ParameterErrorName(NativePtr, null, out ulong length);
StringBuilder buffer = new StringBuilder(checked((int)length));
NativeMethods.EPQ_ParameterErrorName(NativePtr, buffer, out length);
return buffer.ToString();
}
/// <summary>
/// If the encryption parameters are set in a way that is considered valid by SEAL, return "valid".
/// Otherwise, return a comprehensive reason.
/// </summary>
public string ParametersErrorMessage()
{
NativeMethods.EPQ_ParameterErrorMessage(NativePtr, null, out ulong length);
StringBuilder buffer = new StringBuilder(checked((int)length));
NativeMethods.EPQ_ParameterErrorMessage(NativePtr, buffer, out length);
return buffer.ToString();
}
/// <summary>
/// Tells whether FFT can be used for polynomial multiplication.
/// </summary>
///
/// <remarks>
/// Tells whether FFT can be used for polynomial multiplication. If the polynomial modulus
/// is of the form X^N+1, where N is a power of two, then FFT can be used for fast
/// multiplication of polynomials modulo the polynomial modulus. In this case the
/// variable UsingFFT will be set to true. However, currently Microsoft SEAL requires this
/// to be the case for the parameters to be valid. Therefore, ParametersSet can only
/// be true if UsingFFT is true.
/// </remarks>
public bool UsingFFT
{
get
{
NativeMethods.EPQ_UsingFFT(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Tells whether NTT can be used for polynomial multiplication.
/// </summary>
///
/// <remarks>
/// Tells whether NTT can be used for polynomial multiplication. If the primes in the
/// coefficient modulus are congruent to 1 modulo 2N, where X^N+1 is the polynomial
/// modulus and N is a power of two, then the number-theoretic transform (NTT) can be
/// used for fast multiplications of polynomials modulo the polynomial modulus and
/// coefficient modulus.In this case the variable UsingNTT will be set to true. However,
/// currently Microsoft SEAL requires this to be the case for the parameters to be valid.
/// Therefore, ParametersSet can only be true if UsingNTT is true.
/// </remarks>
public bool UsingNTT
{
get
{
NativeMethods.EPQ_UsingNTT(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Tells whether batching is supported by the encryption parameters.
/// </summary>
///
/// <remarks>
/// Tells whether batching is supported by the encryption parameters. If the plaintext
/// modulus is congruent to 1 modulo 2N, where X^N+1 is the polynomial modulus and N is
/// a power of two, then it is possible to use the BatchEncoder class to view plaintext
/// elements as 2-by-(N/2) matrices of integers modulo the plaintext modulus.This is
/// called batching, and allows the user to operate on the matrix elements(slots) in
/// a SIMD fashion, and rotate the matrix rows and columns.When the computation is
/// easily vectorizable, using batching can yield a huge performance boost.If the
/// encryption parameters support batching, the variable UsingBatching is set to true.
/// </remarks>
public bool UsingBatching
{
get
{
NativeMethods.EPQ_UsingBatching(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Tells whether fast plain lift is supported by the encryption parameters.
/// </summary>
///
/// <remarks>
/// Tells whether fast plain lift is supported by the encryption parameters. A certain
/// performance optimization in multiplication of a ciphertext by a plaintext
/// (Evaluator.MultiplyPlain) and in transforming a plaintext element to NTT domain
/// (Evaluator.TransformToNTT) can be used when the plaintext modulus is smaller than
/// each prime in the coefficient modulus. In this case the variable UsingFastPlainLift
/// is set to true.
/// </remarks>
public bool UsingFastPlainLift
{
get
{
NativeMethods.EPQ_UsingFastPlainLift(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Tells whether the coefficient modulus consists of a set of primes that are in
/// decreasing order.
/// </summary>
///
/// <remarks>
/// Tells whether the coefficient modulus consists of a set of primes that are in
/// decreasing order. If this is true, certain modular reductions in base conversion
/// can be omitted, improving performance.
/// </remarks>
public bool UsingDescendingModulusChain
{
get
{
NativeMethods.EPQ_UsingDescendingModulusChain(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Tells whether the encryption parameters are secure based on the standard
/// parameters from HomomorphicEncryption.org security standard.
/// </summary>
public SecLevelType SecLevel
{
get
{
NativeMethods.EPQ_SecLevel(NativePtr, out int result);
return (SecLevelType)result;
}
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.EPQ_Destroy(NativePtr);
}
}
}
\ No newline at end of file
// 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.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Describes the type of encryption scheme to be used.
/// </summary>
public enum SchemeType : byte
{
/// <summary>
/// No scheme set; cannot be used for encryption
/// </summary>
None = 0x0,
/// <summary>
/// Brakerski/Fan-Vercauteren scheme
/// </summary>
BFV = 0x1,
/// <summary>
/// Cheon-Kim-Kim-Song scheme
/// </summary>
CKKS = 0x2
}
/// <summary>
/// Represents the user-customizable encryption scheme settings.
/// </summary>
/// <remarks>
/// <para>
/// Represents user-customizable encryption scheme settings. The parameters (most
/// importantly PolyModulus, CoeffModulus, PlainModulus) significantly affect the
/// performance, capabilities, and security of the encryption scheme. Once an
/// instance of EncryptionParameters is populated with appropriate parameters, it
/// can be used to create an instance of the <see cref="SEALContext" /> class,
/// which verifies the validity of the parameters, and performs necessary
/// pre-computations.
/// </para>
/// <para>
/// Picking appropriate encryption parameters is essential to enable a particular
/// application while balancing performance and security. Some encryption settings
/// will not allow some inputs (e.g. attempting to encrypt a polynomial with more
/// coefficients than PolyModulus or larger coefficients than PlainModulus) or
/// support the desired computations (with noise growing too fast due to too large
/// PlainModulus and too small CoeffModulus).
/// </para>
/// <para>
/// The EncryptionParameters class maintains at all times a 256-bit hash of the
/// currently set encryption parameters called the ParmsId. This hash acts as
/// a unique identifier of the encryption parameters and is used by all further
/// objects created for these encryption parameters. The ParmsId is not intended
/// to be directly modified by the user but is used internally for pre-computation
/// data lookup and input validity checks. In modulus switching the user can use
/// the ParmsId to keep track of the chain of encryption parameters. The ParmsId is
/// not exposed in the public API of EncryptionParameters, but can be accessed
/// through the <see cref="SEALContext.ContextData" /> class once the SEALContext
/// has been created.
/// </para>
/// <para>
/// In general, reading from EncryptionParameters is thread-safe, while mutating
/// is not.
/// </para>
/// <para>
/// Choosing inappropriate encryption parameters may lead to an encryption scheme
/// that is not secure, does not perform well, and/or does not support the input
/// and computation of the desired application. We highly recommend consulting an
/// expert in RLWE-based encryption when selecting parameters, as this is where
/// inexperienced users seem to most often make critical mistakes.
/// </para>
/// </remarks>
public class EncryptionParameters : NativeObject, IEquatable<EncryptionParameters>
{
/// <summary>
/// Creates an empty set of encryption parameters.
/// </summary>
///
/// <param name="scheme">Scheme for the encryption parameters</param>
public EncryptionParameters(SchemeType scheme = SchemeType.None)
{
NativeMethods.EncParams_Create((byte)scheme, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates an empty set of encryption parameters.
/// </summary>
/// <param name="scheme">Scheme for the encryption parameters</param>
/// <exception cref="ArgumentException">if scheme is not supported</exception>
public EncryptionParameters(byte scheme)
{
NativeMethods.EncParams_Create(scheme, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a copy of a given instance of EncryptionParameters.
/// </summary>
/// <param name="copy">The EncryptionParameters to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public EncryptionParameters(EncryptionParameters copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.EncParams_Create(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Create an instance of Encryption Parameters through a pointer to a
/// native object.
/// </summary>
/// <param name="ptr">Native encryption parameters</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal EncryptionParameters(IntPtr ptr, bool owned = true)
: base(ptr, owned)
{
}
/// <summary>
/// Overwrites the EncryptionParameters instance with a copy of a given
/// instance.
/// </summary>
/// <param name="assign">The EncryptionParameters to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(EncryptionParameters assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.EncParams_Set(NativePtr, assign.NativePtr);
}
/// <summary>
/// Returns or Sets the degree of the polynomial modulus parameter.
/// </summary>
/// <remarks>
/// Sets the degree of the polynomial modulus parameter to the specified value.
/// The polynomial modulus directly affects the number of coefficients in plaintext
/// polynomials, the size of ciphertext elements, the computational performance of
/// the scheme (bigger is worse), and the security level(bigger is better). In SEAL
/// the degree of the polynomial modulus must be a power of 2 (e.g. 1024, 2048, 4096,
/// 8192, 16384, or 32768).
/// </remarks>
public ulong PolyModulusDegree
{
get
{
NativeMethods.EncParams_GetPolyModulusDegree(NativePtr, out ulong result);
return result;
}
set
{
NativeMethods.EncParams_SetPolyModulusDegree(NativePtr, value);
}
}
/// <summary>
/// Get a copy of the currently set coefficient modulus parameter, or
/// set the coefficient modulus parameter.
/// </summary>
/// <remarks>
/// When setting:
/// Sets the coefficient modulus parameter. The coefficient modulus consists of a list
/// of distinct prime numbers, and is represented by a list of <see cref="Modulus" />
/// objects. The coefficient modulus directly affects the size of ciphertext elements,
/// the amount of computation that the scheme can perform (bigger is better), and the
/// security level (bigger is worse). In Microsoft SEAL each of the prime numbers in
/// the coefficient modulus must be at most 60 bits, and must be congruent to 1 modulo
/// 2*PolyModulusDegree.
/// </remarks>
/// <exception cref="ArgumentNullException">if the value being set is null</exception>
/// <exception cref="ArgumentException">if the value being set is invalid</exception>
public IEnumerable<Modulus> CoeffModulus
{
get
{
ulong length = 0;
NativeMethods.EncParams_GetCoeffModulus(NativePtr, ref length, null);
IntPtr[] coeffArray = new IntPtr[length];
NativeMethods.EncParams_GetCoeffModulus(NativePtr, ref length, coeffArray);
List<Modulus> result = new List<Modulus>(checked((int)length));
foreach(IntPtr sm in coeffArray)
{
result.Add(new Modulus(sm));
}
return result;
}
set
{
if (null == value)
throw new ArgumentNullException(nameof(value));
IntPtr[] coeffArray = value.Select(sm => sm.NativePtr).ToArray();
NativeMethods.EncParams_SetCoeffModulus(NativePtr, (ulong)coeffArray.LongLength, coeffArray);
}
}
/// <summary>
/// Get a copy of the currently set plaintext modulus parameter, or
/// set the plaintext modulus parameter.
/// </summary>
/// <remarks>
/// When setting:
/// Sets the plaintext modulus parameter. The plaintext modulus is an integer modulus
/// represented by the <see cref="Modulus" /> class. The plaintext modulus determines
/// the largest coefficient that plaintext polynomials can represent. It also affects the
/// amount of computation that the scheme can perform (bigger is worse). In Microsoft SEAL
/// the plaintext modulus can be at most 60 bits long, but can otherwise be any integer.
/// Note, however, that some features (e.g. batching) require the plaintext modulus to be
/// of a particular form.
/// </remarks>
/// <exception cref="ArgumentNullException">if the value being set is null</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
public Modulus PlainModulus
{
get
{
NativeMethods.EncParams_GetPlainModulus(NativePtr, out IntPtr ptr);
Modulus sm = new Modulus(ptr, owned: false);
return sm;
}
set
{
NativeMethods.EncParams_SetPlainModulus(NativePtr, value.NativePtr);
}
}
/// <summary>
/// Sets the plaintext modulus parameter.
/// </summary>
/// <remarks>
/// Sets the plaintext modulus parameter. The plaintext modulus is an integer modulus
/// represented by the <see cref="Modulus" /> class. This method instead takes
/// a ulong and automatically creates the Modulus object. The plaintext modulus
/// determines the largest coefficient that plaintext polynomials can represent. It also
/// affects the amount of computation that the scheme can perform (bigger is worse). In
/// Microsoft SEAL the plaintext modulus can be at most 60 bits long, but can otherwise
/// be any integer. Note, however, that some features (e.g. batching) require the
/// plaintext modulus to be of a particular form.
/// </remarks>
/// <param name="plainModulus">The new plaintext modulus</param>
/// <exception cref="InvalidOperationException">if scheme is not CKKS</exception>
public void SetPlainModulus(ulong plainModulus)
{
NativeMethods.EncParams_SetPlainModulus(NativePtr, plainModulus);
}
/// <summary>
/// Returns the encryption scheme type.
/// </summary>
public SchemeType Scheme
{
get
{
NativeMethods.EncParams_GetScheme(NativePtr, out byte scheme);
return (SchemeType)scheme;
}
}
/// <summary>
/// Returns an upper bound on the size of the EncryptionParameters, as if
/// it was written to an output stream.
/// </summary>
/// <param name="comprMode">The compression mode</param>
/// <exception cref="ArgumentException">if the compression mode is not
/// supported</exception>
/// <exception cref="InvalidOperationException">if the size does not fit in
/// the return type</exception>
public long SaveSize(ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
NativeMethods.EncParams_SaveSize(
NativePtr, (byte)comprModeValue, out long outBytes);
return outBytes;
}
/// <summary>Saves the EncryptionParameters to an output stream.</summary>
/// <remarks>
/// Saves the EncryptionParameters to an output stream. The output is in
/// binary format and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the EncryptionParameters to</param>
/// <param name="comprMode">The desired compression mode</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support writing, or if compression mode is not supported</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved
/// is invalid, or if compression failed</exception>
public long Save(Stream stream, ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
return Serialization.Save(
(byte[] outptr, ulong size, byte cm, out long outBytes) =>
NativeMethods.EncParams_Save(NativePtr, outptr, size,
cm, out outBytes),
SaveSize(comprModeValue), comprModeValue, stream);
}
/// <summary>
/// Loads an EncryptionParameters from an input stream overwriting the
/// current EncryptionParameters.
/// </summary>
/// <param name="stream">The stream to load the EncryptionParameters from</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long Load(Stream stream)
{
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.EncParams_Load(NativePtr, outptr, size,
out outBytes),
stream);
}
/// <summary>
/// Returns the ParmsId of the current parameters. This function is intended
/// for internal use.
/// </summary>
internal ParmsId ParmsId
{
get
{
ParmsId id = new ParmsId();
NativeMethods.EncParams_GetParmsId(NativePtr, id.Block);
return id;
}
}
/// <summary>
/// Compares a given set of encryption parameters to the current set of
/// encryption parameters.
/// </summary>
/// <remarks>
/// Compares a given set of encryption parameters to the current set of encryption
/// parameters. The comparison is performed by comparing hash blocks of the parameter
/// sets rather than comparing the parameters individually.
/// </remarks>
/// <param name="obj">The EncryptionParameters to compare against</param>
public override bool Equals(object obj)
{
EncryptionParameters encParams = obj as EncryptionParameters;
return Equals(encParams);
}
/// <summary>
/// Returns a hash-code based on the EncryptionParameters.
/// </summary>
public override int GetHashCode()
{
return Utilities.ComputeArrayHashCode(ParmsId.Block);
}
#region IEquatable<EncryptionParameters> methods
/// <summary>
/// Compares a given set of encryption parameters to the current set of
/// encryption parameters.
/// </summary>
///
/// <remarks>
/// Compares a given set of encryption parameters to the current set of encryption
/// parameters. The comparison is performed by comparing hash blocks of the parameter
/// sets rather than comparing the parameters individually.
/// </remarks>
/// <param name="other">The EncryptionParameters to compare against</param>
public bool Equals(EncryptionParameters other)
{
if (null == other)
return false;
NativeMethods.EncParams_Equals(NativePtr, other.NativePtr, out bool result);
return result;
}
#endregion
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.EncParams_Destroy(NativePtr);
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Encrypts Plaintext objects into Ciphertext objects.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts Plaintext objects into Ciphertext objects. Constructing an Encryptor
/// requires a SEALContext with valid encryption parameters, the public key and/or
/// the secret key. If an Encrytor is given a secret key, it supports symmetric-key
/// encryption. If an Encryptor is given a public key, it supports asymmetric-key
/// encryption.
/// </para>
/// <para>
/// Overloads
/// For the encrypt function we provide two overloads concerning the memory pool used in
/// allocations needed during the operation. In one overload the global memory pool is used
/// for this purpose, and in another overload the user can supply a MemoryPoolHandle
/// to to be used instead. This is to allow one single Encryptor to be used concurrently by
/// several threads without running into thread contention in allocations taking place during
/// operations. For example, one can share one single Encryptor across any number of threads,
/// but in each thread call the encrypt function by giving it a thread-local MemoryPoolHandle
/// to use. It is important for a developer to understand how this works to avoid unnecessary
/// performance bottlenecks.
/// </para>
/// <para>
/// NTT form
/// When using the BFV scheme (SchemeType.BFV), all plaintext and ciphertexts should
/// remain by default in the usual coefficient representation, i.e. not in NTT form.
/// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts
/// should remain by default in NTT form. We call these scheme-specific NTT states the
/// "default NTT form". Decryption requires the input ciphertexts to be in the default
/// NTT form, and will throw an exception if this is not the case.
/// </para>
/// </remarks>
public class Encryptor : NativeObject
{
/// <summary>
/// Creates an Encryptor instance initialized with the specified SEALContext,
/// public key, and/or secret key.
/// </summary>
/// <param name="context">The SEALContext</param>
/// <param name="publicKey">The public key</param>
/// <param name="secretKey">The secret key</param>
/// <exception cref="ArgumentNullException">if context is null</exception>
/// <exception cref="ArgumentException">if the context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="ArgumentException">if publicKey is not valid</exception>
/// <exception cref="ArgumentException">if secretKey is not null and not valid</exception>
public Encryptor(SEALContext context, PublicKey publicKey, SecretKey secretKey = null)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
if (!context.ParametersSet)
throw new ArgumentException("Encryption parameters are not set correctly");
if (!ValCheck.IsValidFor(publicKey, context))
throw new ArgumentException("Public key is not valid for encryption parameters");
if (null == secretKey)
{
NativeMethods.Encryptor_Create(
context.NativePtr, publicKey.NativePtr, IntPtr.Zero, out IntPtr ptr);
NativePtr = ptr;
}
else
{
if (!ValCheck.IsValidFor(secretKey, context))
throw new ArgumentException("Secret key is not valid for encryption parameters");
NativeMethods.Encryptor_Create(
context.NativePtr, publicKey.NativePtr, secretKey.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
}
/// <summary>
/// Creates an Encryptor instance initialized with the specified SEALContext
/// and secret key.
/// </summary>
/// <param name="context">The SEALContext</param>
/// <param name="secretKey">The secret key</param>
/// <exception cref="ArgumentNullException">if context is null</exception>
/// <exception cref="ArgumentException">if the context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="ArgumentException">if secretKey is not valid</exception>
public Encryptor(SEALContext context, SecretKey secretKey)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
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.Encryptor_Create(context.NativePtr, IntPtr.Zero, secretKey.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Give a new instance of public key.
/// </summary>
/// <param name="publicKey">The public key</param>
/// <exception cref="ArgumentException">if publicKey is not valid</exception>
public void SetPublicKey(PublicKey publicKey)
{
NativeMethods.Encryptor_SetPublicKey(NativePtr, publicKey.NativePtr);
}
/// <summary>
/// Give a new instance of secret key.
/// </summary>
/// <param name="secretKey">The secret key</param>
/// <exception cref="ArgumentException">if secretKey is not valid</exception>
public void SetSecretKey(SecretKey secretKey)
{
NativeMethods.Encryptor_SetSecretKey(NativePtr, secretKey.NativePtr);
}
/// <summary>
/// Encrypts a plaintext with the public key and stores the result in destination.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a plaintext with the public key and stores the result in destination.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to:
/// 1) in BFV, the highest (data) level in the modulus switching chain,
/// 2) in CKKS, the encryption parameters of the plaintext.
/// Dynamic memory allocations in the process are allocated from the memory
/// pool pointed to by the given MemoryPoolHandle.
/// </para>
/// </remarks>
/// <param name="plain">The plaintext to encrypt</param>
/// <param name="destination">The ciphertext to overwrite with the encrypted
/// plaintext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either plain or destination
/// are null</exception>
/// <exception cref="InvalidOperationException">if a public key is not
/// set</exception>
/// <exception cref="ArgumentException">if plain is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if plain is not in default NTT
/// form</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void Encrypt(
Plaintext plain, Ciphertext destination,
MemoryPoolHandle pool = null)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Encryptor_Encrypt(
NativePtr, plain.NativePtr, destination.NativePtr, poolHandle);
}
/// <summary>
/// Encrypts a zero plaintext with the public key and stores the result in
/// destination.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a zero plaintext with the public key and stores the result in
/// destination.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to
/// the given ParmsId. Dynamic memory allocations in the process are allocated
/// from the memory pool pointed to by the given MemoryPoolHandle.
/// </para>
/// </remarks>
/// <param name="parmsId">The ParmsId for the resulting ciphertext</param>
/// <param name="destination">The ciphertext to overwrite with the encrypted
/// plaintext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either parmsId or destination are
/// null</exception>
/// <exception cref="InvalidOperationException">if a public key is not set</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void EncryptZero(
ParmsId parmsId, Ciphertext destination,
MemoryPoolHandle pool = null)
{
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Encryptor_EncryptZero1(
NativePtr, parmsId.Block, destination.NativePtr, poolHandle);
}
/// <summary>
/// Encrypts a zero plaintext with the public key and stores the result in
/// destination.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a zero plaintext with the public key and stores the result in
/// destination.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to the
/// highest (data) level in the modulus switching chain. Dynamic memory allocations
/// in the process are allocated from the memory pool pointed to by the given
/// MemoryPoolHandle.
/// </para>
/// </remarks>
/// <param name="destination">The ciphertext to overwrite with the encrypted
/// plaintext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if destination is null</exception>
/// <exception cref="InvalidOperationException">if a public key is not set</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void EncryptZero(Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Encryptor_EncryptZero2(NativePtr, destination.NativePtr, poolHandle);
}
/// <summary>
/// Encrypts a plaintext with the secret key and stores the result in destination.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a plaintext with the secret key and stores the result in destination.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to:
/// 1) in BFV, the highest (data) level in the modulus switching chain,
/// 2) in CKKS, the encryption parameters of the plaintext.
/// Dynamic memory allocations in the process are allocated from the memory
/// pool pointed to by the given MemoryPoolHandle.
/// </para>
/// </remarks>
/// <param name="plain">The plaintext to encrypt</param>
/// <param name="destination">The ciphertext to overwrite with the encrypted
/// plaintext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either plain or destination are
/// null</exception>
/// <exception cref="InvalidOperationException">if a secret key is not set</exception>
/// <exception cref="ArgumentException">if plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if plain is not in default NTT form</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void EncryptSymmetric(
Plaintext plain, Ciphertext destination,
MemoryPoolHandle pool = null)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Encryptor_EncryptSymmetric(
NativePtr, plain.NativePtr, false, destination.NativePtr, poolHandle);
}
/// <summary>
/// Encrypts a zero plaintext with the secret key and stores the result in
/// destination.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a zero plaintext with the secret key and stores the result in
/// destination.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to the given
/// ParmsId. Dynamic memory allocations in the process are allocated from the
/// memory pool pointed to by the given MemoryPoolHandle.
/// </para>
/// </remarks>
/// <param name="parmsId">The ParmsId for the resulting ciphertext</param>
/// <param name="destination">The ciphertext to overwrite with the encrypted
/// plaintext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either parmsId or destination are
/// null</exception>
/// <exception cref="InvalidOperationException">if a secret key is not set</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void EncryptZeroSymmetric(
ParmsId parmsId, Ciphertext destination,
MemoryPoolHandle pool = null)
{
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Encryptor_EncryptZeroSymmetric1(
NativePtr, parmsId.Block, false, destination.NativePtr, poolHandle);
}
/// <summary>
/// Encrypts a zero plaintext with the secret key and stores the result in
/// destination.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a zero plaintext with the secret key and stores the result in
/// destination.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to the
/// highest (data) level in the modulus switching chain. Dynamic memory allocations
/// in the process are allocated from the memory pool pointed to by the given
/// MemoryPoolHandle.
/// </para>
/// </remarks>
/// <param name="destination">The ciphertext to overwrite with the encrypted
/// plaintext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if destination is null</exception>
/// <exception cref="InvalidOperationException">if a secret key is not set</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void EncryptZeroSymmetric(
Ciphertext destination,
MemoryPoolHandle pool = null)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Encryptor_EncryptZeroSymmetric2(
NativePtr, false, destination.NativePtr, poolHandle);
}
/// <summary>
/// Encrypts a plaintext with the secret key and returns the ciphertext as
/// a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a plaintext with the secret key and returns the ciphertext as
/// a serializable object.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to:
/// 1) in BFV, the highest (data) level in the modulus switching chain,
/// 2) in CKKS, the encryption parameters of the plaintext.
/// Dynamic memory allocations in the process are allocated from the memory
/// pool pointed to by the given MemoryPoolHandle.
/// </para>
/// <para>
/// Half of the ciphertext 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.
/// </para>
/// </remarks>
/// <param name="plain">The plaintext to encrypt</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="InvalidOperationException">if a secret key is not set</exception>
/// <exception cref="ArgumentException">if plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if plain is not in default NTT
/// form</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Serializable<Ciphertext> EncryptSymmetric(
Plaintext plain,
MemoryPoolHandle pool = null)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
Ciphertext destination = new Ciphertext();
NativeMethods.Encryptor_EncryptSymmetric(
NativePtr, plain.NativePtr, true, destination.NativePtr, poolHandle);
return new Serializable<Ciphertext>(destination);
}
/// <summary>
/// Encrypts a zero plaintext with the secret key and returns the ciphertext
/// as a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a zero plaintext with the secret key and returns the ciphertext
/// as a serializable object.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to
/// the given ParmsId. Dynamic memory allocations in the process are allocated
/// from the memory pool pointed to by the given MemoryPoolHandle.
/// </para>
/// <para>
/// Half of the ciphertext 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.
/// </para>
/// </remarks>
/// <param name="parmsId">The ParmsId for the resulting ciphertext</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory
/// pool</param>
/// <exception cref="ArgumentNullException">if parmsId is null</exception>
/// <exception cref="InvalidOperationException">if a secret key is not
/// set</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Serializable<Ciphertext> EncryptZeroSymmetric(
ParmsId parmsId,
MemoryPoolHandle pool = null)
{
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
Ciphertext destination = new Ciphertext();
NativeMethods.Encryptor_EncryptZeroSymmetric1(
NativePtr, parmsId.Block, true, destination.NativePtr, poolHandle);
return new Serializable<Ciphertext>(destination);
}
/// <summary>
/// Encrypts a zero plaintext with the secret key and returns the ciphertext
/// as a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// Encrypts a zero plaintext with the secret key and returns the ciphertext
/// as a serializable object.
/// </para>
/// <para>
/// The encryption parameters for the resulting ciphertext correspond to the
/// highest (data) level in the modulus switching chain. Dynamic memory
/// allocations in the process are allocated from the memory pool pointed to
/// by the given MemoryPoolHandle.
/// </para>
/// <para>
/// Half of the ciphertext 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.
/// </para>
/// </remarks>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory
/// pool</param>
/// <exception cref="InvalidOperationException">if a secret key is not
/// set</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Serializable<Ciphertext> EncryptZeroSymmetric(MemoryPoolHandle pool = null)
{
IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
Ciphertext destination = new Ciphertext();
NativeMethods.Encryptor_EncryptZeroSymmetric2(
NativePtr, true, destination.NativePtr, poolHandle);
return new Serializable<Ciphertext>(destination);
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.Encryptor_Destroy(NativePtr);
}
}
}
// 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;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Provides operations on ciphertexts.
/// </summary>
///
/// <remarks>
/// <para>
/// Provides operations on ciphertexts. Due to the properties of the encryption scheme,
/// the arithmetic operations pass through the encryption layer to the underlying plaintext,
/// changing it according to the type of the operation. Since the plaintext elements are
/// fundamentally polynomials in the polynomial quotient ring Z_T[x]/(X^N+1), where T is
/// the plaintext modulus and X^N+1 is the polynomial modulus, this is the ring where the
/// arithmetic operations will take place. BatchEncoder (batching) provider an alternative
/// possibly more convenient view of the plaintext elements as 2-by-(N2/2) matrices of
/// integers modulo the plaintext modulus. In the batching view the arithmetic operations
/// act on the matrices element-wise. Some of the operations only apply in the batching
/// view, such as matrix row and column rotations. Other operations such as relinearization
/// have no semantic meaning but are necessary for performance reasons.
/// </para>
/// <para>
/// Arithmetic Operations
/// The core operations are arithmetic operations, in particular multiplication and addition
/// of ciphertexts. In addition to these, we also provide negation, subtraction, squaring,
/// exponentiation, and multiplication and addition of several ciphertexts for convenience.
/// in many cases some of the inputs to a computation are plaintext elements rather than
/// ciphertexts. For this we provide fast "plain" operations: plain addition, plain subtraction,
/// and plain multiplication.
/// </para>
/// <para>
/// Relinearization
/// One of the most important non-arithmetic operations is relinearization, which takes
/// as input a ciphertext of size K+1 and relinearization keys (at least K-1 keys are needed),
/// and changes the size of the ciphertext down to 2 (minimum size). For most use-cases only
/// one relinearization key suffices, in which case relinearization should be performed after
/// every multiplication. Homomorphic multiplication of ciphertexts of size K+1 and L+1
/// outputs a ciphertext of size K+L+1, and the computational cost of multiplication is
/// proportional to K*L. Plain multiplication and addition operations of any type do not
/// change the size. Relinearization requires relinearization keys to have been generated.
/// </para>
/// <para>
/// Rotations
/// When batching is enabled, we provide operations for rotating the plaintext matrix rows
/// cyclically left or right, and for rotating the columns (swapping the rows). Rotations
/// require Galois keys to have been generated.
/// </para>
/// <para>
/// Other Operations
/// We also provide operations for transforming ciphertexts to NTT form and back, and for
/// transforming plaintext polynomials to NTT form. These can be used in a very fast plain
/// multiplication variant, that assumes the inputs to be in NTT form. Since the NTT has to
/// be done in any case in plain multiplication, this function can be used when e.g. one
/// plaintext input is used in several plain multiplication, and transforming it several
/// times would not make sense.
/// </para>
/// <para>
/// NTT form
/// When using the BFV scheme (SchemeType.BFV), all plaintexts and ciphertexts should
/// remain by default in the usual coefficient representation, i.e., not in NTT form.
/// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts
/// should remain by default in NTT form. We call these scheme-specific NTT states the
/// "default NTT form". Some functions, such as add, work even if the inputs are not in
/// the default state, but others, such as multiply, will throw an exception. The output
/// of all evaluation functions will be in the same state as the input(s), with the
/// exception of the TransformToNTT and TransformFromNTT functions, which change the
/// state. Ideally, unless these two functions are called, all other functions should
/// "just work".
/// </para>
/// </remarks>
/// <see cref="EncryptionParameters"/> for more details on encryption parameters.
/// <see cref="BatchEncoder"/> for more details on batching
/// <see cref="RelinKeys"/> for more details on relinearization keys.
/// <see cref="GaloisKeys"/> for more details on Galois keys.
public class Evaluator : NativeObject
{
/// <summary>
/// Creates an Evaluator instance initialized with the specified SEALContext.
/// </summary>
///
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if context is null</exception>
/// <exception cref="ArgumentException">if the context is not set or encryption
/// parameters are not valid</exception>
public Evaluator(SEALContext context)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
if (!context.ParametersSet)
throw new ArgumentException("Encryption parameters are not set correctly");
NativeMethods.Evaluator_Create(context.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Negates a ciphertext.
/// </summary>
///
/// <param name="encrypted">The ciphertext to negate</param>
/// <exception cref="ArgumentNullException">if encrypted is null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void NegateInplace(Ciphertext encrypted)
{
Negate(encrypted, destination: encrypted);
}
/// <summary>
/// Negates a ciphertext and stores the result in the destination parameter.
/// </summary>
/// <param name="encrypted">The ciphertext to negate</param>
/// <param name="destination">The ciphertext to overwrite with the negated result</param>
/// <exception cref="ArgumentNullException">if either encrypted or destionation are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Negate(Ciphertext encrypted, Ciphertext destination)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_Negate(NativePtr, encrypted.NativePtr, destination.NativePtr);
}
/// <summary>
/// Adds two ciphertexts.
/// </summary>
/// <remarks>
/// This function adds together encrypted1 and encrypted2 and stores the result in encrypted1.
/// </remarks>
/// <param name="encrypted1">The first ciphertext to add</param>
/// <param name="encrypted2">The second ciphertext to add</param>
/// <exception cref="ArgumentNullException">if either encrypted1 or encrypted2 are null</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not valid for
/// the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 are in different
/// NTT forms</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 have different scale</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void AddInplace(Ciphertext encrypted1, Ciphertext encrypted2)
{
Add(encrypted1, encrypted2, destination: encrypted1);
}
/// <summary>
/// Adds two ciphertexts.
/// </summary>
/// <remarks>
/// This function adds together encrypted1 and encrypted2 and stores the result in the destination
/// parameter.
/// </remarks>
/// <param name="encrypted1">The first ciphertext to add</param>
/// <param name="encrypted2">The second ciphertext to add</param>
/// <param name="destination">The ciphertext to overwrite with the addition result</param>
/// <exception cref="ArgumentNullException">if either encrypted1, encrypted2 or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not valid for
/// the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 are in different
/// NTT forms</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 have different scale</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Add(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination)
{
if (null == encrypted1)
throw new ArgumentNullException(nameof(encrypted1));
if (null == encrypted2)
throw new ArgumentNullException(nameof(encrypted2));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_Add(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr);
}
/// <summary>
/// Adds together a vector of ciphertexts and stores the result in the destination
/// parameter.
/// </summary>
/// <param name="encrypteds">The ciphertexts to add</param>
/// <param name="destination">The ciphertext to overwrite with the addition result</param>
/// <exception cref="ArgumentNullException">if either encrypteds or destination are null</exception>
/// <exception cref="ArgumentException">if encrypteds is empty</exception>
/// <exception cref="ArgumentException">if the encrypteds are not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypteds are in different NTT forms</exception>
/// <exception cref="ArgumentException">if encrypteds have different scale</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void AddMany(IEnumerable<Ciphertext> encrypteds, Ciphertext destination)
{
if (null == encrypteds)
throw new ArgumentNullException(nameof(encrypteds));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray();
NativeMethods.Evaluator_AddMany(NativePtr, (ulong)encarray.Length, encarray, destination.NativePtr);
}
/// <summary>
/// Subtracts two ciphertexts.
/// </summary>
/// <remarks>
/// This function computes the difference of encrypted1 and encrypted2, and stores the result in encrypted1.
/// </remarks>
/// <param name="encrypted1">The ciphertext to subtract from</param>
/// <param name="encrypted2">The ciphertext to subtract</param>
/// <exception cref="ArgumentNullException">if either encrypted1 or encrypted2 are null</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 are in different
/// NTT forms</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 have different scale</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void SubInplace(Ciphertext encrypted1, Ciphertext encrypted2)
{
Sub(encrypted1, encrypted2, destination: encrypted1);
}
/// <summary>
/// Subtracts two ciphertexts.
/// </summary>
/// <remarks>This function computes the difference of encrypted1 and encrypted2 and stores the result
/// in the destination parameter.
/// </remarks>
/// <param name="encrypted1">The ciphertext to subtract from</param>
/// <param name="encrypted2">The ciphertext to subtract</param>
/// <param name="destination">The ciphertext to overwrite with the subtraction result</param>
/// <exception cref="ArgumentNullException">if either encrypted1, encrypted2 or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 are in different
/// NTT forms</exception>
/// <exception cref="ArgumentException">if encrypted1 and encrypted2 have different scale</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Sub(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination)
{
if (null == encrypted1)
throw new ArgumentNullException(nameof(encrypted1));
if (null == encrypted2)
throw new ArgumentNullException(nameof(encrypted2));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_Sub(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr);
}
/// <summary>
/// Multiplies two ciphertexts.
/// </summary>
/// <remarks>This functions computes the product of encrypted1 and encrypted2 and stores the
/// result in encrypted1. Dynamic memory allocations in the process are allocated from the
/// memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted1">The first ciphertext to multiply</param>
/// <param name="encrypted2">The second ciphertext to multiply</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted1, encrypted2 are null</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not in the default
/// NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void MultiplyInplace(Ciphertext encrypted1, Ciphertext encrypted2,
MemoryPoolHandle pool = null)
{
Multiply(encrypted1, encrypted2, destination: encrypted1, pool: pool);
}
/// <summary>
/// Multiplies two ciphertexts.
/// </summary>
/// <remarks>
/// This functions computes the product of encrypted1 and encrypted2 and stores the result
/// in the destination parameter. Dynamic memory allocations in the process are allocated
/// from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted1">The first ciphertext to multiply</param>
/// <param name="encrypted2">The second ciphertext to multiply</param>
/// <param name="destination">The ciphertext to overwrite with the multiplication result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted1, encrypted2, destination are null</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted1 or encrypted2 is not in the default
/// NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Multiply(Ciphertext encrypted1, Ciphertext encrypted2,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted1)
throw new ArgumentNullException(nameof(encrypted1));
if (null == encrypted2)
throw new ArgumentNullException(nameof(encrypted2));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_Multiply(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Squares a ciphertext.
/// </summary>
/// <remarks>
/// This functions computes the square of encrypted. Dynamic memory allocations in the process
/// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to square</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void SquareInplace(Ciphertext encrypted, MemoryPoolHandle pool = null)
{
Square(encrypted, destination: encrypted, pool: pool);
}
/// <summary>
/// Squares a ciphertext.
/// </summary>
/// <remarks>
/// This functions computes the square of encrypted and stores the result in the destination
/// parameter. Dynamic memory allocations in the process are allocated from the memory pool
/// pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to square</param>
/// <param name="destination">The ciphertext to overwrite with the square</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, destination are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Square(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_Square(NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Relinearizes a ciphertext.
/// </summary>
/// <remarks>
/// This functions relinearizes encrypted, reducing its size down to 2. If the size
/// of encrypted is K+1, the given relinearization keys need to have size at least K-1.
/// Dynamic memory allocations in the process are allocated from the memory pool pointed
/// to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to relinearize</param>
/// <param name="relinKeys">The relinearization keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, relinKeys are null</exception>
/// <exception cref="ArgumentException">if encrypted or relinKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if relinKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if the size of relinKeys is too small</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RelinearizeInplace(Ciphertext encrypted, RelinKeys relinKeys,
MemoryPoolHandle pool = null)
{
Relinearize(encrypted, relinKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Relinearizes a ciphertext.
/// </summary>
/// <remarks>
/// This functions relinearizes encrypted, reducing its size down to 2, and stores the
/// result in the destination parameter. If the size of encrypted is K+1, the given
/// relinearization keys need to have size at least K-1. Dynamic memory allocations in the
/// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to relinearize</param>
/// <param name="relinKeys">The relinearization keys</param>
/// <param name="destination">The ciphertext to overwrite with the relinearized result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, relinKeys or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted or relinKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if relinKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if the size of relinKeys is too small</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Relinearize(Ciphertext encrypted, RelinKeys relinKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == relinKeys)
throw new ArgumentNullException(nameof(relinKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_Relinearize(
NativePtr, encrypted.NativePtr, relinKeys.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1} and stores the result in the destination parameter.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1} and stores the result in the destination parameter. Dynamic
/// memory allocations in the process are allocated from the memory pool pointed to by
/// the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="destination">The ciphertext to overwrite with the modulus switched result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if encrypted is already at lowest level</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ModSwitchToNext(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_ModSwitchToNext(
NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1}.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1}. Dynamic memory allocations in the process are allocated from
/// the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if encrypted is null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if encrypted is already at lowest level</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ModSwitchToNextInplace(Ciphertext encrypted, MemoryPoolHandle pool = null)
{
ModSwitchToNext(encrypted, destination: encrypted, pool: pool);
}
/// <summary>
/// Modulus switches an NTT transformed plaintext from modulo q_1...q_k down to modulo
/// q_1...q_{k-1}.
/// </summary>
/// <param name="plain">The plaintext to be switched to a smaller modulus</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="ArgumentException">if plain is not in NTT form</exception>
/// <exception cref="ArgumentException">if plain is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if plain is already at lowest level</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
public void ModSwitchToNextInplace(Plaintext plain)
{
ModSwitchToNext(plain, destination: plain);
}
/// <summary>
/// Modulus switches an NTT transformed plaintext from modulo q_1...q_k down to modulo
/// q_1...q_{k-1} and stores the result in the destination parameter.
/// </summary>
/// <param name="plain">The plaintext to be switched to a smaller modulus</param>
/// <param name="destination">destination The plaintext to overwrite with the modulus switched result</param>
/// <exception cref="ArgumentNullException">if either plain or destination are null</exception>
/// <exception cref="ArgumentException">if plain is not in NTT form</exception>
/// <exception cref="ArgumentException">if plain is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if plain is already at lowest level</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void ModSwitchToNext(Plaintext plain, Plaintext destination)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_ModSwitchToNext(NativePtr, plain.NativePtr, destination.NativePtr);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId. Dynamic memory allocations in
/// the process are allocated from the memory pool pointed to by the given
/// MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="parmsId">The target parmsId</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or parmsId are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is already at lower level in modulus chain
/// than the parameters corresponding to parmsId</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ModSwitchToInplace(Ciphertext encrypted, ParmsId parmsId, MemoryPoolHandle pool = null)
{
ModSwitchTo(encrypted, parmsId, destination: encrypted, pool: pool);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId and stores the result in the
/// destination parameter.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId and stores the result in the
/// destination parameter. Dynamic memory allocations in the process are allocated
/// from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="parmsId">The target parmsId</param>
/// <param name="destination">The ciphertext to overwrite with the modulus switched result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, parmsId or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is already at lower level in modulus chain
/// than the parameters corresponding to parmsId</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ModSwitchTo(Ciphertext encrypted, ParmsId parmsId, Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_ModSwitchTo(
NativePtr, encrypted.NativePtr, parmsId.Block, destination.NativePtr, poolPtr);
}
/// <summary>
/// Given an NTT transformed plaintext modulo q_1...q_k, this function switches the
/// modulus down until the parameters reach the given ParmsId.
/// </summary>
/// <param name="plain">The plaintext to be switched to a smaller modulus</param>
/// <param name="parmsId">The target parmsId</param>
/// <exception cref="ArgumentNullException">if either plain or parmsId is null</exception>
/// <exception cref="ArgumentException">if plain is not in NTT form</exception>
/// <exception cref="ArgumentException">if plain is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if plain is already at lower level in modulus chain
/// than the parameters corresponding to parmsId</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
public void ModSwitchToInplace(Plaintext plain, ParmsId parmsId)
{
ModSwitchTo(plain, parmsId, destination: plain);
}
/// <summary>
/// Given an NTT transformed plaintext modulo q_1...q_k, this function switches the
/// modulus down until the parameters reach the given ParmsId and stores the result in
/// the destination parameter.
/// </summary>
/// <param name="plain">The plaintext to be switched to a smaller modulus</param>
/// <param name="parmsId">The target parmsId</param>
/// <param name="destination">The plaintext to overwrite with the modulus switched result</param>
/// <exception cref="ArgumentNullException">if either plain, parmsId or destination are null</exception>
/// <exception cref="ArgumentException">if plain is not in NTT form</exception>
/// <exception cref="ArgumentException">if plain is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if plain is already at lower level in modulus chain
/// than the parameters corresponding to parmsId</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the scale is too
/// large for the new encryption parameters</exception>
public void ModSwitchTo(Plaintext plain, ParmsId parmsId,
Plaintext destination)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_ModSwitchTo(NativePtr, plain.NativePtr, parmsId.Block, destination.NativePtr);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1}, scales the message down accordingly, and stores the
/// result in the destination parameter.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1}, scales the message down accordingly, and stores the
/// result in the destination parameter. Dynamic memory allocations in the process
/// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="destination">The ciphertext to overwrite with the modulus switched result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or destination are null</exception>
/// <exception cref="ArgumentException">if the scheme is invalid for rescaling</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if encrypted is already at lowest level</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RescaleToNext(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_RescaleToNext(
NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1} and scales the message down accordingly.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down to q_1...q_{k-1} and scales the message down accordingly. Dynamic memory
/// allocations in the process are allocated from the memory pool pointed to by the
/// given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if encrypted is null</exception>
/// <exception cref="ArgumentException">if the scheme is invalid for rescaling</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form
/// guaranteed to be</exception>
/// <exception cref="ArgumentException">if encrypted is already at lowest level</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RescaleToNextInplace(Ciphertext encrypted, MemoryPoolHandle pool = null)
{
RescaleToNext(encrypted, destination: encrypted, pool: pool);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId and scales the message down
/// accordingly.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId and scales the message down
/// accordingly. Dynamic memory allocations in the process are allocated from the
/// memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="parmsId">The target parmsId</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or parmsId are null</exception>
/// <exception cref="ArgumentException">if the scheme is invalid for rescaling</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is already at lower level in modulus chain
/// than the parameters corresponding to parmsId</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RescaleToInplace(Ciphertext encrypted, ParmsId parmsId, MemoryPoolHandle pool = null)
{
RescaleTo(encrypted, parmsId, destination: encrypted, pool: pool);
}
/// <summary>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId, scales the message down
/// accordingly, and stores the result in the destination parameter.
/// </summary>
/// <remarks>
/// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
/// down until the parameters reach the given ParmsId, scales the message down
/// accordingly, and stores the result in the destination parameter. Dynamic memory
/// allocations in the process are allocated from the memory pool pointed to by the
/// given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to be switched to a smaller modulus</param>
/// <param name="parmsId">The target parmsId</param>
/// <param name="destination">The ciphertext to overwrite with the modulus switched result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, parmsId or destination are null.</exception>
/// <exception cref="ArgumentException">if the scheme is invalid for rescaling</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if parmsId is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is already at lower level in modulus chain
/// than the parameters corresponding to parmsId</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RescaleTo(Ciphertext encrypted, ParmsId parmsId, Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_RescaleTo(
NativePtr, encrypted.NativePtr, parmsId.Block, destination.NativePtr, poolPtr);
}
/// <summary>
/// Multiplies several ciphertexts together. This function computes the product of several
/// ciphertext given as an IEnumerable and stores the result in the destination parameter.
/// </summary>
/// <remarks>
/// Multiplies several ciphertexts together. This function computes the product of several
/// ciphertext given as an IEnumerable and stores the result in the destination parameter.
/// The multiplication is done in a depth-optimal order, and relinearization is performed
/// automatically after every multiplication in the process. In relinearization the given
/// relinearization keys are used. Dynamic memory allocations in the process are allocated
/// from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypteds">The ciphertexts to multiply</param>
/// <param name="relinKeys">The relinearization keys</param>
/// <param name="destination">The ciphertext to overwrite with the multiplication result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypteds, relinKeys or destination are null</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypteds is empty</exception>
/// <exception cref="ArgumentException">if the ciphertexts or relinKeys are not valid for
/// the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypteds are not in the default NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if the size of relinKeys is too small</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void MultiplyMany(IEnumerable<Ciphertext> encrypteds, RelinKeys relinKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypteds)
throw new ArgumentNullException(nameof(encrypteds));
if (null == relinKeys)
throw new ArgumentNullException(nameof(relinKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray();
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_MultiplyMany(
NativePtr, (ulong)encarray.Length, encarray, relinKeys.NativePtr,
destination.NativePtr, poolPtr);
}
/// <summary>
/// Exponentiates a ciphertext.
/// </summary>
/// <remarks>
/// This functions raises encrypted to a power. Dynamic memory allocations in the process
/// are allocated from the memory pool pointed to by the given MemoryPoolHandle. The
/// exponentiation is done in a depth-optimal order, and relinearization is performed
/// automatically after every multiplication in the process. In relinearization the given
/// relinearization keys are used.
/// </remarks>
/// <param name="encrypted">The ciphertext to exponentiate</param>
/// <param name="exponent">The power to raise the ciphertext to</param>
/// <param name="relinKeys">The relinearization keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or relinKeys are null</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypted or relinKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if exponent is zero</exception>
/// <exception cref="ArgumentException">if the size of relinKeys is too small</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ExponentiateInplace(Ciphertext encrypted, ulong exponent,
RelinKeys relinKeys, MemoryPoolHandle pool = null)
{
Exponentiate(encrypted, exponent, relinKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Exponentiates a ciphertext.
/// </summary>
/// <remarks>
/// This functions raises encrypted to a power and stores the result in the destination
/// parameter. Dynamic memory allocations in the process are allocated from the memory pool
/// pointed to by the given MemoryPoolHandle. The exponentiation is done in a depth-optimal
/// order, and relinearization is performed automatically after every multiplication in the
/// process. In relinearization the given relinearization keys are used.
/// </remarks>
/// <param name="encrypted">The ciphertext to exponentiate</param>
/// <param name="exponent">The power to raise the ciphertext to</param>
/// <param name="relinKeys">The relinearization keys</param>
/// <param name="destination">The ciphertext to overwrite with the power</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypted or relinKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if exponent is zero</exception>
/// <exception cref="ArgumentException">if the size of relinKeys is too small</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void Exponentiate(Ciphertext encrypted, ulong exponent, RelinKeys relinKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == relinKeys)
throw new ArgumentNullException(nameof(relinKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_Exponentiate(
NativePtr, encrypted.NativePtr, exponent, relinKeys.NativePtr,
destination.NativePtr, poolPtr);
}
/// <summary>
/// Adds a ciphertext and a plaintext.
/// </summary>
/// <remarks>
/// Adds a ciphertext and a plaintext. The plaintext must be valid for the current
/// encryption parameters.
/// </remarks>
/// <param name="encrypted">The ciphertext to add</param>
/// <param name="plain">The plaintext to add</param>
/// <exception cref="ArgumentNullException">if either encrypted or plain are null</exception>
/// <exception cref="ArgumentException">if encrypted or plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted or plain is in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void AddPlainInplace(Ciphertext encrypted, Plaintext plain)
{
AddPlain(encrypted, plain, destination: encrypted);
}
/// <summary>
/// Adds a ciphertext and a plaintext.
/// </summary>
/// <remarks>
/// Adds a ciphertext and a plaintext. This function adds a ciphertext and a plaintext
/// and stores the result in the destination parameter. The plaintext must be valid for
/// the current encryption parameters.
/// </remarks>
/// <param name="encrypted">The ciphertext to add</param>
/// <param name="plain">The plaintext to add</param>
/// <param name="destination">The ciphertext to overwrite with the addition result</param>
/// <exception cref="ArgumentNullException">if either encrypted, plain or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted or plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted or plain is in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void AddPlain(Ciphertext encrypted, Plaintext plain, Ciphertext destination)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_AddPlain(
NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr);
}
/// <summary>
/// Subtracts a plaintext from a ciphertext.
/// </summary>
/// <remarks>
/// Subtracts a plaintext from a ciphertext. The plaintext must be valid for the current
/// encryption parameters.
/// </remarks>
/// <param name="encrypted">The ciphertext to subtract from</param>
/// <param name="plain">The plaintext to subtract</param>
/// <exception cref="ArgumentNullException">if either encrypted or plain are null</exception>
/// <exception cref="ArgumentException">if encrypted or plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted or plain is in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void SubPlainInplace(Ciphertext encrypted, Plaintext plain)
{
SubPlain(encrypted, plain, destination: encrypted);
}
/// <summary>
/// Subtracts a plaintext from a ciphertext.
/// </summary>
/// <remarks>This function subtracts a plaintext from a ciphertext and stores the result in the
/// destination parameter. The plaintext must be valid for the current encryption parameters.
/// </remarks>
/// <param name="encrypted">The ciphertext to subtract from</param>
/// <param name="plain">The plaintext to subtract</param>
/// <param name="destination">The ciphertext to overwrite with the subtraction result</param>
/// <exception cref="ArgumentNullException">if either encrypted, plain or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted or plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted or plain is in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void SubPlain(Ciphertext encrypted, Plaintext plain, Ciphertext destination)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_SubPlain(
NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr);
}
/// <summary>
/// Multiplies a ciphertext with a plaintext.
/// </summary>
/// <remarks>Multiplies a ciphertext with a plaintext. The plaintext must be valid for the
/// current encryption parameters, and cannot be identially 0. Dynamic memory allocations in
/// the process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to multiply</param>
/// <param name="plain">The plaintext to multiply</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or plain are null.</exception>
/// <exception cref="ArgumentException">if the encrypted or plain is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if encrypted and plain are in different NTT forms</exception>
/// <exception cref="ArgumentException">if plain is zero</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void MultiplyPlainInplace(Ciphertext encrypted, Plaintext plain, MemoryPoolHandle pool = null)
{
MultiplyPlain(encrypted, plain, destination: encrypted, pool: pool);
}
/// <summary>
/// Multiplies a ciphertext with a plaintext.
/// </summary>
/// <remarks>
/// This function multiplies a ciphertext with a plaintext and stores the result in the
/// destination parameter. The plaintext must be valid for the current encryption parameters,
/// and cannot be identially 0. Dynamic memory allocations in the process are allocated from
/// the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to multiply</param>
/// <param name="plain">The plaintext to multiply</param>
/// <param name="destination">The ciphertext to overwrite with the multiplication result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, plain or destination are null</exception>
/// <exception cref="ArgumentException">if the encrypted or plain is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted and plain are in different NTT forms</exception>
/// <exception cref="ArgumentException">if plain is zero</exception>
/// <exception cref="ArgumentException">if, when using SchemeType.CKKS, the output scale
/// is too large for the encryption parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void MultiplyPlain(Ciphertext encrypted, Plaintext plain,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_MultiplyPlain(
NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Transforms a plaintext to NTT domain.
/// </summary>
/// <remarks>This functions applies the Number Theoretic Transform to a plaintext by first
/// embedding integers modulo the plaintext modulus to integers modulo the coefficient
/// modulus and then performing David Harvey's NTT on the resulting polynomial. The
/// transformation is done with respect to encryption parameters corresponding to a given
/// parmsId. For the operation to be valid, the plaintext must have degree less than
/// PolyModulusDegree and each coefficient must be less than the plaintext modulus, i.e.,
/// the plaintext must be a valid plaintext under the current encryption parameters.
/// Dynamic memory allocations in the process are allocated from the memory pool pointed
/// to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="plain">The plaintext to transform</param>
/// <param name="parmsId">The ParmsId with respect to which the NTT is done</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either plain or parmsId are null</exception>
/// <exception cref="ArgumentException">if plain is already in NTT form</exception>
/// <exception cref="ArgumentException">if plain or parmsId is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void TransformToNTTInplace(Plaintext plain, ParmsId parmsId, MemoryPoolHandle pool = null)
{
TransformToNTT(plain, parmsId, destinationNTT: plain, pool: pool);
}
/// <summary>
/// Transforms a plaintext to NTT domain.
/// </summary>
/// <remarks>
/// This functions applies the Number Theoretic Transform to a plaintext by first
/// embedding integers modulo the plaintext modulus to integers modulo the coefficient
/// modulus and then performing David Harvey's NTT on the resulting polynomial. The
/// transformation is done with respect to encryption parameters corresponding to
/// a given ParmsId. The result is stored in the destinationNTT parameter. For the
/// operation to be valid, the plaintext must have degree less than PolyModulusDegree
/// and each coefficient must be less than the plaintext modulus, i.e., the plaintext
/// must be a valid plaintext under the current encryption parameters. Dynamic memory
/// allocations in the process are allocated from the memory pool pointed to by the
/// given MemoryPoolHandle.
/// </remarks>
/// <param name="plain">The plaintext to transform</param>
/// <param name="parmsId">The ParmsId with respect to which the NTT is done</param>
/// <param name="destinationNTT">The plaintext to overwrite with the transformed result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either plain, parmsId or destinationNTT are null</exception>
/// <exception cref="ArgumentException">if plain is already in NTT form</exception>
/// <exception cref="ArgumentException">if plain or parmsId is not valid for the encryption
/// parameters</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public void TransformToNTT(Plaintext plain, ParmsId parmsId,
Plaintext destinationNTT, MemoryPoolHandle pool = null)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
if (null == destinationNTT)
throw new ArgumentNullException(nameof(destinationNTT));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_TransformToNTT(NativePtr, plain.NativePtr, parmsId.Block, destinationNTT.NativePtr, poolPtr);
}
/// <summary>
/// Transforms a ciphertext to NTT domain.
/// </summary>
/// <remarks>
/// Transforms a ciphertext to NTT domain. This functions applies David Harvey's Number
/// Theoretic Transform separately to each polynomial of a ciphertext.
/// </remarks>
/// <param name="encrypted">The ciphertext to transform</param>
/// <exception cref="ArgumentNullException">if encrypted is null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is already in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void TransformToNTTInplace(Ciphertext encrypted)
{
TransformToNTT(encrypted, destinationNTT: encrypted);
}
/// <summary>
/// Transforms a ciphertext to NTT domain.
/// </summary>
/// <remarks>
/// Transforms a ciphertext to NTT domain. This functions applies David Harvey's Number
/// Theoretic Transform separately to each polynomial of a ciphertext. The result is
/// stored in the DestinationNTT parameter.
/// </remarks>
/// <param name="encrypted">The ciphertext to transform</param>
/// <param name="destinationNTT">The ciphertext to overwrite with the transformed result</param>
/// <exception cref="ArgumentNullException">if either encrypted or destinationNTT are null</exception>
/// <exception cref="ArgumentException">if encrypted is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encrypted is already in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void TransformToNTT(Ciphertext encrypted,
Ciphertext destinationNTT)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == destinationNTT)
throw new ArgumentNullException(nameof(destinationNTT));
NativeMethods.Evaluator_TransformToNTT(
NativePtr, encrypted.NativePtr, destinationNTT.NativePtr);
}
/// <summary>
/// Transforms a ciphertext back from NTT domain.
/// </summary>
/// <remarks>
/// Transforms a ciphertext back from NTT domain. This functions applies the inverse of
/// David Harvey's Number Theoretic Transform separately to each polynomial of a ciphertext.
/// </remarks>
/// <param name="encryptedNTT">The ciphertext to transform</param>
/// <exception cref="ArgumentNullException">if encryptedNTT is null</exception>
/// <exception cref="ArgumentException">if encryptedNTT is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encryptedNTT is not in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void TransformFromNTTInplace(Ciphertext encryptedNTT)
{
TransformFromNTT(encryptedNTT, destination: encryptedNTT);
}
/// <summary>
/// Transforms a ciphertext back from NTT domain.
/// </summary>
/// <remarks>
/// Transforms a ciphertext back from NTT domain. This functions applies the inverse of
/// David Harvey's Number Theoretic Transform separately to each polynomial of a ciphertext.
/// The result is stored in the destination parameter.
/// </remarks>
/// <param name="encryptedNTT">The ciphertext to transform</param>
/// <param name="destination">The ciphertext to overwrite with the transformed result</param>
/// <exception cref="ArgumentNullException">if either encryptedNTT or destination are null</exception>
/// <exception cref="ArgumentException">if encryptedNTT is not valid for the encryption parameters</exception>
/// <exception cref="ArgumentException">if encryptedNTT is not in NTT form</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void TransformFromNTT(Ciphertext encryptedNTT, Ciphertext destination)
{
if (null == encryptedNTT)
throw new ArgumentNullException(nameof(encryptedNTT));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.Evaluator_TransformFromNTT(
NativePtr, encryptedNTT.NativePtr, destination.NativePtr);
}
/// <summary>
/// Applies a Galois automorphism to a ciphertext.
/// </summary>
/// <remarks>
/// <para>
/// Applies a Galois automorphism to a ciphertext. To evaluate the Galois automorphism,
/// an appropriate set of Galois keys must also be provided. Dynamic memory allocations
/// in the process are allocated from the memory pool pointed to by the given
/// MemoryPoolHandle.
/// </para>
/// <para>
/// The desired Galois automorphism is given as a Galois element, and must be an odd
/// integer 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 BFV, and complex conjugation in CKKS. In the polynomial view (not batching),
/// a Galois automorphism by a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)).
/// </para>
/// </remarks>
/// <param name="encrypted">The ciphertext to apply the Galois automorphism to</param>
/// <param name="galoisElt">The Galois element</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or galoisKeys are null</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if the Galois element is not valid</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ApplyGaloisInplace(Ciphertext encrypted, uint galoisElt,
GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
{
ApplyGalois(encrypted, galoisElt, galoisKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Applies a Galois automorphism to a ciphertext and writes the result to the
/// destination parameter.
/// </summary>
/// <remarks>
/// <para>
/// Applies a Galois automorphism to a ciphertext and writes the result to the
/// destination parameter. To evaluate the Galois automorphism, an appropriate set of
/// Galois keys must also be provided. Dynamic memory allocations in the process are
/// allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </para>
/// <para>
/// The desired Galois automorphism is given as a Galois element, and must be an odd
/// integer 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 BFV, and complex conjugation in CKKS. In the polynomial view (not batching),
/// a Galois automorphism by a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)).
/// </para>
/// </remarks>
/// <param name="encrypted">The ciphertext to apply the Galois automorphism to</param>
/// <param name="galoisElt">The Galois element</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="destination">The ciphertext to overwrite with the result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, galoisKeys or destination are null</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if the Galois element is not valid</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ApplyGalois(Ciphertext encrypted, uint galoisElt, GaloisKeys galoisKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == galoisKeys)
throw new ArgumentNullException(nameof(galoisKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_ApplyGalois(
NativePtr, encrypted.NativePtr, galoisElt,
galoisKeys.NativePtr, destination.NativePtr, poolPtr);
}
/// <summary>
/// Rotates plaintext matrix rows cyclically.
/// </summary>
/// <remarks>
/// When batching is used with the BFV scheme, this function rotates the encrypted plaintext
/// matrix rows cyclically to the left (steps &gt; 0) or to the right (steps &lt; 0). Since
/// the size of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial
/// modulus, the number of steps to rotate must have absolute value at most N/2-1. Dynamic
/// memory allocations in the process are allocated from the memory pool pointed to by the
/// given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="steps">The number of steps to rotate (negative left, positive right)</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or galoisKeys are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is not in the default NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if steps has too big absolute value</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RotateRowsInplace(Ciphertext encrypted,
int steps, GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
{
RotateRows(encrypted, steps, galoisKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Rotates plaintext matrix rows cyclically.
/// </summary>
/// <remarks>
/// When batching is used with the BFV scheme, this function rotates the encrypted plaintext
/// matrix rows cyclically to the left (steps &gt; 0) or to the right (steps &lt; 0) and writes
/// the result to the destination parameter. Since the size of the batched matrix is 2-by-(N/2),
/// where N is the degree of the polynomial modulus, the number of steps to rotate must have
/// absolute value at most N/2-1. Dynamic memory allocations in the process are allocated from
/// the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="steps">The number of steps to rotate (negative left, positive right)</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="destination">The ciphertext to overwrite with the rotated result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, galoisKeys or destination are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if steps has too big absolute value</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RotateRows(Ciphertext encrypted, int steps, GaloisKeys galoisKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == galoisKeys)
throw new ArgumentNullException(nameof(galoisKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_RotateRows(
NativePtr, encrypted.NativePtr, steps, galoisKeys.NativePtr,
destination.NativePtr, poolPtr);
}
/// <summary>
/// Rotates plaintext matrix columns cyclically.
/// </summary>
/// <remarks>
/// When batching is used with the BFV scheme, this function rotates the encrypted
/// plaintext matrix columns cyclically. Since the size of the batched matrix is 2-by-(N/2),
/// where N is the degree of the polynomial modulus, this means simply swapping the two
/// rows. Dynamic memory allocations in the process are allocated from the memory pool
/// pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or galoisKeys are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RotateColumnsInplace(Ciphertext encrypted, GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
{
RotateColumns(encrypted, galoisKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Rotates plaintext matrix columns cyclically.
/// </summary>
/// <remarks>
/// When batching is used with the BFV scheme, this function rotates the encrypted plaintext
/// matrix columns cyclically, and writes the result to the destination parameter. Since the
/// size of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial modulus,
/// this means simply swapping the two rows. Dynamic memory allocations in the process are
/// allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="destination">The ciphertext to overwrite with the rotated result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, galoisKeys or destination are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.BFV</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RotateColumns(Ciphertext encrypted, GaloisKeys galoisKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == galoisKeys)
throw new ArgumentNullException(nameof(galoisKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_RotateColumns(
NativePtr, encrypted.NativePtr, galoisKeys.NativePtr,
destination.NativePtr, poolPtr);
}
/// <summary>
/// Rotates plaintext vector cyclically.
/// </summary>
/// <remarks>
/// When using the CKKS scheme, this function rotates the encrypted plaintext vector
/// cyclically to the left (steps &gt; 0) or to the right (steps &lt; 0). Since the size
/// of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial modulus,
/// the number of steps to rotate must have absolute value at most N/2-1. Dynamic memory
/// allocations in the process are allocated from the memory pool pointed to by the given
/// MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="steps">The number of steps to rotate (negative left, positive right)</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or galoisKeys are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.CKKS</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if steps has too big absolute value</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RotateVectorInplace(Ciphertext encrypted, int steps,
GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
{
RotateVector(encrypted, steps, galoisKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Rotates plaintext vector cyclically.
/// </summary>
/// <remarks>
/// When using the CKKS scheme, this function rotates the encrypted plaintext vector
/// cyclically to the left (steps &gt; 0) or to the right (steps &lt; 0) and writes
/// the result to the destination parameter. Since the size of the batched matrix is
/// 2-by-(N/2), where N is the degree of the polynomial modulus, the number of steps
/// to rotate must have absolute value at most N/2-1. Dynamic memory allocations in the
/// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="steps">The number of steps to rotate (negative left, positive right)</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="destination">The ciphertext to overwrite with the rotated result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted, galoisKeys or destination are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.CKKS</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if steps has too big absolute value</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void RotateVector(Ciphertext encrypted, int steps, GaloisKeys galoisKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == galoisKeys)
throw new ArgumentNullException(nameof(galoisKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_RotateVector(
NativePtr, encrypted.NativePtr, steps, galoisKeys.NativePtr,
destination.NativePtr, poolPtr);
}
/// <summary>
/// Complex conjugates plaintext slot values.
/// </summary>
/// <remarks>
/// When using the CKKS scheme, this function complex conjugates all values in the
/// underlying plaintext. Dynamic memory allocations in the process are allocated from
/// the memory pool pointed to by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either encrypted or galoisKeys are null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.CKKS</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ComplexConjugateInplace(Ciphertext encrypted, GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
{
ComplexConjugate(encrypted, galoisKeys, destination: encrypted, pool: pool);
}
/// <summary>
/// Complex conjugates plaintext slot values.
/// </summary>
/// <remarks>
/// When using the CKKS scheme, this function complex conjugates all values in the
/// underlying plaintext, and writes the result to the destination parameter. Dynamic
/// memory allocations in the process are allocated from the memory pool pointed to
/// by the given MemoryPoolHandle.
/// </remarks>
/// <param name="encrypted">The ciphertext to rotate</param>
/// <param name="galoisKeys">The Galois keys</param>
/// <param name="destination">The ciphertext to overwrite with the rotated result</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="InvalidOperationException">if the encryption parameters do not support batching</exception>
/// <exception cref="InvalidOperationException">if scheme is not SchemeType.CKKS</exception>
/// <exception cref="ArgumentException">if encrypted or galoisKeys is not valid for the
/// encryption parameters</exception>
/// <exception cref="ArgumentException">if galoisKeys do not correspond to the top level
/// parameters in the current context</exception>
/// <exception cref="ArgumentException">if encrypted is in NTT form</exception>
/// <exception cref="ArgumentException">if encrypted has size larger than 2</exception>
/// <exception cref="ArgumentException">if necessary Galois keys are not present</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
/// <exception cref="InvalidOperationException">if keyswitching is not supported by the context</exception>
/// <exception cref="InvalidOperationException">if result ciphertext is transparent</exception>
public void ComplexConjugate(Ciphertext encrypted, GaloisKeys galoisKeys,
Ciphertext destination, MemoryPoolHandle pool = null)
{
if (null == encrypted)
throw new ArgumentNullException(nameof(encrypted));
if (null == galoisKeys)
throw new ArgumentNullException(nameof(galoisKeys));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
if (!ContextUsingKeyswitching)
throw new InvalidOperationException("Keyswitching is not supported by the context");
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Evaluator_ComplexConjugate(
NativePtr, encrypted.NativePtr, galoisKeys.NativePtr,
destination.NativePtr, poolPtr);
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.Evaluator_Destroy(NativePtr);
}
internal bool ContextUsingKeyswitching
{
get
{
NativeMethods.Evaluator_ContextUsingKeyswitching(NativePtr, out bool result);
return result;
}
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Class to store Galois keys.
/// </summary>
/// <remarks>
/// <para>
/// Slot rotations
/// Galois keys are certain types of public keys that are needed to perform encrypted
/// vector rotation operations on batched ciphertexts. Batched ciphertexts encrypt
/// a 2-by-(N/2) matrix of modular integers in the BFV scheme, or an N/2-dimensional
/// vector of complex numbers in the CKKS scheme, where N denotes the degree of the
/// polynomial modulus. In the BFV scheme Galois keys can enable both cyclic rotations
/// of the encrypted matrix rows, as well as row swaps (column rotations). In the CKKS
/// scheme Galois keys can enable cyclic vector rotations, as well as a complex
/// conjugation operation.
/// </para>
/// <para>
/// Thread Safety
/// In general, reading from GaloisKeys is thread-safe as long as no other thread is
/// concurrently mutating it. This is due to the underlying data structure storing
/// the Galois keys not being thread-safe.
/// </para>
/// </remarks>
public class GaloisKeys :
KSwitchKeys,
ISettable<GaloisKeys>
{
/// <summary>
/// Creates an empty set of Galois keys.
/// </summary>
public GaloisKeys() : base()
{
}
/// <summary>
/// Creates a new GaloisKeys instance by copying a given instance.
/// </summary>
/// <param name="copy">The GaloisKeys to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public GaloisKeys(GaloisKeys copy)
: base(copy)
{
}
/// <summary>
/// Creates a new GaloisKeys instance initialized with a pointer to a native
/// KSwitchKeys object.
/// </summary>
/// <param name="kswitchKeys">Pointer to native KSwitchKeys object</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal GaloisKeys(IntPtr kswitchKeys, bool owned = true)
: base(kswitchKeys, owned)
{
}
/// <summary>
/// Copies a given GaloisKeys instance to the current one.
/// </summary>
///
/// <param name="assign">The GaloisKeys to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(GaloisKeys assign)
{
base.Set(assign);
}
/// <summary>
/// Returns the index of a Galois key in the backing KSwitchKeys instance that
/// corresponds to the given Galois element, assuming that it exists in the
/// backing KSwitchKeys.
/// </summary>
/// <param name="galoisElt">The Galois element</param>
/// <exception cref="ArgumentException">if Galois element is not valid</exception>
public static ulong GetIndex(uint galoisElt)
{
NativeMethods.GaloisKeys_GetIndex(galoisElt, out ulong index);
return index;
}
/// <summary>
/// Returns whether a Galois key corresponding to a given Galois key element
/// exists.
/// </summary>
/// <param name="galoisElt">The Galois element</param>
/// <exception cref="ArgumentException">if Galois element is not valid</exception>
public bool HasKey(uint galoisElt)
{
ulong index = GetIndex(galoisElt);
return (ulong)Data.LongCount() > index &&
Data.ElementAt(checked((int)index)).Count() != 0;
}
/// <summary>
/// Returns a specified Galois key.
/// </summary>
/// <remarks>
/// Returns a specified Galois key. The returned Galois key corresponds to the
/// given Galois element and is valid only as long as the GaloisKeys is valid.
/// </remarks>
/// <param name="galoisElt">The Galois element</param>
/// <exception cref="ArgumentException">if the key corresponding to galoisElt
/// does not exist</exception>
public IEnumerable<PublicKey> Key(uint galoisElt)
{
return Data.ElementAt(checked((int)GetIndex(galoisElt)));
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Encodes integers into plaintext polynomials that Encryptor can encrypt. An instance of
/// the IntegerEncoder class converts an integer into a plaintext polynomial by placing its
/// binary digits as the coefficients of the polynomial. Decoding the integer amounts to
/// evaluating the plaintext polynomial at x=2.
///
/// Addition and multiplication on the integer side translate into addition and multiplication
/// on the encoded plaintext polynomial side, provided that the length of the polynomial
/// never grows to be of the size of the polynomial modulus (PolyModulus), and that the
/// coefficients of the plaintext polynomials appearing throughout the computations never
/// experience coefficients larger than the plaintext modulus (PlainModulus).
/// </summary>
/// <remarks>
/// <para>
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
/// </para>
/// </remarks>
public class IntegerEncoder : NativeObject
{
/// <summary>
/// Creates a IntegerEncoder object. The constructor takes as input a pointer to
/// a SEALContext object which contains the plaintext modulus.
/// </summary>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if context is null</exception>
/// <exception cref="ArgumentException">if the context is not set</exception>
/// <exception cref="ArgumentException">if the PlainModulus set in context is not
/// at least 2</exception>
public IntegerEncoder(SEALContext context)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
if (!context.ParametersSet)
throw new ArgumentException("Encryption parameters are not set correctly");
SEALContext.ContextData contextData = context.FirstContextData;
if (contextData.Parms.Scheme != SchemeType.BFV)
throw new ArgumentException("Unsupported scheme");
NativeMethods.IntegerEncoder_Create(context.NativePtr, out IntPtr encoderPtr);
NativePtr = encoderPtr;
}
/// <summary>
/// Encodes an unsigned integer (represented by ulong) into a plaintext polynomial.
/// </summary>
/// <param name="value">The unsigned integer to encode</param>
public Plaintext Encode(ulong value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
/// <summary>
/// Encodes an unsigned integer(represented by ulong) into a plaintext polynomial.
/// </summary>
/// <param name="value">The unsigned integer to encode</param>
/// <param name="destination">The plaintext to overwrite with the encoding</param>
/// <exception cref="ArgumentNullException">if destination is null</exception>
public void Encode(ulong value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
/// <summary>
/// Decodes a plaintext polynomial and returns the result as uint. Mathematically
/// this amounts to evaluating the input polynomial at X = 2.
/// </summary>
/// <param name="plain">The plaintext to be decoded</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="ArgumentException">if plain does not represent a valid plaintext polynomial</exception>
/// <exception cref="ArgumentException">if the output does not fit in uint</exception>
public uint DecodeUInt32(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeUInt32(NativePtr, plain.NativePtr, out uint result);
return result;
}
/// <summary>
/// Decodes a plaintext polynomial and returns the result as ulong. Mathematically
/// this amounts to evaluating the input polynomial at X=2.
/// </summary>
/// <param name="plain">The plaintext to be decoded</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="ArgumentException">if plain does not represent a valid plaintext polynomial</exception>
/// <exception cref="ArgumentException">if the output does not fit in ulong</exception>
public ulong DecodeUInt64(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeUInt64(NativePtr, plain.NativePtr, out ulong result);
return result;
}
/// <summary>
/// Encodes a signed integer (represented by long) into a plaintext polynomial.
/// </summary>
/// <remarks>
/// <para>
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
/// </para>
/// </remarks>
/// <param name="value">The signed integer to encode</param>
public Plaintext Encode(long value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
/// <summary>
/// Encodes a signed integer(represented by long) into a plaintext polynomial.
/// </summary>
/// <remarks>
/// <para>
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
/// </para>
/// </remarks>
/// <param name="value">The signed integer to encode</param>
/// <param name="destination">The plaintext to overwrite with the encoding</param>
public void Encode(long value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
/// <summary>
/// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial.
/// </summary>
/// <param name="value">The unsigned integer to encode</param>
/// <exception cref="ArgumentNullException">if value is null</exception>
public Plaintext Encode(BigUInt value)
{
if (null == value)
throw new ArgumentNullException(nameof(value));
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, plain.NativePtr);
return plain;
}
/// <summary>
/// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial.
/// </summary>
/// <param name="value">The unsigned integer to encode</param>
/// <param name="destination">The plaintext to overwrite with the encoding</param>
/// <exception cref="ArgumentNullException">if either value or destination are null</exception>
public void Encode(BigUInt value, Plaintext destination)
{
if (null == value)
throw new ArgumentNullException(nameof(value));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, destination.NativePtr);
}
/// <summary>
/// Decodes a plaintext polynomial and returns the result as int. Mathematically
/// this amounts to evaluating the input polynomial at X = 2.
/// </summary>
/// <param name="plain">The plaintext to be decoded</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="ArgumentException">if plain does not represent a valid plaintext polynomial</exception>
/// <exception cref="ArgumentException">if the output does not fit in int</exception>
public int DecodeInt32(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeInt32(NativePtr, plain.NativePtr, out int result);
return result;
}
/// <summary>
/// Decodes a plaintext polynomial and returns the result as long. Mathematically
/// this amounts to evaluating the input polynomial at X = 2.
/// </summary>
/// <param name="plain">The plaintext to be decoded</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="ArgumentException">if plain does not represent a valid plaintext polynomial</exception>
/// <exception cref="ArgumentException">if the output does not fit in long</exception>
public long DecodeInt64(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeInt64(NativePtr, plain.NativePtr, out long result);
return result;
}
/// <summary>
/// Decodes a plaintext polynomial and returns the result as BigUInt.
/// Mathematically this amounts to evaluating the input polynomial at X = 2.
/// </summary>
/// <param name="plain">The plaintext to be decoded</param>
/// <exception cref="ArgumentNullException">if plain is null</exception>
/// <exception cref="ArgumentException">if plain does not represent a valid plaintext polynomial</exception>
/// <exception cref="ArgumentException">if the output is negative</exception>
public BigUInt DecodeBigUInt(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeBigUInt(NativePtr, plain.NativePtr, out IntPtr buiPtr);
BigUInt bui = new BigUInt(buiPtr);
return bui;
}
/// <summary>
/// Encodes a signed integer(represented by int) into a plaintext polynomial.
/// </summary>
/// <remarks>
/// <para>
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
/// </para>
/// </remarks>
/// <param name="value">The signed integer to encode</param>
public Plaintext Encode(int value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
/// <summary>
/// Encodes an unsigned integer(represented by uint) into a plaintext polynomial.
/// </summary>
/// <param name="value">The unsigned integer to encode</param>
public Plaintext Encode(uint value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
/// <summary>
/// Encodes a signed integer(represented by int) into a plaintext polynomial.
/// </summary>
/// <remarks>
/// <para>
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
/// </para>
/// </remarks>
/// <param name="value">The signed integer to encode</param>
/// <param name="destination">The plaintext to overwrite with the encoding</param>
/// <exception cref="ArgumentNullException">if destination is null</exception>
public void Encode(int value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
/// <summary>
/// Encodes an unsigned integer(represented by uint) into a plaintext polynomial.
/// </summary>
/// <param name="value">The unsigned integer to encode</param>
/// <param name="destination">The plaintext to overwrite with the encoding</param>
/// <exception cref="ArgumentNullException">if destination is null</exception>
public void Encode(uint value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
/// <summary>
/// Get a copy of the plaintext modulus.
/// </summary>
public Modulus PlainModulus
{
get
{
NativeMethods.IntegerEncoder_PlainModulus(NativePtr, out IntPtr sm);
Modulus result = new Modulus(sm);
return result;
}
}
/// <summary>
/// Destroy the native object
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.IntegerEncoder_Destroy(NativePtr);
}
}
}
// 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.IO;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Class to store keyswitching keys.
/// </summary>
///
/// <remarks>
/// <para>
/// Class to store keyswitching keys. It should never be necessary for normal
/// users to create an instance of KSwitchKeys. This class is used strictly as
/// a base class for RelinKeys and GaloisKeys classes.
/// </para>
/// <para>
/// Concretely, keyswitching is used to change a ciphertext encrypted with one
/// key to be encrypted with another key.It is a general technique and is used
/// in relinearization and Galois rotations. A keyswitching key contains a sequence
/// (vector) of keys.In RelinKeys, each key is an encryption of a power of the
/// secret key.In GaloisKeys, each key corresponds to a type of rotation.
/// </para>
/// <para>
/// In general, reading from KSwitchKeys is thread-safe as long as no
/// other thread is concurrently mutating it.This is due to the underlying
/// data structure storing the keyswitching keys not being thread-safe.
/// </para>
/// </remarks>
public class KSwitchKeys :
NativeObject,
ISerializableObject,
ISettable<KSwitchKeys>
{
/// <summary>
/// Creates an empty KSwitchKeys.
/// </summary>
public KSwitchKeys()
{
NativeMethods.KSwitchKeys_Create(out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a new KSwitchKeys instance by copying a given instance.
/// </summary>
/// <param name="copy">The KSwitchKeys to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public KSwitchKeys(KSwitchKeys copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.KSwitchKeys_Create(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a new KSwitchKeys instance initialized with a pointer to a native
/// KSwitchKeys object.
/// </summary>
/// <param name="kswitchKeys">Pointer to native KSwitchKeys object</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal KSwitchKeys(IntPtr kswitchKeys, bool owned = true)
: base(kswitchKeys, owned)
{
}
/// <summary>
/// Copies a given KSwitchKeys instance to the current one.
/// </summary>
///
/// <param name="assign">The KSwitchKeys to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(KSwitchKeys assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.KSwitchKeys_Set(NativePtr, assign.NativePtr);
}
/// <summary>
/// Returns the current number of keyswitching keys. Only keys that are non-empty
/// are counted.
/// </summary>
public ulong Size
{
get
{
NativeMethods.KSwitchKeys_Size(NativePtr, out ulong size);
return size;
}
}
/// <summary>
/// Returns the KSwitchKeys data.
/// </summary>
/// <remarks>
/// Returns the KSwitchKeys data. The returned object is valid only as long as
/// the KSwitchKeys is valid and not changed.
/// </remarks>
public IEnumerable<IEnumerable<PublicKey>> Data
{
get
{
List<List<PublicKey>> result = new List<List<PublicKey>>();
NativeMethods.KSwitchKeys_RawSize(NativePtr, out ulong size);
for (ulong i = 0; i < size; i++)
{
ulong count = 0;
NativeMethods.KSwitchKeys_GetKeyList(NativePtr, i, ref count, null);
IntPtr[] pointers = new IntPtr[count];
NativeMethods.KSwitchKeys_GetKeyList(NativePtr, i, ref count, pointers);
List<PublicKey> key = new List<PublicKey>(checked((int)count));
foreach (IntPtr ptr in pointers)
{
key.Add(new PublicKey(ptr, owned: false));
}
result.Add(key);
}
return result;
}
}
/// <summary>
/// Returns a copy of ParmsId.
/// </summary>
public ParmsId ParmsId
{
get
{
ParmsId parms = new ParmsId();
NativeMethods.KSwitchKeys_GetParmsId(NativePtr, parms.Block);
return parms;
}
private set
{
NativeMethods.KSwitchKeys_SetParmsId(NativePtr, value.Block);
}
}
/// <summary>
/// Returns an upper bound on the size of the KSwitchKeys, as if it was written
/// to an output stream.
/// </summary>
/// <param name="comprMode">The compression mode</param>
/// <exception cref="ArgumentException">if the compression mode is not
/// supported</exception>
/// <exception cref="InvalidOperationException">if the size does not fit in
/// the return type</exception>
public long SaveSize(ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
NativeMethods.KSwitchKeys_SaveSize(
NativePtr, (byte)comprModeValue, out long outBytes);
return outBytes;
}
/// <summary>Saves the KSwitchKeys to an output stream.</summary>
/// <remarks>
/// Saves the KSwitchKeys to an output stream. The output is in binary format
/// and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the KSwitchKeys to</param>
/// <param name="comprMode">The desired compression mode</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support writing, or if compression mode is not supported</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved
/// is invalid, or if compression failed</exception>
public long Save(Stream stream, ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
return Serialization.Save(
(byte[] outptr, ulong size, byte cm, out long outBytes) =>
NativeMethods.KSwitchKeys_Save(NativePtr, outptr, size,
cm, out outBytes),
SaveSize(comprModeValue), comprModeValue, stream);
}
/// <summary>Loads a KSwitchKeys from an input stream overwriting the current
/// KSwitchKeys.</summary>
/// <remarks>
/// Loads a KSwitchKeys from an input stream overwriting the current
/// KSwitchKeys. No checking of the validity of the KSwitchKeys data against
/// encryption parameters is performed. This function should not be used
/// unless the KSwitchKeys comes from a fully trusted source.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the KSwitchKeys from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long UnsafeLoad(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.KSwitchKeys_UnsafeLoad(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>Loads a KSwitchKeys from an input stream overwriting the current
/// KSwitchKeys.</summary>
/// <remarks>
/// Loads a KSwitchKeys from an input stream overwriting the current
/// KSwitchKeys. The loaded KSwitchKeys is verified to be valid for the given
/// SEALContext.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the KSwitchKeys from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long Load(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.KSwitchKeys_Load(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>
/// Returns the currently used MemoryPoolHandle.
/// </summary>
public MemoryPoolHandle Pool
{
get
{
NativeMethods.KSwitchKeys_Pool(NativePtr, out IntPtr pool);
MemoryPoolHandle handle = new MemoryPoolHandle(pool);
return handle;
}
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.KSwitchKeys_Destroy(NativePtr);
}
}
}
// 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
{
/// <summary>
/// Generates matching secret key and public key.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public class KeyGenerator : NativeObject
{
/// <summary>
/// Creates a KeyGenerator initialized with the specified SEALContext.
/// </summary>
/// <remarks>
/// Creates a KeyGenerator initialized with the specified <see cref="SEALContext" />.
/// Dynamically allocated member variables are allocated from the global memory pool.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentException">if encryption parameters are not
/// valid</exception>
/// <exception cref="ArgumentNullException">if context is null</exception>
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;
}
/// <summary>
/// Creates an KeyGenerator instance initialized with the specified
/// SEALContext and specified previously secret key.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="secretKey">A previously generated secret key</param>
/// <exception cref="ArgumentNullException">if either context or secretKey
/// are null</exception>
/// <exception cref="ArgumentException">if encryption parameters are not
/// valid</exception>
/// <exception cref="ArgumentException">if secretKey or publicKey is not
/// valid for encryption parameters</exception>
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;
}
/// <summary>
/// Generates and returns a public key. Every time this function is called,
/// a new public key will be generated.
/// </summary>
public PublicKey PublicKey
{
get
{
NativeMethods.KeyGenerator_PublicKey(NativePtr, out IntPtr pubKeyPtr);
PublicKey pubKey = new PublicKey(pubKeyPtr);
return pubKey;
}
}
/// <summary>
/// Returns a copy of the secret key.
/// </summary>
public SecretKey SecretKey
{
get
{
NativeMethods.KeyGenerator_SecretKey(NativePtr, out IntPtr secretKeyPtr);
SecretKey secretKey = new SecretKey(secretKeyPtr);
return secretKey;
}
}
/// <summary>
/// Generates and returns relinearization keys.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
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);
}
/// <summary>
/// Generates and returns relinearization keys as a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// Generates and returns relinearization keys as a serializable object.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
public Serializable<RelinKeys> 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>(relinKeys);
}
/// <summary>
/// Generates and returns Galois keys.
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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)).
/// </para>
/// </remarks>
/// <param name="galoisElts">The Galois elements for which to generate keys</param>
/// <exception cref="InvalidOperationException">if the encryption parameters
/// do not support batching and scheme is SchemeType.BFV</exception>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
/// <exception cref="ArgumentException">if the Galois elements are not valid</exception>
public GaloisKeys GaloisKeysLocal(IEnumerable<uint> 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);
}
/// <summary>
/// Generates and returns Galois keys as a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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)).
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
/// <param name="galoisElts">The Galois elements for which to generate keys</param>
/// <exception cref="ArgumentNullException">if galoisElts is null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters
/// do not support batching and scheme is SchemeType.BFV</exception>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
/// <exception cref="ArgumentException">if the Galois elements are not valid</exception>
public Serializable<GaloisKeys> GaloisKeys(IEnumerable<uint> 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>(galoisKeys);
}
/// <summary>
/// Generates and returns Galois keys.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <param name="steps">The rotation step counts for which to generate keys</param>
/// <exception cref="ArgumentNullException">if steps is null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters
/// do not support batching and scheme is SchemeType.BFV</exception>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
/// <exception cref="ArgumentException">if the step counts are not valid</exception>
public GaloisKeys GaloisKeysLocal(IEnumerable<int> 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);
}
/// <summary>
/// Generates and returns Galois keys as a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
/// <param name="steps">The rotation step counts for which to generate keys</param>
/// <exception cref="ArgumentNullException">if steps is null</exception>
/// <exception cref="InvalidOperationException">if the encryption parameters
/// do not support batching and scheme is SchemeType.BFV</exception>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
/// <exception cref="ArgumentException">if the step counts are not valid</exception>
public Serializable<GaloisKeys> GaloisKeys(IEnumerable<int> 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>(galoisKeys);
}
/// <summary>
/// Generates and returns Galois keys.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <exception cref="InvalidOperationException">if the encryption parameters
/// do not support batching and scheme is SchemeType.BFV</exception>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
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);
}
/// <summary>
/// Generates and returns Galois keys as a serializable object.
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
/// <exception cref="InvalidOperationException">if the encryption parameters
/// do not support batching and scheme is SchemeType.BFV</exception>
/// <exception cref="InvalidOperationException">if the encryption
/// parameters do not support keyswitching</exception>
public Serializable<GaloisKeys> 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>(galoisKeys);
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.KeyGenerator_Destroy(NativePtr);
}
internal bool UsingKeyswitching()
{
NativeMethods.KeyGenerator_ContextUsingKeyswitching(NativePtr, out bool result);
return result;
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// The MMProf is a pure virtual class that every profile for the MemoryManager
/// should inherit from. The only functionality this class implements is the
/// GetPool() function that returns a MemoryPoolHandle pointing
/// to a pool selected by internal logic. The returned MemoryPoolHandle must
/// point to a valid memory pool.
/// </summary>
public abstract class MMProf : NativeObject
{
/// <summary>
/// Returns a MemoryPoolHandle pointing to a pool selected by internal logic
/// in a derived class.
/// </summary>
public MemoryPoolHandle GetPool()
{
NativeMethods.MMProf_GetPool(NativePtr, out IntPtr pool);
MemoryPoolHandle handle = new MemoryPoolHandle(pool);
return handle;
}
/// <summary>
/// Destroy native backing object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.MMProf_Destroy(NativePtr);
}
}
/// <summary>
/// A memory manager profile that always returns a MemoryPoolHandle pointing to
/// the global memory pool. Microsoft SEAL uses this memory manager profile by default.
/// </summary>
public class MMProfGlobal : MMProf
{
/// <summary>
/// Create a new instance of MMProfGlobal
/// </summary>
public MMProfGlobal()
{
NativeMethods.MMProf_CreateGlobal(out IntPtr profile);
NativePtr = profile;
}
}
/// <summary>
/// A memory manager profile that always returns a MemoryPoolHandle pointing to
/// specific memory pool.
/// </summary>
public class MMProfFixed : MMProf
{
/// <summary>
/// Create a new instance of MMProfFixed
/// </summary>
/// <param name="pool">Fixed memory pool handle to use</param>
/// <exception cref="ArgumentNullException">if pool is null</exception>
public MMProfFixed(MemoryPoolHandle pool)
{
if (null == pool)
throw new ArgumentNullException(nameof(pool));
// Create a copy of MemoryPoolHandle, as the profile will take ownership
// of the pointer and will attempt to delete it when destroyed.
NativeMethods.MemoryPoolHandle_Create(pool.NativePtr, out IntPtr poolCopy);
NativeMethods.MMProf_CreateFixed(poolCopy, out IntPtr profile);
NativePtr = profile;
}
}
/// <summary>
/// A memory manager profile that always returns a MemoryPoolHandle pointing to
/// the new thread-safe memory pool. This profile should not be used except in
/// special circumstances, as it does not result in any reuse of allocated memory.
/// </summary>
public class MMProfNew : MMProf
{
/// <summary>
/// Create a new instance of MMProfNew
/// </summary>
public MMProfNew()
{
NativeMethods.MMProf_CreateNew(out IntPtr profile);
NativePtr = profile;
}
}
/// <summary>
/// A memory manager profile that always returns a MemoryPoolHandle pointing to
/// the thread-local memory pool. This profile should be used with care, as any
/// memory allocated by it will be released once the thread exits. In other words,
/// the thread-local memory pool cannot be used to share memory across different
/// threads. On the other hand, this profile can be useful when a very high number
/// of threads doing simultaneous allocations would cause contention in the
/// global memory pool.
/// </summary>
public class MMProfThreadLocal : MMProf
{
/// <summary>
/// Create a new instance of MMProfThreadLocal
/// </summary>
public MMProfThreadLocal()
{
NativeMethods.MMProf_CreateThreadLocal(out IntPtr profile);
NativePtr = profile;
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Memory Manager Profile Options used in MemoryManager.GetPool method
/// </summary>
public enum MMProfOpt : ulong
{
/// <summary>
/// Use default profile
/// </summary>
Default = 0,
/// <summary>
/// Force use of the Global profile
/// </summary>
ForceGlobal = 1,
/// <summary>
/// Force use of a New profile
/// </summary>
ForceNew = 2,
/// <summary>
/// Force use of the Thread Local profile
/// </summary>
ForceThreadLocal = 4
}
/// <summary>
/// The MemoryManager class can be used to create instances of MemoryPoolHandle
/// based on a given "profile". A profile is implemented by inheriting from the
/// MMProf class (pure virtual) and encapsulates internal logic for deciding which
/// memory pool to use.
/// </summary>
public static class MemoryManager
{
/// <summary>
/// Static initialization of MemoryManager
/// </summary>
static MemoryManager()
{
// The default profile is Global
profile_ = new MMProfGlobal();
}
/// <summary>
/// Sets the current profile to a given one and returns an instance pointing
/// to the previously set profile.
/// </summary>
/// <param name="newProfile">New memory manager profile</param>
/// <exception cref="ArgumentNullException">if newProfile is null</exception>
public static MMProf SwitchProfile(MMProf newProfile)
{
if (null == newProfile)
throw new ArgumentNullException(nameof(newProfile));
NativeMethods.MemoryManager_SwitchProfile(newProfile.NativePtr);
MMProf oldProfile = profile_;
profile_ = newProfile;
return oldProfile;
}
/// <summary>
/// Returns a MemoryPoolHandle according to the currently set memory manager
/// profile and profOpt. The following values for profOpt have an effect
/// independent of the current profile:
///
/// MMProfOpt.ForceNew: return MemoryPoolHandle.New()
/// MMProfOpt.ForceGlobal: return MemoryPoolHandle.Global()
/// MMProfOpt.ForceThreadLocal: return MemoryPoolHandle.ThreadLocal()
///
/// Other values for profOpt are forwarded to the current profile and, depending
/// on the profile, may or may not have an effect. The value MMProfOpt.Default
/// will always invoke a default behavior for the current profile.
/// </summary>
/// <param name="profOpt">A MMProfOpt parameter used to provide additional
/// instructions to the memory manager profile for internal logic.</param>
/// <param name="clearOnDestruction">Indicates whether the memory pool data
/// should be cleared when destroyed.This can be important when memory pools
/// are used to store private data. This parameter is only used with MMProfOpt.ForceNew,
/// and ignored in all other cases.</param>
public static MemoryPoolHandle GetPool(MMProfOpt profOpt, bool clearOnDestruction = false)
{
NativeMethods.MemoryManager_GetPool((int)profOpt, clearOnDestruction, out IntPtr handlePtr);
MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
return handle;
}
/// <summary>
/// Returns a MemoryPoolHandle according to the currently set memory manager profile.
/// </summary>
public static MemoryPoolHandle GetPool()
{
NativeMethods.MemoryManager_GetPool(out IntPtr handlePtr);
MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
return handle;
}
/// <summary>
/// Currently set profile
/// </summary>
private static MMProf profile_ = null;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Manages a shared pointer to a memory pool. Microsoft SEAL uses memory pools for
/// improved performance due to the large number of memory allocations needed
/// by the homomorphic encryption operations, and the underlying polynomial
/// arithmetic. The library automatically creates a shared global memory pool
/// that is used for all dynamic allocations by default, and the user can
/// optionally create any number of custom memory pools to be used instead.
/// </summary>
/// <remarks>
/// <para>
/// Uses in Multi-Threaded Applications
/// Sometimes the user might want to use specific memory pools for dynamic
/// allocations in certain functions. For example, in heavily multi-threaded
/// applications allocating concurrently from a shared memory pool might lead
/// to significant performance issues due to thread contention. For these cases
/// Microsoft SEAL provides overloads of the functions that take a MemoryPoolHandle as an
/// additional argument, and uses the associated memory pool for all dynamic
/// allocations inside the function. Whenever this functions is called, the
/// user can then simply pass a thread-local MemoryPoolHandle to be used.
/// </para>
/// <para>
/// Thread-Unsafe Memory Pools
/// While memory pools are by default thread-safe, in some cases it suffices
/// to have a memory pool be thread-unsafe. To get a little extra performance,
/// the user can optionally create such thread-unsafe memory pools and use them
/// just as they would use thread-safe memory pools.
/// </para>
/// <para>
/// Initialized and Uninitialized Handles
/// A MemoryPoolHandle has to be set to point either to the global memory pool,
/// or to a new memory pool. If this is not done, the MemoryPoolHandle is
/// said to be uninitialized, and cannot be used. Initialization simple means
/// assigning MemoryPoolHandle::Global() or MemoryPoolHandle::New() to it.
/// </para>
/// <para>
/// Managing Lifetime
/// Internally, the MemoryPoolHandle wraps a C++ shared pointer pointing to
/// a memory pool class. Thus, as long as a MemoryPoolHandle pointing to
/// a particular memory pool exists, the pool stays alive. Classes such as
/// Evaluator and Ciphertext store their own local copies of a MemoryPoolHandle
/// to guarantee that the pool stays alive as long as the managing object
/// itself stays alive. The global memory pool is implemented as a global
/// C++ std::shared_ptr to a memory pool class, and is thus expected to stay
/// alive for the entire duration of the program execution. Note that it can
/// be problematic to create other global objects that use the memory pool
/// e.g. in their constructor, as one would have to ensure the initialization
/// order of these global variables to be correct (i.e. global memory pool
/// first).
/// </para>
/// </remarks>
public class MemoryPoolHandle : NativeObject
{
/// <summary>
/// Creates a new uninitialized MemoryPoolHandle.
/// </summary>
public MemoryPoolHandle()
{
NativeMethods.MemoryPoolHandle_Create(out IntPtr handlePtr);
NativePtr = handlePtr;
}
/// <summary>
/// Creates a copy of a given MemoryPoolHandle. As a result, the created
/// MemoryPoolHandle will point to the same underlying memory pool as the
/// copied instance.
/// </summary>
/// <param name="copy">The MemoryPoolHandle to copy from.</param>
/// <exception cref="ArgumentNullException">if copy is null.</exception>
public MemoryPoolHandle(MemoryPoolHandle copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.MemoryPoolHandle_Create(copy.NativePtr, out IntPtr handlePtr);
NativePtr = handlePtr;
}
/// <summary>
/// Create a MemoryPoolHandle through a native object pointer.
/// </summary>
/// <param name="ptr">Pointer to native MemoryPoolHandle</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal MemoryPoolHandle(IntPtr ptr, bool owned = true)
: base(ptr, owned)
{
}
/// <summary>
/// Overwrites the MemoryPoolHandle instance with the specified instance. As
/// a result, the current MemoryPoolHandle will point to the same underlying
/// memory pool as the assigned instance.
/// </summary>
/// <param name="assign">The MemoryPoolHandle instance to assign to the current
/// instance</param>
/// <exception cref="ArgumentNullException">if assign is null.</exception>
public void Set(MemoryPoolHandle assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.MemoryPoolHandle_Set(NativePtr, assign.NativePtr);
}
/// <summary>
/// Returns a MemoryPoolHandle pointing to the global memory pool.
/// </summary>
public static MemoryPoolHandle Global()
{
NativeMethods.MemoryPoolHandle_Global(out IntPtr handlePtr);
MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
return handle;
}
/// <summary>
/// Returns a MemoryPoolHandle pointing to the thread-local memory pool.
/// </summary>
public static MemoryPoolHandle ThreadLocal()
{
NativeMethods.MemoryPoolHandle_ThreadLocal(out IntPtr handlePtr);
MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
return handle;
}
/// <summary>
/// Returns a MemoryPoolHandle pointing to a new thread-safe memory pool.
/// </summary>
/// <param name="clearOnDestruction">Indicates whether the memory pool data
/// should be cleared when destroyed.This can be important when memory pools
/// are used to store private data.</param>
public static MemoryPoolHandle New(bool clearOnDestruction = false)
{
NativeMethods.MemoryPoolHandle_New(clearOnDestruction, out IntPtr handlePtr);
MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
return handle;
}
/// <summary>
/// Returns the number of different allocation sizes.
/// </summary>
/// <remarks>
/// This function returns the number of different allocation sizes the memory
/// pool pointed to by the current MemoryPoolHandle has made. For example,
/// if the memory pool has only allocated two allocations of sizes 128 KB,
/// this function returns 1. If it has instead allocated one allocation of
/// size 64 KB and one of 128 KB, this functions returns 2.
/// </remarks>
public ulong PoolCount
{
get
{
NativeMethods.MemoryPoolHandle_PoolCount(NativePtr, out ulong count);
return count;
}
}
/// <summary>
/// Returns the size of allocated memory.
/// </summary>
/// <remarks>
/// This functions returns the total amount of memory (in bytes) allocated
/// by the memory pool pointed to by the current MemoryPoolHandle.
/// </remarks>
public ulong AllocByteCount
{
get
{
NativeMethods.MemoryPoolHandle_AllocByteCount(NativePtr, out ulong count);
return count;
}
}
/// <summary>
/// Returns the number of MemoryPoolHandle objects sharing this memory pool.
/// </summary>
public long UseCount
{
get
{
NativeMethods.MemoryPoolHandle_UseCount(NativePtr, out long count);
return count;
}
}
/// <summary>
/// Returns whether the MemoryPoolHandle is initialized.
/// </summary>
public bool IsInitialized
{
get
{
NativeMethods.MemoryPoolHandle_IsInitialized(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Compares MemoryPoolHandles. This function returns whether the current
/// MemoryPoolHandle points to the same memory pool as a given MemoryPoolHandle.
/// </summary>
/// <param name="obj">Object to compare to.</param>
public override bool Equals(object obj)
{
MemoryPoolHandle other = obj as MemoryPoolHandle;
if (null == other)
return false;
NativeMethods.MemoryPoolHandle_Equals(NativePtr, other.NativePtr, out bool result);
return result;
}
/// <summary>
/// Get hash code for this MemoryPoolHandle
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.MemoryPoolHandle_Destroy(NativePtr);
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Research.SEAL
{
/// <summary>Represent an integer modulus of up to 61 bits.</summary>
/// <remarks>
/// <para>
/// Represent an integer modulus of up to 61 bits. An instance of the Modulus
/// class represents a non-negative integer modulus up to 61 bits. In particular,
/// the encryption parameter PlainModulus, and the primes in CoeffModulus, are
/// represented by instances of Modulus. The purpose of this class is to
/// perform and store the pre-computation required by Barrett reduction.
/// </para>
/// <para>
/// In general, reading from Modulus is thread-safe as long as no other thread
/// is concurrently mutating it.
/// </para>
/// </remarks>
/// <seealso cref="EncryptionParameters">See EncryptionParameters for a description
/// of the encryption parameters.</seealso>
public class Modulus : NativeObject,
IEquatable<Modulus>, IEquatable<ulong>,
IComparable<Modulus>, IComparable<ulong>
{
/// <summary>Creates a Modulus instance.</summary>
/// <remarks>
/// Creates a Modulus instance. The value of the Modulus is set to 0.
/// </remarks>
public Modulus()
{
NativeMethods.Modulus_Create(value: 0, smallModulus: out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>Creates a Modulus instance.</summary>
/// <remarks>
/// Creates a Modulus instance. The value of the Modulus is set to
/// the given value.
/// </remarks>
/// <param name="value">The integer modulus</param>
/// <exception cref="ArgumentException">if value is 1 or more than
/// 61 bits</exception>
public Modulus(ulong value)
{
NativeMethods.Modulus_Create(value, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>Creates a new Modulus by copying a given one.</summary>
/// <param name="copy">The Modulus to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public Modulus(Modulus copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.Modulus_Create(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a Modulus from a native pointer
/// </summary>
/// <param name="sm">Pointer to the native Modulus</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal Modulus(IntPtr sm, bool owned = true)
: base(sm, owned)
{
}
/// <summary>Copies a given Modulus to the current one.</summary>
/// <param name="assign">The Modulus to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(Modulus assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.Modulus_Set(NativePtr, assign.NativePtr);
}
/// <summary>Sets the value of the Modulus.</summary>
/// <param name="value">The new integer modulus</param>
/// <exception cref="ArgumentException">if value is 1 or more than
/// 61 bits</exception>
public void Set(ulong value)
{
NativeMethods.Modulus_Set(NativePtr, value);
}
/// <summary>
/// Returns the significant bit count of the value of the current Modulus.
/// </summary>
public int BitCount
{
get
{
NativeMethods.Modulus_BitCount(NativePtr, out int result);
return result;
}
}
/// <summary>
/// Returns the size (in 64-bit words) of the value of the current Modulus.
/// </summary>
public ulong UInt64Count
{
get
{
NativeMethods.Modulus_UInt64Count(NativePtr, out ulong result);
return result;
}
}
/// <summary>
/// Returns the value of the current Modulus.
/// </summary>
public ulong Value
{
get
{
NativeMethods.Modulus_Value(NativePtr, out ulong result);
return result;
}
}
/// <summary>
/// Returns the Barrett ratio computed for the value of the current Modulus.
/// </summary>
/// <remarks>
/// Returns the Barrett ratio computed for the value of the current Modulus.
/// The first two components of the Barrett ratio are the floor of 2^128/value,
/// and the third component is the remainder.
/// </remarks>
public Tuple<ulong, ulong, ulong> ConstRatio
{
get
{
ulong[] ratio = new ulong[3];
NativeMethods.Modulus_ConstRatio(NativePtr, length: (ulong)3, ratio: ratio);
return new Tuple<ulong, ulong, ulong>(ratio[0], ratio[1], ratio[2]);
}
}
/// <summary>
/// Returns whether the value of the current Modulus is zero.
/// </summary>
public bool IsZero
{
get
{
NativeMethods.Modulus_IsZero(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Returns whether the value of the current Modulus is a prime number.
/// </summary>
public bool IsPrime
{
get
{
NativeMethods.Modulus_IsPrime(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Returns an upper bound on the size of the Modulus, as if it was
/// written to an output stream.
/// </summary>
/// <param name="comprMode">The compression mode</param>
/// <exception cref="ArgumentException">if the compression mode is not
/// supported</exception>
/// <exception cref="InvalidOperationException">if the size does not fit in
/// the return type</exception>
public long SaveSize(ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
NativeMethods.Modulus_SaveSize(
NativePtr, (byte)comprModeValue, out long outBytes);
return outBytes;
}
/// <summary>Saves the Modulus to an output stream.</summary>
/// <remarks>
/// Saves the Modulus to an output stream. The output is in binary format
/// and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the Modulus to</param>
/// <param name="comprMode">The desired compression mode</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support writing, or if compression mode is not supported</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved
/// is invalid, or if compression failed</exception>
public long Save(Stream stream, ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
return Serialization.Save(
(byte[] outptr, ulong size, byte cm, out long outBytes) =>
NativeMethods.Modulus_Save(NativePtr, outptr, size,
cm, out outBytes),
SaveSize(comprModeValue), comprModeValue, stream);
}
/// <summary>
/// Loads a Modulus from an input stream overwriting the current
/// Modulus.
/// </summary>
/// <param name="stream">The stream to load the Modulus from</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long Load(Stream stream)
{
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.Modulus_Load(NativePtr, outptr, size,
out outBytes),
stream);
}
/// <summary>
/// Returns a hash-code based on the value of the Modulus.
/// </summary>
public override int GetHashCode()
{
ulong[] arr = new ulong[1];
arr[0] = Value;
return Utilities.ComputeArrayHashCode(arr);
}
/// <summary>
/// Compares two Modulus instances.
/// </summary>
/// <param name="obj">The value to compare against</param>
public override bool Equals(object obj)
{
Modulus sm = obj as Modulus;
return Equals(sm);
}
/// <summary>Creates a Modulus instance.</summary>
/// <remarks>
/// Creates a Modulus instance. The value of the Modulus is set to
/// the given value.
/// </remarks>
/// <param name="value">The integer modulus</param>
/// <exception cref="ArgumentException">if value is 1 or more than 61 bits</exception>
public static explicit operator Modulus(ulong value)
{
Modulus sm = new Modulus(value);
return sm;
}
#region IEquatable<Modulus> methods
/// <summary>
/// Determines whether this instance equals another Modulus instance
/// </summary>
/// <param name="other">Instance to compare against</param>
public bool Equals(Modulus other)
{
if (null == other)
return false;
NativeMethods.Modulus_Equals(NativePtr, other.NativePtr, out bool result);
return result;
}
#endregion
#region IEquatable<ulong> methods
/// <summary>
/// Determines whether the value of this instance equals the given UInt64 value
/// </summary>
/// <param name="other">The value to compare against</param>
public bool Equals(ulong other)
{
NativeMethods.Modulus_Equals(NativePtr, other, out bool result);
return result;
}
#endregion
#region IComparable<Modulus> methods
/// <summary>
/// Compares two Modulus instances.
/// </summary>
/// <param name="compare">The Modulus to compare against</param>
public int CompareTo(Modulus compare)
{
if (null == compare)
return 1;
return Value.CompareTo(compare.Value);
}
#endregion
#region IComparable<ulong> methods
/// <summary>
/// Compares a Modulus value to an unsigned integer.
/// </summary>
/// <param name="compare">The unsigned integer to compare against</param>
public int CompareTo(ulong compare)
{
return Value.CompareTo(compare);
}
#endregion
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.Modulus_Destroy(NativePtr);
}
}
/// <summary>
/// Represents a standard security level according to the HomomorphicEncryption.org
/// security standard.
/// </summary>
/// <remarks>
/// Represents a standard security level according to the HomomorphicEncryption.org
/// security standard. The value SecLevelType.None signals that no standard
/// security level should be imposed. The value SecLevelType.TC128 provides
/// a very high level of security and is the default security level enforced by
/// Microsoft SEAL when constructing a SEALContext object. Normal users should not
/// have to specify the security level explicitly anywhere.
/// </remarks>
public enum SecLevelType : int
{
/// <summary>
/// No security level specified.
/// </summary>
None = 0,
/// <summary>
/// 128-bit security level according to HomomorphicEncryption.org standard.
/// </summary>
TC128 = 128,
/// <summary>
/// 192-bit security level according to HomomorphicEncryption.org standard.
/// </summary>
TC192 = 192,
/// <summary>
/// 256-bit security level according to HomomorphicEncryption.org standard.
/// </summary>
TC256 = 256
}
/// <summary>
/// This class contains static methods for creating a coefficient modulus easily.
/// </summary>
/// <remarks>
/// <para>
/// This class contains static methods for creating a coefficient modulus easily.
/// Note that while these functions take a SecLevelType argument, all security
/// guarantees are lost if the output is used with encryption parameters with
/// a mismatching value for the PolyModulusDegree.
/// </para>
/// <para>
/// The default value SecLevelType.TC128 provides a very high level of security
/// and is the default security level enforced by Microsoft SEAL when constructing
/// a SEALContext object. Normal users should not have to specify the security
/// level explicitly anywhere.
/// </para>
/// </remarks>
public static class CoeffModulus
{
/// <summary>
/// Returns the largest bit-length of the coefficient modulus, i.e., bit-length
/// of the product of the primes in the coefficient modulus, that guarantees
/// a given security level when using a given PolyModulusDegree, according
/// to the HomomorphicEncryption.org security standard.
/// </summary>
/// <param name="polyModulusDegree">The value of the PolyModulusDegree
/// encryption parameter</param>
/// <param name="secLevel">The desired standard security level</param>
static public int MaxBitCount(ulong polyModulusDegree, SecLevelType secLevel = SecLevelType.TC128)
{
NativeMethods.CoeffModulus_MaxBitCount(polyModulusDegree, (int)secLevel, out int result);
return result;
}
/// <summary>
/// Returns a default coefficient modulus for the BFV scheme that guarantees
/// a given security level when using a given PolyModulusDegree, according
/// to the HomomorphicEncryption.org security standard.
/// </summary>
/// <remarks>
/// <para>
/// Returns a default coefficient modulus for the BFV scheme that guarantees
/// a given security level when using a given PolyModulusDegree, according
/// to the HomomorphicEncryption.org security standard. Note that all security
/// guarantees are lost if the output is used with encryption parameters with
/// a mismatching value for the PolyModulusDegree.
/// </para>
/// <para>
/// The coefficient modulus returned by this function will not perform well
/// if used with the CKKS scheme.
/// </para>
/// </remarks>
/// <param name="polyModulusDegree">The value of the PolyModulusDegree
/// encryption parameter</param>
/// <param name="secLevel">The desired standard security level</param>
/// <exception cref="ArgumentException">if polyModulusDegree is not
/// a power-of-two or is too large</exception>
/// <exception cref="ArgumentException">if secLevel is SecLevelType.None</exception>
static public IEnumerable<Modulus> BFVDefault(
ulong polyModulusDegree, SecLevelType secLevel = SecLevelType.TC128)
{
List<Modulus> result = null;
ulong length = 0;
NativeMethods.CoeffModulus_BFVDefault(polyModulusDegree, (int)secLevel, ref length, null);
IntPtr[] coeffArray = new IntPtr[length];
NativeMethods.CoeffModulus_BFVDefault(polyModulusDegree, (int)secLevel, ref length, coeffArray);
result = new List<Modulus>(checked((int)length));
foreach (IntPtr sm in coeffArray)
{
result.Add(new Modulus(sm));
}
return result;
}
/// <summary>
/// Returns a custom coefficient modulus suitable for use with the specified
/// PolyModulusDegree.
/// </summary>
/// <remarks>
/// Returns a custom coefficient modulus suitable for use with the specified
/// PolyModulusDegree.The return value will be a vector consisting of
/// Modulus elements representing distinct prime numbers of bit-lengths
/// as given in the bitSizes parameter. The bit sizes of the prime numbers
/// can be at most 60 bits.
/// </remarks>
/// <param name="polyModulusDegree">The value of the PolyModulusDegree
/// encryption parameter</param>
/// <param name="bitSizes">The bit-lengths of the primes to be generated</param>
/// <exception cref="ArgumentException">if polyModulusDegree is not
/// a power-of-two or is too large</exception>
/// <exception cref="ArgumentException">if bitSizes is too large or if its
/// elements are out of bounds</exception>
/// <exception cref="InvalidOperationException">if not enough suitable primes could be found</exception>
static public IEnumerable<Modulus> Create(
ulong polyModulusDegree, IEnumerable<int> bitSizes)
{
if (null == bitSizes)
throw new ArgumentNullException(nameof(bitSizes));
List<Modulus> result = null;
int[] bitSizesArr = bitSizes.ToArray();
int length = bitSizesArr.Length;
IntPtr[] coeffArray = new IntPtr[length];
NativeMethods.CoeffModulus_Create(polyModulusDegree, (ulong)length, bitSizesArr, coeffArray);
result = new List<Modulus>(length);
foreach (IntPtr sm in coeffArray)
{
result.Add(new Modulus(sm));
}
return result;
}
}
/// <summary>
/// This class contains static methods for creating a plaintext modulus easily.
/// </summary>
public static class PlainModulus
{
/// <summary>
/// Creates a prime number Modulus for use as PlainModulus encryption
/// parameter that supports batching with a given PolyModulusDegree.
/// </summary>
/// <param name="polyModulusDegree">The value of the PolyModulusDegree
/// encryption parameter</param>
/// <param name="bitSize">The bit-length of the prime to be generated</param>
/// <exception cref="ArgumentException">if polyModulusDegree is not
/// a power-of-two or is too large</exception>
/// <exception cref="ArgumentException">if bitSize is out of bounds</exception>
/// <exception cref="InvalidOperationException">if a suitable prime could not be found</exception>
static public Modulus Batching(ulong polyModulusDegree, int bitSize)
{
return CoeffModulus.Create(
polyModulusDegree,
new int[] { bitSize }).First();
}
/// <summary>
/// Creates several prime number Modulus elements that can be used as
/// PlainModulus encryption parameters, each supporting batching with a given
/// PolyModulusDegree.
/// </summary>
/// <param name="polyModulusDegree">The value of the PolyModulusDegree
/// encryption parameter</param>
/// <param name="bitSizes">The bit-lengths of the primes to be generated</param>
/// <exception cref="ArgumentException">if polyModulusDegree is not
/// a power-of-two or is too large</exception>
/// <exception cref="ArgumentException">if bitSizes is too large or if its
/// elements are out of bounds</exception>
/// <exception cref="InvalidOperationException">if not enough suitable primes could be found</exception>
static public IEnumerable<Modulus> Batching(
ulong polyModulusDegree, IEnumerable<int> bitSizes)
{
return CoeffModulus.Create(polyModulusDegree, bitSizes);
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.Research.SEAL
{
[Guid("A7AAD62F-3A48-4188-B6C3-523C294CFDAD")]
static class NativeMethods
{
private const string sealc = "sealc";
#region Version methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Version_Major(out byte value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Version_Minor(out byte value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Version_Patch(out byte value);
#endregion
#region BigUInt methods
[DllImport(sealc, EntryPoint = "BigUInt_Create1", PreserveSig = false)]
internal static extern void BigUInt_Create(out IntPtr bigUInt);
[DllImport(sealc, EntryPoint = "BigUInt_Create2", PreserveSig = false)]
internal static extern void BigUInt_Create(int bitCount, out IntPtr bigUInt);
[DllImport(sealc, EntryPoint = "BigUInt_Create3", PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_Create(int bitCount, string hexString, out IntPtr bigUInt);
[DllImport(sealc, EntryPoint = "BigUInt_Create4", PreserveSig = false)]
internal static extern void BigUInt_Create(int bitCount, ulong value, out IntPtr bigUInt);
[DllImport(sealc, EntryPoint = "BigUInt_Create5", PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_Create(string hexString, out IntPtr bigUInt);
[DllImport(sealc, EntryPoint = "BigUInt_Create6", PreserveSig = false)]
internal static extern void BigUInt_Create(IntPtr copy, out IntPtr bigUInt);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_IsAlias(IntPtr thisptr, out bool isAlias);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_BitCount(IntPtr thisptr, out int bitCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_ByteCount(IntPtr thisptr, out ulong byteCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_UInt64Count(IntPtr thisptr, out ulong uint64Count);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_IsZero(IntPtr thisptr, out bool isZero);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_Get(IntPtr thisptr, ulong index, out byte value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_GetU64(IntPtr thisptr, ulong index, out ulong value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_GetSignificantBitCount(IntPtr thisptr, out int significantBitCount);
[DllImport(sealc, EntryPoint = "BigUInt_Set1", PreserveSig = false)]
internal static extern void BigUInt_Set(IntPtr thisptr, ulong index, byte value);
[DllImport(sealc, EntryPoint = "BigUInt_Set2", PreserveSig = false)]
internal static extern void BigUInt_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, EntryPoint = "BigUInt_Set3", PreserveSig = false)]
internal static extern void BigUInt_Set(IntPtr thisptr, ulong value);
[DllImport(sealc, EntryPoint = "BigUInt_Set4", PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_Set(IntPtr thisptr, string assign);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_SetZero(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_Resize(IntPtr thisptr, int bitCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_Equals(IntPtr thisptr, IntPtr compare, out bool result);
[DllImport(sealc, EntryPoint = "BigUInt_CompareTo1", PreserveSig = false)]
internal static extern void BigUInt_CompareTo(IntPtr thisptr, IntPtr compare, out int result);
[DllImport(sealc, EntryPoint = "BigUInt_CompareTo2", PreserveSig = false)]
internal static extern void BigUInt_CompareTo(IntPtr thisptr, ulong compare, out int result);
[DllImport(sealc, EntryPoint = "BigUInt_DivideRemainder1", PreserveSig = false)]
internal static extern void BigUInt_DivideRemainder(IntPtr thisptr, IntPtr operand2, IntPtr remainder, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_DivideRemainder2", PreserveSig = false)]
internal static extern void BigUInt_DivideRemainder(IntPtr thisptr, ulong operand2, IntPtr remainder, out IntPtr result);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_ToString(IntPtr thisptr, StringBuilder outstr, out ulong length);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_ToDecimalString(IntPtr thisptr, StringBuilder outstr, out ulong length);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_DuplicateTo(IntPtr thisptr, IntPtr destination);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void BigUInt_DuplicateFrom(IntPtr thisptr, IntPtr value);
[DllImport(sealc, EntryPoint = "BigUInt_ModuloInvert1", PreserveSig = false)]
internal static extern void BigUInt_ModuloInvert(IntPtr thisptr, IntPtr modulus, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_ModuloInvert2", PreserveSig = false)]
internal static extern void BigUInt_ModuloInvert(IntPtr thisptr, ulong modulus, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_TryModuloInvert1", PreserveSig = false)]
internal static extern void BigUInt_TryModuloInvert(IntPtr thisptr, IntPtr modulus, IntPtr inverse, out bool result);
[DllImport(sealc, EntryPoint = "BigUInt_TryModuloInvert2", PreserveSig = false)]
internal static extern void BigUInt_TryModuloInvert(IntPtr thisptr, ulong modulus, IntPtr inverse, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_OperatorNeg(IntPtr thisptr, out IntPtr result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_OperatorTilde(IntPtr thisptr, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorPlus1", PreserveSig = false)]
internal static extern void BigUInt_OperatorPlus(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorPlus2", PreserveSig = false)]
internal static extern void BigUInt_OperatorPlus(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorMinus1", PreserveSig = false)]
internal static extern void BigUInt_OperatorMinus(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorMinus2", PreserveSig = false)]
internal static extern void BigUInt_OperatorMinus(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorMult1", PreserveSig = false)]
internal static extern void BigUInt_OperatorMult(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorMult2", PreserveSig = false)]
internal static extern void BigUInt_OperatorMult(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorDiv1", PreserveSig = false)]
internal static extern void BigUInt_OperatorDiv(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorDiv2", PreserveSig = false)]
internal static extern void BigUInt_OperatorDiv(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorXor1", PreserveSig = false)]
internal static extern void BigUInt_OperatorXor(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorXor2", PreserveSig = false)]
internal static extern void BigUInt_OperatorXor(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorAnd1", PreserveSig = false)]
internal static extern void BigUInt_OperatorAnd(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorAnd2", PreserveSig = false)]
internal static extern void BigUInt_OperatorAnd(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorOr1", PreserveSig = false)]
internal static extern void BigUInt_OperatorOr(IntPtr thisptr, IntPtr operand, out IntPtr result);
[DllImport(sealc, EntryPoint = "BigUInt_OperatorOr2", PreserveSig = false)]
internal static extern void BigUInt_OperatorOr(IntPtr thisptr, ulong operand, out IntPtr result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_OperatorShiftLeft(IntPtr thisptr, int shift, out IntPtr result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_OperatorShiftRight(IntPtr thisptr, int shift, out IntPtr result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_ToDouble(IntPtr thisptr, out double result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BigUInt_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes);
#endregion
#region EncryptionParameterQualifiers methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_Create(IntPtr copy, out IntPtr epq);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_ParametersSet(IntPtr thisptr, out bool parametersSet);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_UsingFFT(IntPtr thisptr, out bool usingFFT);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_UsingNTT(IntPtr thisptr, out bool usingNTT);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_UsingBatching(IntPtr thisptr, out bool usingBatching);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_UsingFastPlainLift(IntPtr thisptr, out bool usingFastPlainLift);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_UsingDescendingModulusChain(IntPtr thisptr, out bool usingDescendingModulusChain);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EPQ_SecLevel(IntPtr thisptr, out int secLevel);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void EPQ_ParameterErrorName(IntPtr thisptr, StringBuilder outstr, out ulong length);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void EPQ_ParameterErrorMessage(IntPtr thisptr, StringBuilder outstr, out ulong length);
#endregion
#region Modulus methods
[DllImport(sealc, EntryPoint = "Modulus_Create1", PreserveSig = false)]
internal static extern void Modulus_Create(ulong value, out IntPtr smallModulus);
[DllImport(sealc, EntryPoint = "Modulus_Create2", PreserveSig = false)]
internal static extern void Modulus_Create(IntPtr copy, out IntPtr smallModulus);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_IsZero(IntPtr thisptr, out bool isZero);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_IsPrime(IntPtr thisptr, out bool isPrime);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_Value(IntPtr thisptr, out ulong value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_BitCount(IntPtr thisptr, out int bitCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_UInt64Count(IntPtr thisptr, out ulong uint64Count);
[DllImport(sealc, EntryPoint = "Modulus_Set1", PreserveSig = false)]
internal static extern void Modulus_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, EntryPoint = "Modulus_Set2", PreserveSig = false)]
internal static extern void Modulus_Set(IntPtr thisptr, ulong value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_ConstRatio(
IntPtr thisptr,
ulong length,
[MarshalAs(UnmanagedType.LPArray)] ulong[] ratio);
[DllImport(sealc, EntryPoint = "Modulus_Equals1", PreserveSig = false)]
internal static extern void Modulus_Equals(IntPtr thisptr, IntPtr other, out bool result);
[DllImport(sealc, EntryPoint = "Modulus_Equals2", PreserveSig = false)]
internal static extern void Modulus_Equals(IntPtr thisptr, ulong other, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Modulus_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes);
#endregion
#region EncryptionParameters methods
[DllImport(sealc, EntryPoint = "EncParams_Create1", PreserveSig = false)]
internal static extern void EncParams_Create(byte scheme, out IntPtr encParams);
[DllImport(sealc, EntryPoint = "EncParams_Create2", PreserveSig = false)]
internal static extern void EncParams_Create(IntPtr copy, out IntPtr encParams);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_GetPolyModulusDegree(IntPtr thisptr, out ulong polyModulusDegree);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_SetPolyModulusDegree(IntPtr thisptr, ulong polyModulusDegree);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_GetCoeffModulus(
IntPtr thisptr,
ref ulong length,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffs);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_SetCoeffModulus(
IntPtr thisptr,
ulong length,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffs);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_GetScheme(IntPtr thisptr, out byte scheme);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_GetParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_GetPlainModulus(IntPtr thisptr, out IntPtr plainModulus);
[DllImport(sealc, EntryPoint = "EncParams_SetPlainModulus1", PreserveSig = false)]
internal static extern void EncParams_SetPlainModulus(IntPtr thisptr, IntPtr plainModulus);
[DllImport(sealc, EntryPoint = "EncParams_SetPlainModulus2", PreserveSig = false)]
internal static extern void EncParams_SetPlainModulus(IntPtr thisptr, ulong plainModulus);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_Equals(IntPtr thisptr, IntPtr otherptr, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void EncParams_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes);
#endregion
#region CoeffModulus methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void CoeffModulus_MaxBitCount(ulong polyModulusDegree, int secLevel, out int bitCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void CoeffModulus_BFVDefault(
ulong polyModulusDegree,
int secLevel,
ref ulong length,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffArray);
[DllImport(sealc, PreserveSig = false)]
internal static extern void CoeffModulus_Create(
ulong polyModulusDegree,
ulong length,
int[] bitSizes,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffArray);
#endregion
#region SEALContext methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_Create(
IntPtr encryptionParams,
bool expandModChain,
int secLevel,
out IntPtr context);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_KeyParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_FirstParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_LastParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_ParametersSet(IntPtr thisptr, out bool paramsSet);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_ParameterErrorName(IntPtr thisptr, byte[] outstr, out ulong length);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_ParameterErrorMessage(IntPtr thisptr, byte[] outstr, out ulong length);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_KeyContextData(IntPtr thisptr, out IntPtr contextData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_FirstContextData(IntPtr thisptr, out IntPtr contextData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_LastContextData(IntPtr thisptr, out IntPtr contextData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_GetContextData(IntPtr thisptr, ulong[] parmsId, out IntPtr contextData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SEALContext_UsingKeyswitching(IntPtr thisptr, out bool usingKeySwitching);
#endregion
#region ContextData methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_TotalCoeffModulus(IntPtr thisptr, ref ulong count, ulong[] totalCoeffModulus);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_TotalCoeffModulusBitCount(IntPtr thisptr, out int bitCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_Parms(IntPtr thisptr, out IntPtr parms);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_Qualifiers(IntPtr thisptr, out IntPtr epq);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_CoeffDivPlainModulus(IntPtr thisptr, ref ulong count, ulong[] coefDivPlainMod);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_PlainUpperHalfThreshold(IntPtr thisptr, out ulong puht);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_PlainUpperHalfIncrement(IntPtr thisptr, ref ulong count, ulong[] puhi);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_UpperHalfThreshold(IntPtr thisptr, ref ulong count, ulong[] uht);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_UpperHalfIncrement(IntPtr thisptr, ref ulong count, ulong[] uhi);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_PrevContextData(IntPtr thisptr, out IntPtr prevContextData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_NextContextData(IntPtr thisptr, out IntPtr nextContextData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ContextData_ChainIndex(IntPtr thisptr, out ulong index);
#endregion
#region Evaluator methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Create(IntPtr sealContext, out IntPtr evaluator);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Negate(IntPtr thisptr, IntPtr encrypted, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Add(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_AddMany(IntPtr thisptr, ulong count, IntPtr[] encrypteds, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_AddPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Sub(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_SubPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Multiply(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_MultiplyMany(IntPtr thisptr, ulong count, IntPtr[] encrypteds, IntPtr relinKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_MultiplyPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Square(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Relinearize(IntPtr thisptr, IntPtr encrypted, IntPtr relinKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "Evaluator_ModSwitchToNext1", PreserveSig = false)]
internal static extern void Evaluator_ModSwitchToNext(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "Evaluator_ModSwitchToNext2", PreserveSig = false)]
internal static extern void Evaluator_ModSwitchToNext(IntPtr thisptr, IntPtr plain, IntPtr destination);
[DllImport(sealc, EntryPoint = "Evaluator_ModSwitchTo1", PreserveSig = false)]
internal static extern void Evaluator_ModSwitchTo(IntPtr thisptr, IntPtr encrypted, ulong[] parmsId, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "Evaluator_ModSwitchTo2", PreserveSig = false)]
internal static extern void Evaluator_ModSwitchTo(IntPtr thisptr, IntPtr plain, ulong[] parmsId, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_RescaleToNext(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_RescaleTo(IntPtr thisptr, IntPtr encrypted, ulong[] parmsId, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_Exponentiate(IntPtr thisptr, IntPtr encrypted, ulong exponent, IntPtr relinKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "Evaluator_TransformToNTT1", PreserveSig = false)]
internal static extern void Evaluator_TransformToNTT(IntPtr thisptr, IntPtr plain, ulong[] parmsId, IntPtr destinationNTT, IntPtr pool);
[DllImport(sealc, EntryPoint = "Evaluator_TransformToNTT2", PreserveSig = false)]
internal static extern void Evaluator_TransformToNTT(IntPtr thisptr, IntPtr encrypted, IntPtr destinationNTT);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_TransformFromNTT(IntPtr thisptr, IntPtr encryptedNTT, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_ApplyGalois(IntPtr thisptr, IntPtr encrypted, uint galoisElt, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_RotateRows(IntPtr thisptr, IntPtr encrypted, int steps, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_RotateColumns(IntPtr thisptr, IntPtr encrypted, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_RotateVector(IntPtr thisptr, IntPtr encrypted, int steps, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_ComplexConjugate(IntPtr thisptr, IntPtr encrypted, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Evaluator_ContextUsingKeyswitching(IntPtr thisptr, out bool usingKeySwitching);
#endregion
#region Ciphertext methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Create1(IntPtr pool, out IntPtr cipher);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Create2(IntPtr copy, out IntPtr cipher);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Create3(IntPtr context, IntPtr pool, out IntPtr cipher);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Create4(IntPtr context, ulong[] parmsId, IntPtr pool, out IntPtr cipher);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Create5(IntPtr context, ulong[] parmsId, ulong capacity, IntPtr pool, out IntPtr cipher);
[DllImport(sealc, EntryPoint = "Ciphertext_Reserve1", PreserveSig = false)]
internal static extern void Ciphertext_Reserve(IntPtr thisptr, IntPtr context, ulong[] parmsId, ulong sizeCapacity);
[DllImport(sealc, EntryPoint = "Ciphertext_Reserve2", PreserveSig = false)]
internal static extern void Ciphertext_Reserve(IntPtr thisptr, IntPtr context, ulong sizeCapacity);
[DllImport(sealc, EntryPoint = "Ciphertext_Reserve3", PreserveSig = false)]
internal static extern void Ciphertext_Reserve(IntPtr thisptr, ulong sizeCapacity);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_UInt64Count(IntPtr thisptr, out ulong uint64Count);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_UInt64CountCapacity(IntPtr thisptr, out ulong uint64CountCapacity);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Size(IntPtr thisptr, out ulong size);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_SizeCapacity(IntPtr thisptr, out ulong sizeCapacity);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_PolyModulusDegree(IntPtr thisptr, out ulong polyModulusDegree);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_CoeffModulusSize(IntPtr thisptr, out ulong coeffModCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_ParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_SetParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, EntryPoint = "Ciphertext_Resize1", PreserveSig = false)]
internal static extern void Ciphertext_Resize(IntPtr thisptr, IntPtr context, ulong[] parms_id, ulong size);
[DllImport(sealc, EntryPoint = "Ciphertext_Resize2", PreserveSig = false)]
internal static extern void Ciphertext_Resize(IntPtr thisptr, IntPtr context, ulong size);
[DllImport(sealc, EntryPoint = "Ciphertext_Resize3", PreserveSig = false)]
internal static extern void Ciphertext_Resize(IntPtr thisptr, ulong size);
[DllImport(sealc, EntryPoint = "Ciphertext_Resize4", PreserveSig = false)]
internal static extern void Ciphertext_Resize(IntPtr thisptr, ulong size, ulong polyModulusDegree, ulong coeffModCount);
[DllImport(sealc, EntryPoint = "Ciphertext_GetDataAt1", PreserveSig = false)]
internal static extern void Ciphertext_GetDataAt(IntPtr thisptr, ulong index, out ulong data);
[DllImport(sealc, EntryPoint = "Ciphertext_GetDataAt2", PreserveSig = false)]
internal static extern void Ciphertext_GetDataAt(IntPtr thisptr, ulong polyIndex, ulong coeffIndex, out ulong data);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_SetDataAt(IntPtr thisptr, ulong index, ulong value);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_IsNTTForm(IntPtr thisptr, out bool isNTTForm);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_SetIsNTTForm(IntPtr thisptr, bool isNTTForm);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Scale(IntPtr thisptr, out double scale);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_SetScale(IntPtr thisptr, double scale);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Release(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_IsTransparent(IntPtr thisptr, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Pool(IntPtr thisptr, out IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Ciphertext_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
#endregion
#region Plaintext methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Create1(IntPtr memoryPoolHandle, out IntPtr plainText);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Create2(ulong coeffCount, IntPtr memoryPoolHandle, out IntPtr plainText);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Create3(ulong capacity, ulong coeffCount, IntPtr memoryPoolHandle, out IntPtr plainText);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void Plaintext_Create4(string hexPoly, IntPtr memoryPoolHandle, out IntPtr plainText);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Create5(IntPtr copy, out IntPtr plainText);
[DllImport(sealc, EntryPoint = "Plaintext_Set1", PreserveSig = false)]
internal static extern void Plaintext_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, EntryPoint = "Plaintext_Set2", PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void Plaintext_Set(IntPtr thisptr, string hexPoly);
[DllImport(sealc, EntryPoint = "Plaintext_Set3", PreserveSig = false)]
internal static extern void Plaintext_Set(IntPtr thisptr, ulong constCoeff);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_CoeffCount(IntPtr thisptr, out ulong coeffCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_CoeffAt(IntPtr thisptr, ulong index, out ulong coeff);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_SetCoeffAt(IntPtr thisptr, ulong index, ulong value);
[DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
internal static extern void Plaintext_ToString(IntPtr thisptr, StringBuilder outstr, out ulong length);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_IsNTTForm(IntPtr thisptr, out bool isNTTForm);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_IsZero(IntPtr thisptr, out bool isZero);
[DllImport(sealc, EntryPoint = "Plaintext_SetZero1", PreserveSig = false)]
internal static extern void Plaintext_SetZero(IntPtr thisptr);
[DllImport(sealc, EntryPoint = "Plaintext_SetZero2", PreserveSig = false)]
internal static extern void Plaintext_SetZero(IntPtr thisptr, ulong startCoeff);
[DllImport(sealc, EntryPoint = "Plaintext_SetZero3", PreserveSig = false)]
internal static extern void Plaintext_SetZero(IntPtr thisptr, ulong startCoeff, ulong length);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_GetParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_SetParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Reserve(IntPtr thisptr, ulong capacity);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Resize(IntPtr thisptr, ulong coeffCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_ShrinkToFit(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Release(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Capacity(IntPtr thisptr, out ulong capacity);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_UInt64Count(IntPtr thisptr, out ulong uint64Count);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_UInt64CountCapacity(IntPtr thisptr, out ulong uint64CountCapacity);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_SignificantCoeffCount(IntPtr thisptr, out ulong significantCoeffCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_NonZeroCoeffCount(IntPtr thisptr, out ulong nonZeroCoeffCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Scale(IntPtr thisptr, out double scale);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_SetScale(IntPtr thisptr, double scale);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Equals(IntPtr thisptr, IntPtr otherptr, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_SwapData(IntPtr thisptr, ulong count, ulong[] newData);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Pool(IntPtr thisptr, out IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Plaintext_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
#endregion
#region KSwitchKeys methods
[DllImport(sealc, EntryPoint = "KSwitchKeys_Create1", PreserveSig = false)]
internal static extern void KSwitchKeys_Create(out IntPtr kswitchKeys);
[DllImport(sealc, EntryPoint = "KSwitchKeys_Create2", PreserveSig = false)]
internal static extern void KSwitchKeys_Create(IntPtr copy, out IntPtr kswitchKeys);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_Set(IntPtr thisptr, IntPtr assignptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_Size(IntPtr thisptr, out ulong size);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_ClearDataAndReserve(IntPtr thisptr, ulong size);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_RawSize(IntPtr thisptr, out ulong keyCount);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_GetKeyList(IntPtr thisptr, ulong index, ref ulong count, IntPtr[] key_list);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_AddKeyList(IntPtr thisptr, ulong count, IntPtr[] key_list);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_GetParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_SetParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_Pool(IntPtr thisptr, out IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KSwitchKeys_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
#endregion
#region GaloisKeys methods
[DllImport(sealc, EntryPoint = "GaloisKeys_GetIndex", PreserveSig = false)]
internal static extern void GaloisKeys_GetIndex(uint galoisElt, out ulong index);
#endregion
#region KeyGenerator methods
[DllImport(sealc, EntryPoint = "KeyGenerator_Create1", PreserveSig = false)]
internal static extern void KeyGenerator_Create(IntPtr sealContext, out IntPtr keyGenerator);
[DllImport(sealc, EntryPoint = "KeyGenerator_Create2", PreserveSig = false)]
internal static extern void KeyGenerator_Create(IntPtr sealContext, IntPtr secretKey, out IntPtr keyGenerator);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KeyGenerator_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KeyGenerator_RelinKeys(IntPtr thisptr, bool save_seed, out IntPtr relin_keys);
[DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysAll", PreserveSig = false)]
internal static extern void KeyGenerator_GaloisKeysAll(IntPtr thisptr, bool save_seed, out IntPtr galoisKeys);
[DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysFromElts", PreserveSig = false)]
internal static extern void KeyGenerator_GaloisKeysFromElts(IntPtr thisptr, ulong count, uint[] galoisElts, bool save_seed, out IntPtr galoisKeys);
[DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysFromSteps", PreserveSig = false)]
internal static extern void KeyGenerator_GaloisKeysFromSteps(IntPtr thisptr, ulong count, int[] steps, bool save_seed, out IntPtr galoisKeys);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KeyGenerator_PublicKey(IntPtr thisptr, out IntPtr publicKey);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KeyGenerator_SecretKey(IntPtr thisptr, out IntPtr secretKey);
[DllImport(sealc, PreserveSig = false)]
internal static extern void KeyGenerator_ContextUsingKeyswitching(IntPtr thisptr, out bool result);
#endregion
#region RelinKeys methods
[DllImport(sealc, EntryPoint = "RelinKeys_GetIndex", PreserveSig = false)]
internal static extern void RelinKeys_GetIndex(ulong keyPower, out ulong index);
#endregion
#region PublicKey methods
[DllImport(sealc, EntryPoint = "PublicKey_Create1", PreserveSig = false)]
internal static extern void PublicKey_Create(out IntPtr publicKey);
[DllImport(sealc, EntryPoint = "PublicKey_Create2", PreserveSig = false)]
internal static extern void PublicKey_Create(IntPtr copy, out IntPtr publicKey);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_Data(IntPtr thisptr, out IntPtr data);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_ParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_Pool(IntPtr thisptr, out IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void PublicKey_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
#endregion
#region SecretKey methods
[DllImport(sealc, EntryPoint = "SecretKey_Create1", PreserveSig = false)]
internal static extern void SecretKey_Create(out IntPtr secretKey);
[DllImport(sealc, EntryPoint = "SecretKey_Create2", PreserveSig = false)]
internal static extern void SecretKey_Create(IntPtr copy, out IntPtr secretKey);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_Set(IntPtr thisptr, IntPtr assign);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_Data(IntPtr thisptr, out IntPtr data);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_ParmsId(IntPtr thisptr, ulong[] parmsId);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_Pool(IntPtr thisptr, out IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_SaveSize(IntPtr thisptr, byte comprMode, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
[DllImport(sealc, PreserveSig = false)]
internal static extern void SecretKey_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
#endregion
#region MemoryManager methods
[DllImport(sealc, EntryPoint = "MemoryManager_GetPool1", PreserveSig = false)]
internal static extern void MemoryManager_GetPool(int profOpt, bool clearOnDestruction, out IntPtr handle);
[DllImport(sealc, EntryPoint = "MemoryManager_GetPool2", PreserveSig = false)]
internal static extern void MemoryManager_GetPool(out IntPtr handle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryManager_SwitchProfile(IntPtr newProfile);
#endregion
#region MMProf methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void MMProf_CreateGlobal(out IntPtr profile);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MMProf_CreateFixed(IntPtr pool, out IntPtr profile);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MMProf_CreateNew(out IntPtr profile);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MMProf_CreateThreadLocal(out IntPtr profile);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MMProf_GetPool(IntPtr thisptr, out IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MMProf_Destroy(IntPtr thisptr);
#endregion
#region MemoryPoolHandle methods
[DllImport(sealc, EntryPoint = "MemoryPoolHandle_Create1", PreserveSig = false)]
internal static extern void MemoryPoolHandle_Create(out IntPtr handlePtr);
[DllImport(sealc, EntryPoint = "MemoryPoolHandle_Create2", PreserveSig = false)]
internal static extern void MemoryPoolHandle_Create(IntPtr other, out IntPtr handlePtr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_Set(IntPtr thisptr, IntPtr assignptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_Global(out IntPtr handlePtr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_ThreadLocal(out IntPtr handlePtr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_New(bool clearOnDestruction, out IntPtr handlePtr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_PoolCount(IntPtr thisptr, out ulong count);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_AllocByteCount(IntPtr thisptr, out ulong count);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_UseCount(IntPtr thisptr, out long count);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_IsInitialized(IntPtr thisptr, out bool initialized);
[DllImport(sealc, PreserveSig = false)]
internal static extern void MemoryPoolHandle_Equals(IntPtr thisptr, IntPtr otherptr, out bool result);
#endregion
#region Encryptor methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_Create(IntPtr context, IntPtr publicKey, IntPtr secretKey, out IntPtr encryptor);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_SetPublicKey(IntPtr thisptr, IntPtr publicKey);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_SetSecretKey(IntPtr thisptr, IntPtr secretKey);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_Encrypt(IntPtr thisptr, IntPtr plaintext, IntPtr destination, IntPtr poolHandle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_EncryptZero1(IntPtr thisptr, ulong[] parmsId, IntPtr destination, IntPtr poolHandle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_EncryptZero2(IntPtr thisptr, IntPtr destination, IntPtr poolHandle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_EncryptSymmetric(IntPtr thisptr, IntPtr plaintext, bool save_seed, IntPtr destination, IntPtr poolHandle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_EncryptZeroSymmetric1(IntPtr thisptr, ulong[] parmsId, bool save_seed, IntPtr destination, IntPtr poolHandle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_EncryptZeroSymmetric2(IntPtr thisptr, bool save_seed, IntPtr destination, IntPtr poolHandle);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Encryptor_Destroy(IntPtr thisptr);
#endregion
#region Decryptor methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Decryptor_Create(IntPtr context, IntPtr secretKey, out IntPtr decryptor);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Decryptor_Destroy(IntPtr thisptr);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Decryptor_Decrypt(IntPtr thisptr, IntPtr encrypted, IntPtr destination);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Decryptor_InvariantNoiseBudget(IntPtr thisptr, IntPtr encrypted, out int invariantNoiseBudget);
#endregion
#region CKKSEncoder methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void CKKSEncoder_Create(IntPtr context, out IntPtr ckksEncoder);
[DllImport(sealc, PreserveSig = false)]
internal static extern void CKKSEncoder_Destroy(IntPtr thisptr);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Encode1", PreserveSig = false)]
internal static extern void CKKSEncoder_EncodeDouble(IntPtr thisptr, ulong valueCount, double[] values, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Encode2", PreserveSig = false)]
internal static extern void CKKSEncoder_EncodeComplex(IntPtr thisptr, ulong valueCount, double[] values, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Encode3", PreserveSig = false)]
internal static extern void CKKSEncoder_Encode(IntPtr thisptr, double value, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Encode4", PreserveSig = false)]
internal static extern void CKKSEncoder_Encode(IntPtr thisptr, double valueRe, double valueIm, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Encode5", PreserveSig = false)]
internal static extern void CKKSEncoder_Encode(IntPtr thisptr, long value, ulong[] parms_id, IntPtr destination);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Decode1", PreserveSig = false)]
internal static extern void CKKSEncoder_DecodeDouble(IntPtr thisptr, IntPtr plain, ref ulong valueCount, double[] values, IntPtr pool);
[DllImport(sealc, EntryPoint = "CKKSEncoder_Decode2", PreserveSig = false)]
internal static extern void CKKSEncoder_DecodeComplex(IntPtr thisptr, IntPtr plain, ref ulong valueCount, double[] values, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void CKKSEncoder_SlotCount(IntPtr thisptr, out ulong slotCount);
#endregion
#region BatchEncoder methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void BatchEncoder_Create(IntPtr context, out IntPtr batchEncoder);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BatchEncoder_Destroy(IntPtr thisptr);
[DllImport(sealc, EntryPoint = "BatchEncoder_Encode1", PreserveSig = false)]
internal static extern void BatchEncoder_Encode(IntPtr thisptr, ulong count, ulong[] values, IntPtr destination);
[DllImport(sealc, EntryPoint = "BatchEncoder_Encode2", PreserveSig = false)]
internal static extern void BatchEncoder_Encode(IntPtr thisptr, ulong count, long[] values, IntPtr destination);
[DllImport(sealc, EntryPoint = "BatchEncoder_Encode3", PreserveSig = false)]
internal static extern void BatchEncoder_Encode(IntPtr thisptr, IntPtr plain, IntPtr pool);
[DllImport(sealc, EntryPoint = "BatchEncoder_Decode1", PreserveSig = false)]
internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, ref ulong count, ulong[] destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "BatchEncoder_Decode2", PreserveSig = false)]
internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, ref ulong count, long[] destination, IntPtr pool);
[DllImport(sealc, EntryPoint = "BatchEncoder_Decode3", PreserveSig = false)]
internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, IntPtr pool);
[DllImport(sealc, PreserveSig = false)]
internal static extern void BatchEncoder_GetSlotCount(IntPtr thisptr, out ulong slotCount);
#endregion
#region IntegerEncoder methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_Create(IntPtr context, out IntPtr encoder);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_Destroy(IntPtr thisptr);
[DllImport(sealc, EntryPoint = "IntegerEncoder_Encode1", PreserveSig = false)]
internal static extern void IntegerEncoder_Encode(IntPtr thisptr, int value, IntPtr plain);
[DllImport(sealc, EntryPoint = "IntegerEncoder_Encode2", PreserveSig = false)]
internal static extern void IntegerEncoder_Encode(IntPtr thisptr, uint value, IntPtr plain);
[DllImport(sealc, EntryPoint = "IntegerEncoder_Encode3", PreserveSig = false)]
internal static extern void IntegerEncoder_Encode(IntPtr thisptr, ulong value, IntPtr plain);
[DllImport(sealc, EntryPoint = "IntegerEncoder_Encode4", PreserveSig = false)]
internal static extern void IntegerEncoder_Encode(IntPtr thisptr, long value, IntPtr plain);
[DllImport(sealc, EntryPoint = "IntegerEncoder_Encode5", PreserveSig = false)]
internal static extern void IntegerEncoder_Encode(IntPtr thisptr, IntPtr bigUInt, IntPtr plain);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_DecodeUInt32(IntPtr thisptr, IntPtr plain, out uint result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_DecodeUInt64(IntPtr thisptr, IntPtr plain, out ulong result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_DecodeInt32(IntPtr thisptr, IntPtr plain, out int result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_DecodeInt64(IntPtr thisptr, IntPtr plain, out long result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_DecodeBigUInt(IntPtr thisptr, IntPtr plain, out IntPtr bigUInt);
[DllImport(sealc, PreserveSig = false)]
internal static extern void IntegerEncoder_PlainModulus(IntPtr thisptr, out IntPtr smallModulus);
#endregion
#region ValCheck methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_Plaintext_IsValidFor(IntPtr plaintext, IntPtr context, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_Ciphertext_IsValidFor(IntPtr ciphertext, IntPtr context, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_SecretKey_IsValidFor(IntPtr secretKey, IntPtr context, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_PublicKey_IsValidFor(IntPtr publicKey, IntPtr context, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_KSwitchKeys_IsValidFor(IntPtr kswitchKeys, IntPtr context, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_RelinKeys_IsValidFor(IntPtr relinKeys, IntPtr context, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void ValCheck_GaloisKeys_IsValidFor(IntPtr galoisKeys, IntPtr context, out bool result);
#endregion
#region Serialization methods
[DllImport(sealc, PreserveSig = false)]
internal static extern void Serialization_SEALMagic(out ushort result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Serialization_SEALHeaderSize(out byte result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Serialization_IsSupportedComprMode(byte comprMode, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Serialization_ComprModeDefault(out byte result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Serialization_IsCompatibleVersion(byte[] headerptr, ulong size, out bool result);
[DllImport(sealc, PreserveSig = false)]
internal static extern void Serialization_IsValidHeader(byte[] headerptr, ulong size, out bool result);
#endregion
public static class Errors
{
public const uint NoError = 0;
public const uint InsufficientBuffer = 122;
public const uint BadArguments = 160;
public const uint InvalidIndex = 1413;
public const uint InvalidOperation = 4317;
public const uint HRPointer = 0x80004003;
public const uint HRInvalidIndex = 0x80070585;
public const uint HRInvalidOperation = 0x800710DD;
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.Text;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Identify a set of Encryption Parameters
/// </summary>
public class ParmsId : IEquatable<ParmsId>
{
/// <summary>
/// Create an instance of ParmsId
/// </summary>
public ParmsId()
{
}
/// <summary>
/// Create an instance of ParmsId by copying other instance
/// </summary>
/// <param name="other">Instance to copy</param>
public ParmsId(ParmsId other)
{
if (null == other)
throw new ArgumentNullException(nameof(other));
CopyId(this, other.Block);
}
/// <summary>
/// Create an instance of ParmsId by copying the input array
/// </summary>
/// <param name="id">Array to copy</param>
private ParmsId(ulong[] id)
{
if (null == id)
throw new ArgumentNullException(nameof(id));
if (id.Length != ULongCount)
throw new ArgumentException($"id length should be {ULongCount}");
CopyId(this, id);
}
/// <summary>
/// Array that contains the Params Id hash block
/// </summary>
public ulong[] Block { get; } = new ulong[4] { 0, 0, 0, 0 };
/// <summary>
/// Copy an input array to the ParmsId hash block
/// </summary>
private static void CopyId(ParmsId dest, ulong[] src)
{
int idx = 0;
foreach (ulong ul in src)
{
dest.Block[idx++] = ul;
}
}
/// <summary>
/// Convert ParmsId to a string representation.
/// </summary>
public override string ToString()
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < ULongCount; i++)
{
byte[] bytes = BitConverter.GetBytes(Block[i]);
for (int b = bytes.Length - 1; b >= 0; b--)
{
result.Append(BitConverter.ToString(bytes, b, length: 1));
}
if (i < (ULongCount - 1))
result.Append(" ");
}
return result.ToString();
}
/// <summary>
/// Hash code for this object
/// </summary>
public override int GetHashCode()
{
return Utilities.ComputeArrayHashCode(Block);
}
/// <summary>
/// Whether the input object is equivalent to this object
/// </summary>
public override bool Equals(object obj)
{
return Equals(obj as ParmsId);
}
/// <summary>
/// Whether the input object is equivalent to this object
/// </summary>
public bool Equals(ParmsId other)
{
if (null == other)
return false;
for (int i = 0; i < ULongCount; i++)
{
if (Block[i] != other.Block[i])
return false;
}
return true;
}
/// <summary>
/// Return whether parms1 equals parms2.
/// </summary>
public static bool operator ==(ParmsId parms1, ParmsId parms2)
{
object obj1 = parms1 as object;
object obj2 = parms2 as object;
if (null == obj1 && null == obj2)
return true;
if (null == obj1)
return false;
return parms1.Equals(parms2);
}
/// <summary>
/// Return whether parms1 does not equal parms2.
/// </summary>
public static bool operator !=(ParmsId parms1, ParmsId parms2)
{
object obj1 = parms1 as object;
object obj2 = parms2 as object;
if (null == obj1 && null == obj2)
return false;
if (null == obj1)
return true;
return !parms1.Equals(parms2);
}
/// <summary>
/// ParmsId with a Zero hash block
/// </summary>
public static ParmsId Zero = new ParmsId(new ulong[4] { 0, 0, 0, 0 });
/// <summary>
/// Number of elements in the hash block array
/// </summary>
private const int ULongCount = 4;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Class to store a plaintext element.
/// </summary>
/// <remarks>
/// <para>
/// Class to store a plaintext element. The data for the plaintext is
/// a polynomial with coefficients modulo the plaintext modulus. The degree
/// of the plaintext polynomial must be one less than the degree of the
/// polynomial modulus. The backing array always allocates one 64-bit word
/// per each coefficient of the polynomial.
/// </para>
/// <para>
/// Memory Management
/// The coefficient count of a plaintext refers to the number of word-size
/// coefficients in the plaintext, whereas its capacity refers to the number
/// of word-size coefficients that fit in the current memory allocation. In
/// high-performance applications unnecessary re-allocations should be avoided
/// by reserving enough memory for the plaintext to begin with either by
/// providing the desired capacity to the constructor as an extra argument, or
/// by calling the reserve function at any time.
///
/// When the scheme is SchemeType.BFV each coefficient of a plaintext is
/// a 64-bit word, but when the scheme is SchemeType.CKKS the plaintext is
/// by default stored in an NTT transformed form with respect to each of the
/// primes in the coefficient modulus. Thus, the size of the allocation that
/// is needed is the size of the coefficient modulus (number of primes) times
/// the degree of the polynomial modulus. In addition, a valid CKKS plaintext
/// will also store the ParmsId for the corresponding encryption parameters.
/// </para>
/// <para>
/// Thread Safety
/// In general, reading from plaintext is thread-safe as long as no other
/// thread is concurrently mutating it. This is due to the underlying data
/// structure storing the plaintext not being thread-safe.
/// </para>
/// </remarks>
/// <seealso cref="Ciphertext">See Ciphertext for the class that stores ciphertexts.</seealso>
public class Plaintext : NativeObject, IEquatable<Plaintext>
{
/// <summary>
/// Constructs an empty plaintext allocating no memory.
/// </summary>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Plaintext(MemoryPoolHandle pool = null)
{
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Plaintext_Create1(poolPtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Constructs a plaintext representing a constant polynomial 0. The
/// coefficient count of the polynomial is set to the given value. The
/// capacity is set to the same value.
/// </summary>
/// <param name="coeffCount">The number of (zeroed) coefficients in the
/// plaintext polynomial</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentException">if coeffCount is negative</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Plaintext(ulong coeffCount, MemoryPoolHandle pool = null)
{
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Plaintext_Create2(coeffCount, poolPtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Constructs a plaintext representing a constant polynomial 0. The
/// coefficient count of the polynomial and the capacity are set to the
/// given values.
/// </summary>
/// <param name="capacity">The capacity</param>
/// <param name="coeffCount">The number of (zeroed) coefficients in the
/// plaintext polynomial</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentException">if capacity is less than coeffCount</exception>
/// <exception cref="ArgumentException">if coeffCount is negative</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Plaintext(ulong capacity, ulong coeffCount, MemoryPoolHandle pool = null)
{
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Plaintext_Create3(capacity, coeffCount, poolPtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Constructs a plaintext from a given hexadecimal string describing the
/// plaintext polynomial.
/// </summary>
/// <remarks>
/// The string description of the polynomial must adhere to the format
/// returned by ToString(), which is of the form "7FFx^3 + 1x^1 + 3"
/// and summarized by the following
/// rules:
/// 1. Terms are listed in order of strictly decreasing exponent
/// 2. Coefficient values are non-negative and in hexadecimal format (upper
/// and lower case letters are both supported)
/// 3. Exponents are positive and in decimal format
/// 4. Zero coefficient terms (including the constant term) may be (but do
/// not have to be) omitted
/// 5. Term with the exponent value of one must be exactly written as x^1
/// 6. Term with the exponent value of zero (the constant term) must be written
/// as just a hexadecimal number without exponent
/// 7. Terms must be separated by exactly [space]+[space] and minus is not
/// allowed
/// 8. Other than the +, no other terms should have whitespace
/// </remarks>
/// <param name="hexPoly">The formatted polynomial string specifying the plaintext
/// polynomial</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if hexPoly is null</exception>
/// <exception cref="ArgumentException">if hexPoly does not adhere to the expected
/// format</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Plaintext(string hexPoly, MemoryPoolHandle pool = null)
{
if (null == hexPoly)
throw new ArgumentNullException(nameof(hexPoly));
IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
NativeMethods.Plaintext_Create4(hexPoly, poolPtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Constructs a new plaintext by copying a given one.
/// </summary>
/// <param name="copy">The plaintext to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public Plaintext(Plaintext copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.Plaintext_Create5(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Constructs a new plaintext by copying a given one.
/// </summary>
/// <param name="copy">The plaintext to copy from</param>
/// <param name="pool">The MemoryPoolHandle pointing to a valid memory pool</param>
/// <exception cref="ArgumentNullException">if either copy or pool are null</exception>
/// <exception cref="ArgumentException">if pool is uninitialized</exception>
public Plaintext(Plaintext copy, MemoryPoolHandle pool) : this(pool)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
Set(copy);
}
/// <summary>
/// Constructs a plaintext by initializing it with a pointer to a native object.
/// </summary>
/// <param name="plaintextPtr">Pointer to native Plaintext object</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal Plaintext(IntPtr plaintextPtr, bool owned = true)
: base(plaintextPtr, owned)
{
}
/// <summary>
/// Allocates enough memory to accommodate the backing array of a plaintext
/// with given capacity.
/// </summary>
/// <param name="capacity">The capacity</param>
/// <exception cref="InvalidOperationException">if the plaintext is NTT transformed</exception>
public void Reserve(ulong capacity)
{
NativeMethods.Plaintext_Reserve(NativePtr, capacity);
}
/// <summary>
/// Allocates enough memory to accommodate the backing array of the current
/// plaintext and copies it over to the new location. This function is meant
/// to reduce the memory use of the plaintext to smallest possible and can be
/// particularly important after modulus switching.
/// </summary>
public void ShrinkToFit()
{
NativeMethods.Plaintext_ShrinkToFit(NativePtr);
}
/// <summary>
/// Resets the plaintext. This function releases any memory allocated by the
/// plaintext, returning it to the memory pool.
/// </summary>
public void Release()
{
NativeMethods.Plaintext_Release(NativePtr);
}
/// <summary>
/// Resizes the plaintext to have a given coefficient count. The plaintext
/// is automatically reallocated if the new coefficient count does not fit in
/// the current capacity.
/// </summary>
/// <param name="coeffCount">The number of coefficients in the plaintext
/// polynomial</param>
/// <exception cref="InvalidOperationException">if the plaintext is NTT transformed</exception>
public void Resize(ulong coeffCount)
{
NativeMethods.Plaintext_Resize(NativePtr, coeffCount);
}
/// <summary>
/// Copies a given plaintext to the current one.
/// </summary>
///
/// <param name="assign">The plaintext to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(Plaintext assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.Plaintext_Set(NativePtr, assign.NativePtr);
}
/// <summary>
/// Sets the value of the current plaintext to the polynomial represented by the a given hexadecimal string.
/// </summary>
///
/// <remarks>
/// <para>
/// Sets the value of the current plaintext to the polynomial represented by the a given hexadecimal string.
/// </para>
/// <para>
/// The string description of the polynomial must adhere to the format returned by <see cref="ToString()"/>,
/// which is of the form "7FFx^3 + 1x^1 + 3" and summarized by the following rules:
/// <list type="number">
/// <item><description>Terms are listed in order of strictly decreasing exponent</description></item>
/// <item><description>Coefficient values are non-negative and in hexadecimal format (upper and lower case letters are both supported)</description></item>
/// <item><description>Exponents are positive and in decimal format</description></item>
/// <item><description>Zero coefficient terms (including the constant term) may be (but do not have to be) omitted</description></item>
/// <item><description>Term with the exponent value of one is written as x^1</description></item>
/// <item><description>Term with the exponent value of zero (the constant term) is written as just a hexadecimal number without x or exponent</description></item>
/// <item><description>Terms are separated exactly by &lt;space&gt;+&lt;space&gt;</description></item>
/// <item><description>Other than the +, no other terms have whitespace</description></item>
/// </list>
/// </para>
/// </remarks>
/// <param name="hexPoly">The formatted polynomial string specifying the plaintext polynomial</param>
/// <exception cref="ArgumentException">if hexPoly does not adhere to the expected format</exception>
/// <exception cref="ArgumentException">if the coefficients of hexPoly are too wide</exception>
/// <exception cref="ArgumentNullException">if hexPoly is null</exception>
public void Set(string hexPoly)
{
if (null == hexPoly)
throw new ArgumentNullException(nameof(hexPoly));
NativeMethods.Plaintext_Set(NativePtr, hexPoly);
}
/// <summary>
/// Sets the value of the current plaintext to a given constant polynomial.
/// </summary>
///
/// <remarks>
/// Sets the value of the current plaintext to a given constant polynomial. The coefficient count
/// is set to one.
/// </remarks>
/// <param name="constCoeff">The constant coefficient</param>
public void Set(ulong constCoeff)
{
NativeMethods.Plaintext_Set(NativePtr, constCoeff);
}
/// <summary>
/// Sets a given range of coefficients of a plaintext polynomial to zero.
/// </summary>
///
/// <param name="startCoeff">The index of the first coefficient to set to zero</param>
/// <param name="length">The number of coefficients to set to zero</param>
/// <exception cref="ArgumentOutOfRangeException">if startCoeff is not within [0, CoeffCount)</exception>
/// <exception cref="ArgumentOutOfRangeException">if startCoeff + length is not within [0, CoeffCount)</exception>
/// */
public void SetZero(ulong startCoeff, ulong length)
{
try
{
NativeMethods.Plaintext_SetZero(NativePtr, startCoeff, length);
}
catch(COMException e)
{
if ((uint)e.HResult == NativeMethods.Errors.HRInvalidIndex)
throw new ArgumentOutOfRangeException("startCoeff or length out of range", e);
throw;
}
}
/// <summary>
/// Sets the plaintext polynomial coefficients to zero starting at a given
/// index.
/// </summary>
/// <param name="startCoeff">The index of the first coefficient to set to zero</param>
/// <exception cref="ArgumentOutOfRangeException">if startCoeff is not within [0, CoeffCount)</exception>
public void SetZero(ulong startCoeff)
{
try
{
NativeMethods.Plaintext_SetZero(NativePtr, startCoeff);
}
catch (COMException e)
{
if ((uint)e.HResult == NativeMethods.Errors.HRInvalidIndex)
throw new ArgumentOutOfRangeException("startCoeff or length out of range", e);
throw;
}
}
/// <summary>
/// Sets the plaintext polynomial to zero.
/// </summary>
public void SetZero()
{
NativeMethods.Plaintext_SetZero(NativePtr);
}
/// <summary>
/// Gets/set the value of a given coefficient of the plaintext polynomial.
/// </summary>
/// <param name="coeffIndex">The index of the coefficient in the plaintext polynomial</param>
/// <exception cref="ArgumentOutOfRangeException">if coeffIndex is not within [0, CoeffCount)</exception>
public ulong this[ulong coeffIndex]
{
get
{
NativeMethods.Plaintext_CoeffAt(NativePtr, coeffIndex, out ulong result);
return result;
}
set
{
NativeMethods.Plaintext_SetCoeffAt(NativePtr, coeffIndex, value);
}
}
/// <summary>
/// Returns whether the plaintext polynomial has all zero coefficients.
/// </summary>
public bool IsZero
{
get
{
NativeMethods.Plaintext_IsZero(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Returns the capacity of the current allocation.
/// </summary>
public ulong Capacity
{
get
{
NativeMethods.Plaintext_Capacity(NativePtr, out ulong capacity);
return capacity;
}
}
/// <summary>
/// Returns the coefficient count of the current plaintext polynomial.
/// </summary>
public ulong CoeffCount
{
get
{
NativeMethods.Plaintext_CoeffCount(NativePtr, out ulong result);
return result;
}
}
/// <summary>
/// Returns the significant coefficient count of the current plaintext polynomial.
/// </summary>
public ulong SignificantCoeffCount
{
get
{
NativeMethods.Plaintext_SignificantCoeffCount(NativePtr, out ulong result);
return result;
}
}
/// <summary>
/// Returns the non-zero coefficient count of the current plaintext polynomial.
/// </summary>
public ulong NonZeroCoeffCount
{
get
{
NativeMethods.Plaintext_NonZeroCoeffCount(NativePtr, out ulong result);
return result;
}
}
/// <summary>
/// Returns a human-readable string description of the plaintext polynomial.
/// </summary>
/// <remarks>
/// <para>
/// Returns a human-readable string description of the plaintext polynomial.
/// </para>
/// <para>
/// The returned string is of the form "7FFx^3 + 1x^1 + 3" with a format summarized by the following:
/// <list type="number">
/// <item><description>Terms are listed in order of strictly decreasing exponent</description></item>
/// <item><description>Coefficient values are non-negative and in hexadecimal format (hexadecimal letters are in upper-case)</description></item>
/// <item><description>Exponents are positive and in decimal format</description></item>
/// <item><description>Zero coefficient terms (including the constant term) are omitted unless the polynomial is exactly 0 (see rule 9)</description></item>
/// <item><description>Term with the exponent value of one is written as x^1</description></item>
/// <item><description>Term with the exponent value of zero (the constant term) is written as just a hexadecimal number without x or exponent</description></item>
/// <item><description>Terms are separated exactly by &lt;space&gt;+&lt;space&gt;</description></item>
/// <item><description>Other than the +, no other terms have whitespace</description></item>
/// <item><description>If the polynomial is exactly 0, the string "0" is returned</description></item>
/// </list>
/// </para>
/// </remarks>
/// <exception cref="InvalidOperationException">if the plaintext is in NTT transformed form</exception>
public override string ToString()
{
NativeMethods.Plaintext_ToString(NativePtr, null, out ulong length);
StringBuilder buffer = new StringBuilder(checked((int)length));
NativeMethods.Plaintext_ToString(NativePtr, buffer, out length);
return buffer.ToString();
}
/// <summary>
/// Returns a hash-code based on the value of the plaintext polynomial.
/// </summary>
public override int GetHashCode()
{
ulong coeffCount = CoeffCount;
ulong[] coeffs = new ulong[coeffCount];
for (ulong i = 0; i < coeffCount; i++)
{
coeffs[i] = this[i];
}
return Utilities.ComputeArrayHashCode(coeffs);
}
/// <summary>
/// Returns an upper bound on the size of the ciphertext, as if it was written
/// to an output stream.
/// </summary>
/// <param name="comprMode">The compression mode</param>
/// <exception cref="ArgumentException">if the compression mode is not
/// supported</exception>
/// <exception cref="InvalidOperationException">if the size does not fit in
/// the return type</exception>
public long SaveSize(ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
NativeMethods.Plaintext_SaveSize(
NativePtr, (byte)comprModeValue, out long outBytes);
return outBytes;
}
/// <summary>Saves the Plaintext to an output stream.</summary>
/// <remarks>
/// Saves the Plaintext to an output stream. The output is in binary format
/// and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the Plaintext to</param>
/// <param name="comprMode">The desired compression mode</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support writing, or if compression mode is not supported</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved
/// is invalid, or if compression failed</exception>
public long Save(Stream stream, ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
return Serialization.Save(
(byte[] outptr, ulong size, byte cm, out long outBytes) =>
NativeMethods.Plaintext_Save(NativePtr, outptr, size,
cm, out outBytes),
SaveSize(comprModeValue), comprModeValue, stream);
}
/// <summary>Loads a plaintext from an input stream overwriting the current
/// plaintext.</summary>
/// <remarks>
/// Loads a plaintext from an input stream overwriting the current plaintext.
/// No checking of the validity of the plaintext data against encryption
/// parameters is performed. This function should not be used unless the
/// plaintext comes from a fully trusted source.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the plaintext from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long UnsafeLoad(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.Plaintext_UnsafeLoad(context.NativePtr, NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>Loads a plaintext from an input stream overwriting the current
/// plaintext.</summary>
/// <remarks>
/// Loads a plaintext from an input stream overwriting the current plaintext.
/// The loaded plaintext is verified to be valid for the given SEALContext.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the plaintext from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long Load(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.Plaintext_Load(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>
/// Returns whether the plaintext is in NTT form.
/// </summary>
public bool IsNTTForm
{
get
{
NativeMethods.Plaintext_IsNTTForm(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Returns a copy of ParmsId. The ParmsId must remain zero unless the
/// plaintext polynomial is in NTT form.
/// </summary>
/// <seealso cref="EncryptionParameters">see EncryptionParameters for more
/// information about parmsId.</seealso>
public ParmsId ParmsId
{
get
{
ParmsId parms = new ParmsId();
NativeMethods.Plaintext_GetParmsId(NativePtr, parms.Block);
return parms;
}
private set
{
NativeMethods.Plaintext_SetParmsId(NativePtr, value.Block);
}
}
/// <summary>
/// Returns a reference to the scale. This is only needed when using the
/// CKKS encryption scheme. The user should have little or no reason to ever
/// change the scale by hand.
/// </summary>
public double Scale
{
get
{
NativeMethods.Plaintext_Scale(NativePtr, out double scale);
return scale;
}
private set
{
NativeMethods.Plaintext_SetScale(NativePtr, value);
}
}
/// <summary>
/// Returns the currently used MemoryPoolHandle.
/// </summary>
public MemoryPoolHandle Pool
{
get
{
NativeMethods.Plaintext_Pool(NativePtr, out IntPtr pool);
MemoryPoolHandle handle = new MemoryPoolHandle(pool);
return handle;
}
}
/// <summary>
/// Returns whether or not the plaintext has the same semantic value as a given
/// plaintext.
/// </summary>
/// <remarks>
/// Returns whether or not the plaintext has the same semantic value as a given
/// plaintext. Leading zero coefficients are ignored by the comparison.
/// </remarks>
/// <param name="obj">The object to compare against</param>
public override bool Equals(object obj)
{
Plaintext pt = obj as Plaintext;
return Equals(pt);
}
/// <summary>
/// Returns whether or not the plaintext has the same semantic value as a given
/// plaintext.
/// </summary>
/// <remarks>
/// Returns whether or not the plaintext has the same semantic value as a given
/// plaintext. Leading zero coefficients are ignored by the comparison.
/// </remarks>
/// <param name="other">The plaintext to compare against</param>
public bool Equals(Plaintext other)
{
if (null == other)
return false;
NativeMethods.Plaintext_Equals(NativePtr, other.NativePtr, out bool equals);
return equals;
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.Plaintext_Destroy(NativePtr);
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Class to store a public key.
/// </summary>
/// <remarks>
/// <para>
/// Thread Safety
/// In general, reading from PublicKey is thread-safe as long as no other thread
/// is concurrently mutating it. This is due to the underlying data structure
/// storing the public key not being thread-safe.
/// </para>
/// </remarks>
public class PublicKey : NativeObject
{
/// <summary>
/// Creates an empty public key.
/// </summary>
public PublicKey()
{
NativeMethods.PublicKey_Create(out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a new PublicKey by copying an old one.
/// </summary>
/// <param name="copy">The PublicKey to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public PublicKey(PublicKey copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.PublicKey_Create(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a new PublicKey by initializing with a pointer to a native object.
/// </summary>
/// <param name="publicKeyPtr">Pointer to native PublicKey</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal PublicKey(IntPtr publicKeyPtr, bool owned = true)
: base(publicKeyPtr, owned)
{
}
/// <summary>
/// Copies an old PublicKey to the current one.
/// </summary>
/// <param name="assign">The PublicKey to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(PublicKey assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.PublicKey_Set(NativePtr, assign.NativePtr);
}
/// <summary>
/// Returns the underlying Ciphertext.
/// </summary>
/// <remarks>
/// Returns the underlying Ciphertext. The returned Ciphertext is valid
/// only as long as the PublicKey is valid and not changed.
/// </remarks>
public Ciphertext Data
{
get
{
NativeMethods.PublicKey_Data(NativePtr, out IntPtr cipherPtr);
Ciphertext cipher = new Ciphertext(cipherPtr, owned: false);
return cipher;
}
}
/// <summary>
/// Returns an upper bound on the size of the PublicKey, as if it was written
/// to an output stream.
/// </summary>
/// <param name="comprMode">The compression mode</param>
/// <exception cref="ArgumentException">if the compression mode is not
/// supported</exception>
/// <exception cref="InvalidOperationException">if the size does not fit in
/// the return type</exception>
public long SaveSize(ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
NativeMethods.PublicKey_SaveSize(
NativePtr, (byte)comprModeValue, out long outBytes);
return outBytes;
}
/// <summary>Saves the PublicKey to an output stream.</summary>
/// <remarks>
/// Saves the PublicKey to an output stream. The output is in binary format
/// and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the PublicKey to</param>
/// <param name="comprMode">The desired compression mode</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support writing, or if compression mode is not supported</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved
/// is invalid, or if compression failed</exception>
public long Save(Stream stream, ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
return Serialization.Save(
(byte[] outptr, ulong size, byte cm, out long outBytes) =>
NativeMethods.PublicKey_Save(NativePtr, outptr, size,
cm, out outBytes),
SaveSize(comprModeValue), comprModeValue, stream);
}
/// <summary>Loads a PublicKey from an input stream overwriting the current
/// PublicKey.</summary>
/// <remarks>
/// Loads a PublicKey from an input stream overwriting the current PublicKey.
/// No checking of the validity of the PublicKey data against encryption
/// parameters is performed. This function should not be used unless the
/// PublicKey comes from a fully trusted source.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the PublicKey from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long UnsafeLoad(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.PublicKey_UnsafeLoad(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>Loads a PublicKey from an input stream overwriting the current
/// PublicKey.</summary>
/// <remarks>
/// Loads a PublicKey from an input stream overwriting the current PublicKey.
/// The loaded PublicKey is verified to be valid for the given SEALContext.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the PublicKey from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long Load(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.PublicKey_Load(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>
/// Returns a copy of ParmsId.
/// </summary>
public ParmsId ParmsId
{
get
{
ParmsId parmsId = new ParmsId();
NativeMethods.PublicKey_ParmsId(NativePtr, parmsId.Block);
return parmsId;
}
}
/// <summary>
/// Returns the currently used MemoryPoolHandle.
/// </summary>
public MemoryPoolHandle Pool
{
get
{
NativeMethods.PublicKey_Pool(NativePtr, out IntPtr pool);
MemoryPoolHandle handle = new MemoryPoolHandle(pool);
return handle;
}
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.PublicKey_Destroy(NativePtr);
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Class to store relinearization keys.
/// </summary>
/// <remarks>
/// <para>
/// Relinearization
/// Freshly encrypted ciphertexts have a size of 2, and multiplying ciphertexts
/// of sizes K and L results in a ciphertext of size K+L-1. Unfortunately, this
/// growth in size slows down further multiplications and increases noise growth.
/// Relinearization is an operation that has no semantic meaning, but it reduces
/// the size of ciphertexts back to 2. Microsoft SEAL can only relinearize size 3
/// ciphertexts back to size 2, so if the ciphertexts grow larger than size 3,
/// there is no way to reduce their size. Relinearization requires an instance of
/// RelinKeys to be created by the secret key owner and to be shared with the
/// evaluator. Note that plain multiplication is fundamentally different from
/// normal multiplication and does not result in ciphertext size growth.
/// </para>
/// <para>
/// When to Relinearize
/// Typically, one should always relinearize after each multiplications. However,
/// in some cases relinearization should be postponed as late as possible due to
/// its computational cost.For example, suppose the computation involves several
/// homomorphic multiplications followed by a sum of the results. In this case it
/// makes sense to not relinearize each product, but instead add them first and
/// only then relinearize the sum. This is particularly important when using the
/// CKKS scheme, where relinearization is much more computationally costly than
/// multiplications and additions.
/// </para>
/// <para>
/// Thread Safety
/// In general, reading from RelinKeys is thread-safe as long as no other thread
/// is concurrently mutating it. This is due to the underlying data structure
/// storing the relinearization keys not being thread-safe.
/// </para>
/// </remarks>
public class RelinKeys :
KSwitchKeys,
ISerializableObject,
ISettable<RelinKeys>
{
/// <summary>
/// Creates an empty set of relinearization keys.
/// </summary>
public RelinKeys() : base()
{
}
/// <summary>
/// Creates a new RelinKeys instance by copying a given instance.
/// </summary>
/// <param name="copy">The RelinKeys to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public RelinKeys(RelinKeys copy)
: base(copy)
{
}
/// <summary>
/// Creates a new RelinKeys instance initialized with a pointer to a native
/// KSwitchKeys object.
/// </summary>
/// <param name="kswitchKeys">Pointer to native KSwitchKeys object</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal RelinKeys(IntPtr kswitchKeys, bool owned = true)
: base(kswitchKeys, owned)
{
}
/// <summary>
/// Copies a given RelinKeys instance to the current one.
/// </summary>
///
/// <param name="assign">The RelinKeys to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(RelinKeys assign)
{
base.Set(assign);
}
/// <summary>
/// Returns the index of a relinearization key in the backing KSwitchKeys
/// instance that corresponds to the given secret key power, assuming that
/// it exists in the backing KSwitchKeys.
/// </summary>
/// <param name="keyPower">The power of the secret key</param>
/// <exception cref="ArgumentException">if keyPower is less than 2</exception>
public static ulong GetIndex(ulong keyPower)
{
NativeMethods.RelinKeys_GetIndex(keyPower, out ulong index);
return index;
}
/// <summary>
/// Returns whether a relinearization key corresponding to a given secret
/// key power exists.
/// </summary>
/// <param name="keyPower">The power of the secret key</param>
/// <exception cref="ArgumentException">if keyPower is less than 2</exception>
public bool HasKey(ulong keyPower)
{
ulong index = GetIndex(keyPower);
return (ulong)Data.LongCount() > index &&
Data.ElementAt(checked((int)index)).Count() != 0;
}
/// <summary>
/// Returns a specified relinearization key.
/// </summary>
/// <remarks>
/// Returns a specified relinearization key. The returned relinearization
/// key corresponds to the given power of the secret key and is valid only
/// as long as the RelinKeys is valid.
/// </remarks>
/// <param name="keyPower">The power of the secret key</param>
/// <exception cref="ArgumentException">if the key corresponding to keyPower
/// does not exist</exception>
public IEnumerable<PublicKey> Key(ulong keyPower)
{
return Data.ElementAt(checked((int)GetIndex(keyPower)));
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.Text;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Performs sanity checks (validation) and pre-computations for a given set of encryption
/// parameters.
/// </summary>
///
/// <remarks>
/// <para>
/// Performs sanity checks (validation) and pre-computations for a given set of encryption
/// parameters. While the EncryptionParameters class is intended to be a light-weight class
/// to store the encryption parameters, the SEALContext class is a heavy-weight class that
/// is constructed from a given set of encryption parameters. It validates the parameters
/// for correctness, evaluates their properties, and performs and stores the results of
/// several costly pre-computations.
/// </para>
/// <para>
/// After the user has set at least the PolyModulus, CoeffModulus, and PlainModulus
/// parameters in a given EncryptionParameters instance, the parameters can be validated
/// for correctness and functionality by constructing an instance of SEALContext. The
/// constructor of SEALContext does all of its work automatically, and concludes by
/// constructing and storing an instance of the EncryptionParameterQualifiers class, with
/// its flags set according to the properties of the given parameters. If the created
/// instance of EncryptionParameterQualifiers has the ParametersSet flag set to true, the
/// given parameter set has been deemed valid and is ready to be used. If the parameters
/// were for some reason not appropriately set, the ParametersSet flag will be false,
/// and a new SEALContext will have to be created after the parameters are corrected.
/// </para>
/// <para>
/// By default, SEALContext creates a chain of SEALContext.ContextData instances. The
/// first one in the chain corresponds to special encryption parameters that are reserved
/// to be used by the various key classes (SecretKey, PublicKey, etc.). These are the
/// exact same encryption parameters that are created by the user and passed to the
/// constructor of SEALContext. The properties KeyContextData and KeyParmsId return the
/// ContextData and the ParmsId corresponding to these special parameters. The rest of the
/// ContextData instances in the chain correspond to encryption parameters that are derived
/// from the first encryption parameters by always removing the last one of the moduli in
/// the CoeffModulus, until the resulting parameters are no longer valid, e.g., there are
/// no more primes left. These derived encryption parameters are used by ciphertexts and
/// plaintexts and their respective ContextData can be accessed through the
/// GetContextData(ParmsId) function. The properties FirstContextData and LastContextData
/// return the ContextData corresponding to the first and the last set of parameters in
/// the "data" part of the chain, i.e., the second and the last element in the full chain.
/// The chain is a doubly linked list and is referred to as the modulus switching chain.
/// </para>
/// </remarks>
/// <see cref="EncryptionParameters">see EncryptionParameters for more details on the parameters.</see>
/// <see cref="EncryptionParameterQualifiers">see EncryptionParameterQualifiers for more details on the qualifiers.</see>
public class SEALContext : NativeObject
{
/// <summary>
/// Creates an instance of SEALContext and performs several pre-computations
/// on the given EncryptionParameters.
/// </summary>
/// <param name="parms">The encryption parameters.</param>
/// <param name="expandModChain">Determines whether the modulus switching chain
/// should be created</param>
/// <param name="secLevel">Determines whether a specific security level should be
/// enforced according to HomomorphicEncryption.org security standard</param>
/// <exception cref="ArgumentNullException">if parms is null</exception>
public SEALContext(EncryptionParameters parms,
bool expandModChain = true, SecLevelType secLevel = SecLevelType.TC128)
{
if (null == parms)
throw new ArgumentNullException(nameof(parms));
NativeMethods.SEALContext_Create(parms.NativePtr,
expandModChain, (int)secLevel, out IntPtr context);
NativePtr = context;
}
/// <summary>
/// Returns the ContextData corresponding to encryption parameters with a given
/// parmsId. If parameters with the given ParmsId are not found then the function
/// returns null.
/// </summary>
///
/// <param name="parmsId">The ParmsId of the encryption parameters</param>
/// <exception cref="ArgumentNullException">if parmsId is null</exception>
public ContextData GetContextData(ParmsId parmsId)
{
if (null == parmsId)
throw new ArgumentNullException(nameof(parmsId));
NativeMethods.SEALContext_GetContextData(NativePtr, parmsId.Block, out IntPtr contextData);
if (IntPtr.Zero.Equals(contextData))
return null;
ContextData data = new ContextData(contextData, owned: false);
return data;
}
/// <summary>
/// Returns the ContextData corresponding to encryption parameters that are
/// used for keys.
/// </summary>
public ContextData KeyContextData
{
get
{
NativeMethods.SEALContext_KeyContextData(NativePtr, out IntPtr contextData);
ContextData data = new ContextData(contextData, owned: false);
return data;
}
}
/// <summary>
/// Returns the ContextData corresponding to the first encryption parameters
/// that are used for data.
/// </summary>
public ContextData FirstContextData
{
get
{
NativeMethods.SEALContext_FirstContextData(NativePtr, out IntPtr contextData);
ContextData data = new ContextData(contextData, owned: false);
return data;
}
}
/// <summary>
/// Returns the ContextData corresponding to the last encryption parameters
/// that are used for data.
/// </summary>
public ContextData LastContextData
{
get
{
NativeMethods.SEALContext_LastContextData(NativePtr, out IntPtr contextData);
ContextData data = new ContextData(contextData, owned: false);
return data;
}
}
/// <summary>
/// Returns whether the encryption parameters are valid.
/// </summary>
public bool ParametersSet
{
get
{
NativeMethods.SEALContext_ParametersSet(NativePtr, out bool paramsSet);
return paramsSet;
}
}
/// <summary>
/// If the encryption parameters are set in a way that is considered valid by SEAL, return "success".
/// If the encryption parameters are set but not validated yet, return "none".
/// Otherwise, return a brief reason.
/// </summary>
public string ParameterErrorName()
{
NativeMethods.SEALContext_ParameterErrorName(NativePtr, null, out ulong length);
byte[] buffer = new byte[length];
NativeMethods.SEALContext_ParameterErrorName(NativePtr, buffer, out length);
return Encoding.ASCII.GetString(buffer);
}
/// <summary>
/// If the encryption parameters are set in a way that is considered valid by SEAL, return "valid".
/// Otherwise, return a comprehensive reason.
/// </summary>
public string ParameterErrorMessage()
{
NativeMethods.SEALContext_ParameterErrorMessage(NativePtr, null, out ulong length);
byte[] buffer = new byte[length];
NativeMethods.SEALContext_ParameterErrorMessage(NativePtr, buffer, out length);
return Encoding.ASCII.GetString(buffer);
}
/// <summary>
/// Returns a ParmsId corresponding to the set of encryption parameters
/// that are used for keys.
/// </summary>
public ParmsId KeyParmsId
{
get
{
ParmsId parms = new ParmsId();
NativeMethods.SEALContext_KeyParmsId(NativePtr, parms.Block);
return parms;
}
}
/// <summary>
/// Returns a ParmsId corresponding to the first encryption parameters that
/// are used for data.
/// </summary>
public ParmsId FirstParmsId
{
get
{
ParmsId parms = new ParmsId();
NativeMethods.SEALContext_FirstParmsId(NativePtr, parms.Block);
return parms;
}
}
/// <summary>
/// Returns a ParmsId corresponding to the last encryption parameters that
/// are used for data.
/// </summary>
public ParmsId LastParmsId
{
get
{
ParmsId parms = new ParmsId();
NativeMethods.SEALContext_LastParmsId(NativePtr, parms.Block);
return parms;
}
}
/// <summary>
/// Returns whether the coefficient modulus supports keyswitching.
/// </summary>
/// <remarks>
/// Returns whether the coefficient modulus supports keyswitching. In
/// practice, support for keyswitching is required by Evaluator.Relinearize,
/// Evaluator.ApplyGalois, and all rotation and conjugation operations.
/// For keyswitching to be available, the coefficient modulus parameter must
/// consist of at least two prime number factors.
/// </remarks>
public bool UsingKeyswitching
{
get
{
NativeMethods.SEALContext_UsingKeyswitching(NativePtr, out bool result);
return result;
}
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.SEALContext_Destroy(NativePtr);
}
/// <summary>
/// Class to hold pre-computation data for a given set of encryption parameters.
/// </summary>
public class ContextData : NativeObject
{
/// <summary>
/// Build a ContextData object from a native pointer.
/// </summary>
/// <param name="ptr">Pointer to native object</param>
/// <param name="owned">Whether this instance owns the native object</param>
internal ContextData(IntPtr ptr, bool owned = true)
: base(ptr, owned)
{
}
/// <summary>
/// Returns a copy of the underlying encryption parameters.
/// </summary>
public EncryptionParameters Parms
{
get
{
NativeMethods.ContextData_Parms(NativePtr, out IntPtr parms);
return new EncryptionParameters(parms);
}
}
/// <summary>
/// Returns the ParmsId of the current parameters.
/// </summary>
public ParmsId ParmsId
{
get
{
return Parms.ParmsId;
}
}
/// <summary>
/// Returns a copy of EncryptionParameterQualifiers corresponding to the
/// current encryption parameters.
/// </summary>
/// <remarks>
/// Returns a copy of EncryptionParameterQualifiers corresponding to the
/// current encryption parameters. Note that to change the qualifiers it is
/// necessary to create a new instance of SEALContext once appropriate changes
/// to the encryption parameters have been made.
/// </remarks>
public EncryptionParameterQualifiers Qualifiers
{
get
{
NativeMethods.ContextData_Qualifiers(NativePtr, out IntPtr epq);
EncryptionParameterQualifiers qualifiers = new EncryptionParameterQualifiers(epq);
return qualifiers;
}
}
/// <summary>
/// Returns a the pre-computed product of all primes in the
/// coefficient modulus.
/// </summary>
/// <remarks>
/// Returns a the pre-computed product of all primes in the
/// coefficient modulus. The security of the encryption parameters largely depends
/// on the bit-length of this product, and on the degree of the polynomial modulus.
/// </remarks>
public ulong[] TotalCoeffModulus
{
get
{
ulong count = 0;
NativeMethods.ContextData_TotalCoeffModulus(NativePtr, ref count, null);
ulong[] result = new ulong[count];
NativeMethods.ContextData_TotalCoeffModulus(NativePtr, ref count, result);
return result;
}
}
/// <summary>
/// Returns the significant bit count of the total coefficient modulus.
/// </summary>
public int TotalCoeffModulusBitCount
{
get
{
NativeMethods.ContextData_TotalCoeffModulusBitCount(NativePtr, out int bitCount);
return bitCount;
}
}
/// <summary>
/// Return a copy of BFV "Delta", i.e. coefficient modulus divided by
/// plaintext modulus.
/// </summary>
public ulong[] CoeffDivPlainModulus
{
get
{
ulong count = 0;
NativeMethods.ContextData_CoeffDivPlainModulus(NativePtr, ref count, null);
ulong[] cdpm = new ulong[count];
NativeMethods.ContextData_CoeffDivPlainModulus(NativePtr, ref count, cdpm);
return cdpm;
}
}
/// <summary>
/// Return the threshold for the upper half of integers modulo PlainModulus.
/// This is simply(PlainModulus + 1) / 2.
/// </summary>
public ulong PlainUpperHalfThreshold
{
get
{
NativeMethods.ContextData_PlainUpperHalfThreshold(NativePtr, out ulong puht);
return puht;
}
}
/// <summary>
/// Return a copy of the plaintext upper half increment, i.e. coeffModulus
/// minus plainModulus.
/// </summary>
/// <remarks>
/// Return a copy of the plaintext upper half increment, i.e. coeffModulus
/// minus plainModulus. The upper half increment is represented as an integer
/// for the full product coeffModulus if UsingFastPlainLift is false and is
/// otherwise represented modulo each of the CoeffModulus primes in order.
/// </remarks>
public ulong[] PlainUpperHalfIncrement
{
get
{
ulong count = 0;
NativeMethods.ContextData_PlainUpperHalfIncrement(NativePtr, ref count, null);
ulong[] puhi = new ulong[count];
NativeMethods.ContextData_PlainUpperHalfIncrement(NativePtr, ref count, puhi);
return puhi;
}
}
/// <summary>
/// Return a copy of the upper half threshold with respect to the total
/// coefficient modulus. This is needed in CKKS decryption.
/// </summary>
public ulong[] UpperHalfThreshold
{
get
{
ulong count = 0;
NativeMethods.ContextData_UpperHalfThreshold(NativePtr, ref count, null);
if (count == 0)
return null;
ulong[] uht = new ulong[count];
NativeMethods.ContextData_UpperHalfThreshold(NativePtr, ref count, uht);
return uht;
}
}
/// <summary>
/// Return a copy of the upper half increment used for computing Delta*m
/// and converting the coefficients to modulo CoeffModulus.
/// </summary>
/// <remarks>
/// Return a copy of the upper half increment used for computing Delta*m
/// and converting the coefficients to modulo CoeffModulus. For example,
/// t-1 in plaintext should change into
/// q - Delta = Delta*t + r_t(q) - Delta = Delta*(t-1) + r_t(q)
/// so multiplying the message by Delta is not enough and requires also an
/// addition of r_t(q). This is precisely the UpperHalfIncrement. Note that
/// this operation is only done for negative message coefficients, i.e. those
/// that exceed PlainUpperHalfThreshold.
/// </remarks>
public ulong[] UpperHalfIncrement
{
get
{
ulong count = 0;
NativeMethods.ContextData_UpperHalfIncrement(NativePtr, ref count, null);
if (count == 0)
return null;
ulong[] uhi = new ulong[count];
NativeMethods.ContextData_UpperHalfIncrement(NativePtr, ref count, uhi);
return uhi;
}
}
/// <summary>
/// Returns the context data corresponding to the previous parameters in the
/// modulus switching chain.
/// </summary>
/// <remarks>
/// Returns the context data corresponding to the previous parameters in the
/// modulus switching chain. If the current data is the first one in the chain,
/// then the result is nullptr.
/// </remarks>
public ContextData PrevContextData
{
get
{
NativeMethods.ContextData_PrevContextData(NativePtr, out IntPtr prev);
if (IntPtr.Zero.Equals(prev))
return null;
ContextData data = new ContextData(prev, owned: false);
return data;
}
}
/// <summary>
/// Returns the context data corresponding to the next parameters in the modulus
/// switching chain.
/// </summary>
/// <remarks>
/// Returns the context data corresponding to the next parameters in the modulus
/// switching chain. If the current data is the last one in the chain, then the
/// result is nullptr.
/// </remarks>
public ContextData NextContextData
{
get
{
NativeMethods.ContextData_NextContextData(NativePtr, out IntPtr next);
if (IntPtr.Zero.Equals(next))
return null;
ContextData data = new ContextData(next, owned: false);
return data;
}
}
/// <summary>
/// Returns the index of the parameter set in a chain.
/// </summary>
/// <remarks>
/// Returns the index of the parameter set in a chain. The initial parameters
/// have index 0 and the index increases sequentially in the parameter chain.
/// </remarks>
public ulong ChainIndex
{
get
{
NativeMethods.ContextData_ChainIndex(NativePtr, out ulong index);
return index;
}
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.ContextData_Destroy(NativePtr);
}
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Authors>Microsoft Research</Authors>
<Company>Microsoft Corporation</Company>
<Description>.NET wrapper library for Microsoft SEAL</Description>
<Copyright>Microsoft Corporation 2020</Copyright>
<SignAssembly Condition="'$(OS)' == 'Windows_NT' And '$(SEALNetSigningCertificate)' != ''">true</SignAssembly>
<AssemblyOriginatorKeyFile Condition="'$(OS)' == 'Windows_NT' And '$(SEALNetSigningCertificate)' != ''">SEALNetCert.snk</AssemblyOriginatorKeyFile>
<DelaySign Condition="'$(OS)' == 'Windows_NT' And '$(SEALNetSigningCertificate)' != ''">true</DelaySign>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='AnyCPU'">
<DocumentationFile>$(ProjectDir)../../lib/dotnet/$(Configuration)/SEALNet.xml</DocumentationFile>
<PlatformTarget>x64</PlatformTarget>
<OutputPath>$(ProjectDir)../../lib/dotnet/$(Configuration)</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants />
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
</Project>
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Class to store a secret key.
/// </summary>
/// <remarks>
/// <para>
/// Thread Safety
/// In general, reading from SecretKey is thread-safe as long as no other
/// thread is concurrently mutating it. This is due to the underlying data
/// structure storing the secret key not being thread-safe.
/// </para>
/// </remarks>
/// <see cref="KeyGenerator">see KeyGenerator for the class that generates the secret key.</see>
/// <see cref="PublicKey">see PublicKey for the class that stores the public key.</see>
/// <see cref="RelinKeys">see RelinKeys for the class that stores the relinearization keys.</see>
/// <see cref="GaloisKeys">see GaloisKeys for the class that stores the Galois keys.</see>
public class SecretKey : NativeObject
{
/// <summary>
/// Creates an empty secret key.
/// </summary>
public SecretKey()
{
NativeMethods.SecretKey_Create(out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Creates a new SecretKey by initializing it with a pointer to a native object.
/// </summary>
/// <param name="secretKeyPtr">The native SecretKey pointer</param>
/// <param name="owned">Whether this instance owns the native pointer</param>
internal SecretKey(IntPtr secretKeyPtr, bool owned = true)
: base(secretKeyPtr, owned)
{
}
/// <summary>
/// Creates a new SecretKey by copying an old one.
/// </summary>
/// <param name="copy">The SecretKey to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public SecretKey(SecretKey copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
NativeMethods.SecretKey_Create(copy.NativePtr, out IntPtr ptr);
NativePtr = ptr;
}
/// <summary>
/// Copies an old SecretKey to the current one.
/// </summary>
/// <param name="assign">The SecretKey to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(SecretKey assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
NativeMethods.SecretKey_Set(NativePtr, assign.NativePtr);
}
/// <summary>
/// Returns the underlying Plaintext.
/// </summary>
/// <remarks>
/// Returns the underlying Plaintext. The returned Plaintext is valid
/// only as long as the SecretKey is valid and not changed.
/// </remarks>
public Plaintext Data
{
get
{
NativeMethods.SecretKey_Data(NativePtr, out IntPtr plaintextPtr);
Plaintext plaintext = new Plaintext(plaintextPtr, owned: false);
return plaintext;
}
}
/// <summary>
/// Returns an upper bound on the size of the SecretKey, as if it was written
/// to an output stream.
/// </summary>
/// <param name="comprMode">The compression mode</param>
/// <exception cref="ArgumentException">if the compression mode is not
/// supported</exception>
/// <exception cref="InvalidOperationException">if the size does not fit in
/// the return type</exception>
public long SaveSize(ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
NativeMethods.SecretKey_SaveSize(
NativePtr, (byte)comprModeValue, out long outBytes);
return outBytes;
}
/// <summary>Saves the SecretKey to an output stream.</summary>
/// <remarks>
/// Saves the SecretKey to an output stream. The output is in binary format
/// and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the SecretKey to</param>
/// <param name="comprMode">The desired compression mode</param>
/// <exception cref="ArgumentNullException">if stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support writing, or if compression mode is not supported</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved
/// is invalid, or if compression failed</exception>
public long Save(Stream stream, ComprModeType? comprMode = null)
{
comprMode = comprMode ?? Serialization.ComprModeDefault;
if (!Serialization.IsSupportedComprMode(comprMode.Value))
throw new ArgumentException("Unsupported compression mode");
ComprModeType comprModeValue = comprMode.Value;
return Serialization.Save(
(byte[] outptr, ulong size, byte cm, out long outBytes) =>
NativeMethods.SecretKey_Save(NativePtr, outptr, size,
cm, out outBytes),
SaveSize(comprModeValue), comprModeValue, stream);
}
/// <summary>Loads a SecretKey from an input stream overwriting the current
/// SecretKey.</summary>
/// <remarks>
/// Loads a SecretKey from an input stream overwriting the current SecretKey.
/// No checking of the validity of the SecretKey data against encryption
/// parameters is performed. This function should not be used unless the
/// SecretKey comes from a fully trusted source.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the SecretKey from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long UnsafeLoad(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.SecretKey_UnsafeLoad(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>Loads a SecretKey from an input stream overwriting the current
/// SecretKey.</summary>
/// <remarks>
/// Loads a SecretKey from an input stream overwriting the current SecretKey.
/// The loaded SecretKey is verified to be valid for the given SEALContext.
/// </remarks>
/// <param name="context">The SEALContext</param>
/// <param name="stream">The stream to load the SecretKey from</param>
/// <exception cref="ArgumentNullException">if context or stream is
/// null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not
/// support reading</exception>
/// <exception cref="ArgumentException">if context is not set or encryption
/// parameters are not valid</exception>
/// <exception cref="EndOfStreamException">if the stream ended
/// unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data cannot be loaded
/// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
/// loaded compression mode is not supported</exception>
public long Load(SEALContext context, Stream stream)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
return Serialization.Load(
(byte[] outptr, ulong size, out long outBytes) =>
NativeMethods.SecretKey_Load(NativePtr, context.NativePtr,
outptr, size, out outBytes),
stream);
}
/// <summary>
/// Returns a copy of ParmsId.
/// </summary>
public ParmsId ParmsId
{
get
{
ParmsId parms = new ParmsId();
NativeMethods.SecretKey_ParmsId(NativePtr, parms.Block);
return parms;
}
}
/// <summary>
/// Returns the currently used MemoryPoolHandle.
/// </summary>
public MemoryPoolHandle Pool
{
get
{
NativeMethods.SecretKey_Pool(NativePtr, out IntPtr pool);
MemoryPoolHandle handle = new MemoryPoolHandle(pool);
return handle;
}
}
/// <summary>
/// Destroy native object.
/// </summary>
protected override void DestroyNativeObject()
{
NativeMethods.SecretKey_Destroy(NativePtr);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment