Commit c6c9d2f5 authored by Hoang Gia NGUYEN's avatar Hoang Gia NGUYEN
Browse files

first commit

parent fe2d6195
Pipeline #60 failed with stages
in 0 seconds

Too many changes to show.

To preserve performance only 275 of 275+ files are displayed.
// 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);
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
using System.IO;
namespace Microsoft.Research.SEAL
{
/// <summary>Interface for classes with a Set function.</summary>
public interface ISettable<T> where T : class
{
/// <summary>
/// Copies a given object to the current one.
/// </summary>
/// <param name="assign">The object to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
void Set(T assign);
}
/// <summary>Interface for classes that are serializable.</summary>
public interface ISerializableObject
{
/// <summary>
/// Returns an upper bound on the size of the object, 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>
long SaveSize(ComprModeType? comprMode);
/// <summary>Saves the object to an output stream.</summary>
/// <remarks>
/// Saves the object to an output stream. The output is in binary format
/// and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the object 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>
long Save(Stream stream, ComprModeType? comprMode);
}
/// <summary>Class to represent a serializable object.</summary>
/// <remarks>
/// <para>
/// Some functions return serializable objects rather than normal objects. For
/// example, Encryptor can be used in symmetric-key mode to create symmetric-key
/// ciphertexts, where half of the ciphertext data is pseudo-random and can be
/// generated from a seed, reducing the size of the newly created ciphertext
/// object by nearly 50%. However, the compression only has an effect when the
/// object is serialized with compression mode ComprModeType.Deflate due to an
/// implementation detail. This makes sense when, e.g., the ciphertexts need
/// to be communicated from a client to a server for encrypted computation.
/// </para>
/// <para>
/// Serializable objects are created only by the following functions:
/// - Encryptor.EncryptSymmetric
/// - Encryptor.EncryptZeroSymmetric
/// - KeyGenerator.RelinKeys
/// - KeyGenerator.GaloisKeys
/// </para>
/// <para>
/// Serializable objects also expose the SaveSize function that behaves just
/// as the SaveSize functions of other objects in Microsoft SEAL: it returns
/// an upper bound on the size of a buffer needed to hold the serialized data.
/// </para>
/// <para>
/// The following illustrates the use of serializable objects:
///
/// +--------------------------+
/// | Serializable{GaloisKeys} | Size 2 MB (example)
/// +------------+-------------+
/// |
/// | Serializable{GaloisKeys}.Save
/// | with ComprModeType.Deflate
/// |
/// +-------v-------+
/// | Stream/Buffer | Size ~1 MB (example)
/// +-------+-------+
/// |
/// |
/// +--v--+
/// Network Minimized communication
/// +--+--+
/// |
/// | GaloisKeys.Load
/// |
/// +-----v------+
/// | GaloisKeys | Size 2 MB (example)
/// +------------+
/// </para>
/// <typeparam name="T">The type to wrap into a serializable object</typeparam>
/// </remarks>
public class Serializable<T> : DisposableObject
where T : DisposableObject, ISerializableObject, ISettable<T>, new()
{
/// <summary>
/// Constructs a new serializable object by copying a given one.
/// </summary>
/// <param name="copy">The serializable object to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public Serializable(Serializable<T> copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
// Use Activator to get around lack of constructor
obj_ = (T)Activator.CreateInstance(typeof(T), copy.obj_);
}
/// <summary>
/// Copies a given serializable object to the current one.
/// </summary>
/// <param name="assign">The serializable object to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(Serializable<T> assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
obj_.Set(assign.obj_);
}
/// <summary>
/// Returns an upper bound on the size of the serializable object, 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)
=> obj_.SaveSize(comprMode);
/// <summary>Saves the serializable object to an output stream.</summary>
/// <remarks>
/// Saves the serializable object to an output stream. The output is in
/// binary format and not human-readable.
/// </remarks>
/// <param name="stream">The stream to save the serializable object 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)
=> obj_.Save(stream, comprMode);
/// <summary>
/// Constructs a new serializable object wrapping a given object.
/// </summary>
/// <param name="obj">The object to wrap</param>
/// <exception cref="ArgumentNullException">if obj is null</exception>
internal Serializable(T obj)
{
if (null == obj)
throw new ArgumentNullException(nameof(obj));
obj_ = obj;
}
/// <summary>
/// Destroy wrapped object.
/// </summary>
protected override void DisposeManagedResources()
{
obj_.Dispose();
}
/// <summary>
/// The object wrapped by an instance of Serializable.
/// </summary>
private readonly T obj_;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// A type to describe the compression algorithm applied to serialized data.
/// Ciphertext and key data consist of a large number of 64-bit words storing
/// integers modulo prime numbers much smaller than the word size, resulting in
/// a large number of zero bytes in the output. Any compression algorithm should
/// be able to clean up these zero bytes and hence compress both ciphertext and
/// key data.
/// </summary>
public enum ComprModeType : byte
{
/// <summary>No compression is used.</summary>
None = 0,
/// <summary>Use Deflate compression.</summary>
Deflate = 1,
}
/// <summary>Class to provide functionality for serialization.</summary>
/// <remarks>
/// Class to provide functionality for serialization. Most users of the library
/// should never have to call these functions explicitly, as they are called
/// internally by functions such as Ciphertext.Save and Ciphertext.Load.
/// </remarks>
public abstract class Serialization
{
/// <summary>
/// The compression mode used by default.
/// </summary>
public static readonly ComprModeType ComprModeDefault = ((Func<ComprModeType>)(() => {
NativeMethods.Serialization_ComprModeDefault(out byte comprMode);
return (ComprModeType)comprMode;
}))();
/// <summary>The magic value indicating a Microsoft SEAL header.</summary>
public static readonly ushort SEALMagic = ((Func<ushort>)(() => {
NativeMethods.Serialization_SEALMagic(out ushort sealMagic);
return sealMagic;
}))();
/// <summary>The size in bytes of the SEALHeader.</summary>
public static readonly byte SEALHeaderSize = ((Func<byte>)(() => {
NativeMethods.Serialization_SEALHeaderSize(out byte sealHeaderSize);
return sealHeaderSize;
}))();
/// <summary>Struct to contain header information for serialization.</summary>
/// <remarks>
/// Struct to contain header information for serialization. The size of the header is 16 bytes and it consists
/// of the following fields:
///
/// 1. a magic number identifying this is a SEALHeader struct (2 bytes)
/// 2. size in bytes of the SEALHeader struct (1 byte)
/// 3. Microsoft SEAL's major version number (1 byte)
/// 4. Microsoft SEAL's minor version number (1 byte)
/// 5. a ComprModeType indicating whether data after the header is compressed (1 byte)
/// 6. reserved for future use and data alignment (2 bytes)
/// 7. the size in bytes of the entire serialized object, including the header (8 bytes)
/// </remarks>
[StructLayout(LayoutKind.Explicit, Size=16)]
public class SEALHeader : ISettable<SEALHeader>
{
/// <summary>A magic number identifying this is a SEALHeader struct (2 bytes)</summary>
[FieldOffset(0)]public ushort Magic = SEALMagic;
/// <summary>Size in bytes of the SEALHeader struct (1 byte)</summary>
[FieldOffset(2)]public byte HeaderSize = SEALHeaderSize;
/// <summary>Microsoft SEAL's major version number (1 byte)</summary>
[FieldOffset(3)]public byte VersionMajor = SEALVersion.Major;
/// <summary>Microsoft SEAL's minor version number (1 byte)</summary>
[FieldOffset(4)]public byte VersionMinor = SEALVersion.Minor;
/// <summary>A compr_mode_type indicating whether data after the header is compressed (1 byte)</summary>
[FieldOffset(5)]public ComprModeType ComprMode = ComprModeDefault;
/// <summary>Reserved for future use and data alignment (2 bytes)</summary>
[FieldOffset(6)]public ushort Reserved = 0;
/// <summary>The size in bytes of the entire serialized object, including the header (8 bytes)</summary>
[FieldOffset(8)]public ulong Size = 0;
/// <summary>
/// Copies a given SEALHeader to the current one.
/// </summary>
/// <param name="assign">The SEALHeader to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(SEALHeader assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
Magic = assign.Magic;
HeaderSize = assign.HeaderSize;
VersionMajor = assign.VersionMajor;
VersionMinor = assign.VersionMinor;
ComprMode = assign.ComprMode;
Reserved = assign.Reserved;
Size = assign.Size;
}
};
private static bool IsSupportedComprMode(byte comprMode)
{
NativeMethods.Serialization_IsSupportedComprMode(comprMode, out bool result);
return result;
}
/// <summary>Returns true if the given value corresponds to a supported compression mode.</summary>
/// <param name="comprMode">The compression mode to validate</param>
public static bool IsSupportedComprMode(ComprModeType comprMode) =>
IsSupportedComprMode((byte)comprMode);
/// <summary>Returns true if the SEALHeader has a version number compatible with this version of
/// Microsoft SEAL.</summary>
/// <param name="header">The SEALHeader</param>
public static bool IsCompatibleVersion(SEALHeader header)
{
byte[] headerArray = new byte[SEALHeaderSize];
using (MemoryStream stream = new MemoryStream(headerArray))
{
SaveHeader(header, stream);
NativeMethods.Serialization_IsCompatibleVersion(
headerArray, (ulong)headerArray.Length, out bool result);
return result;
}
}
/// <summary>Returns true if the given SEALHeader is valid for this version of Microsoft SEAL.</summary>
/// <param name="header">The SEALHeader</param>
public static bool IsValidHeader(SEALHeader header)
{
byte[] headerArray = new byte[SEALHeaderSize];
using (MemoryStream stream = new MemoryStream(headerArray))
{
SaveHeader(header, stream);
NativeMethods.Serialization_IsValidHeader(
headerArray, (ulong)headerArray.Length, out bool result);
return result;
}
}
/// <summary>Saves a SEALHeader to a given binary stream.</summary>
/// <remarks>
/// Saves a SEALHeader to a given stream. The output is in binary format and not human-readable.
/// </remarks>
/// <param name="header">The SEALHeader to save to the stream</param>
/// <param name="stream">The stream to save the SEALHeader to</param>
/// <exception cref="ArgumentNullException">if header or stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not support writing</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
public static void SaveHeader(SEALHeader header, Stream stream)
{
if (null == header)
throw new ArgumentNullException(nameof(header));
if (null == stream)
throw new ArgumentNullException(nameof(stream));
if (!stream.CanWrite)
throw new ArgumentException(nameof(stream));
using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true))
{
writer.Write(header.Magic);
writer.Write(header.HeaderSize);
writer.Write(header.VersionMajor);
writer.Write(header.VersionMinor);
writer.Write((byte)header.ComprMode);
writer.Write(header.Reserved);
writer.Write(header.Size);
}
}
/// <summary>Loads a SEALHeader from a given stream.</summary>
/// <param name="stream">The stream to load the SEALHeader from</param>
/// <param name="header">The SEALHeader to populate with the loaded data</param>
/// <param name="tryUpgradeIfInvalid">If the loaded SEALHeader is invalid, attempt to identify its format and
/// upgrade to the current SEALHeader version</param>
/// <exception cref="ArgumentNullException">if header or stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not support reading</exception>
/// <exception cref="InvalidOperationException">if the loaded data is not a valid SEALHeader or if the loaded
/// compression mode is not supported</exception>
/// <exception cref="EndOfStreamException">if the stream ended unexpectedly</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
public static void LoadHeader(Stream stream, SEALHeader header, bool tryUpgradeIfInvalid = true)
{
if (null == header)
throw new ArgumentNullException(nameof(header));
if (null == stream)
throw new ArgumentNullException(nameof(stream));
if (!stream.CanRead)
throw new ArgumentException(nameof(stream));
using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true))
{
header.Magic = reader.ReadUInt16();
header.HeaderSize = reader.ReadByte();
header.VersionMajor = reader.ReadByte();
header.VersionMinor = reader.ReadByte();
header.ComprMode = (ComprModeType)reader.ReadByte();
header.Reserved = reader.ReadUInt16();
header.Size = reader.ReadUInt64();
}
// If header is invalid this may be an older header and we can try to automatically upgrade it
if (tryUpgradeIfInvalid && !IsValidHeader(header))
{
// Try interpret the data as a Microsoft SEAL 3.4 header
LegacyHeaders.SEALHeader_3_4 header_3_4 = new LegacyHeaders.SEALHeader_3_4(header);
SEALHeader newHeader = new SEALHeader();
// Copy over the fields; of course the result may not be valid depending on whether the input was a
// valid version 3.4 header
newHeader.ComprMode = header_3_4.ComprMode;
newHeader.Size = header_3_4.Size;
// Now validate the new header and discard if still not valid; something else is probably wrong
if (IsValidHeader(newHeader))
{
header.Set(newHeader);
}
}
}
internal delegate void SaveDelegate(
byte[] outptr, ulong size, byte comprMode, out long outBytes);
internal delegate void LoadDelegate(
byte[] inptr, ulong size, out long inBytes);
/// <summary>Saves data to a given binary stream.</summary>
/// <remarks>
/// First this function allocates a buffer of size <paramref name="size" />. The buffer is used by the
/// <paramref name="SaveData"/> delegate that writes some number of bytes to the buffer and outputs (in
/// out-parameter) the number of bytes written (less than the size of the buffer). The contents of the buffer
/// are then written to <paramref name="stream"/> and the function returns the output value of
/// <paramref name="SaveData"/>. This function is intended only for internal use.
/// </remarks>
/// <param name="SaveData">The delegate that writes some number of bytes to a given buffer</param>
/// <param name="size">An upper bound on the number of bytes that <paramref name="SaveData" /> requires</param>
/// <param name="comprMode">The desired compression mode</param>
/// <param name="stream">The destination stream</param>
/// <exception cref="ArgumentNullException">if SaveData or stream is null</exception>
/// <exception cref="ArgumentException">if the stream is closed or does not support writing, or if size is
/// negative or too large</exception>
/// <exception cref="IOException">if I/O operations failed</exception>
/// <exception cref="InvalidOperationException">if the data to be saved is invalid, if compression mode is not
/// supported, or if compression failed</exception>
internal static long Save(SaveDelegate SaveData, long size,
ComprModeType comprMode, Stream stream)
{
if (null == stream)
throw new ArgumentNullException(nameof(stream));
if (null == SaveData)
throw new ArgumentNullException(nameof(SaveData));
if (!stream.CanWrite)
throw new ArgumentException(nameof(stream));
if (!IsSupportedComprMode(comprMode))
throw new InvalidOperationException("Unsupported compression mode");
try
{
int sizeInt = checked((int)size);
byte[] buffer = new byte[sizeInt];
SaveData(buffer, checked((ulong)sizeInt), (byte)comprMode, out long outBytes);
int intOutBytes = checked((int)outBytes);
using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true))
{
writer.Write(buffer, 0, intOutBytes);
}
// Clear the buffer for safety reasons
Array.Clear(buffer, 0, intOutBytes);
return outBytes;
}
catch (OverflowException ex)
{
throw new ArgumentException($"{nameof(size)} is out of bounds", ex);
}
}
/// <summary>Loads data from a given binary stream.</summary>
/// <remarks>
/// This function calls the <see cref="LoadHeader" /> function to first load a <see cref="SEALHeader" /> object
/// from <paramref name="stream"/>. The <see cref="SEALHeader.Size"/> is then read from the
/// <see cref="SEALHeader" /> and a buffer of corresponding size is allocated. Next, the buffer is filled with
/// data read from <paramref name="stream"/> and <paramref name="LoadData"/> is called with the buffer as input,
/// which outputs (in out-parameter) the number bytes read from the buffer. This should match exactly the size
/// of the buffer. Finally, the function returns the output value of <paramref name="LoadData"/>. This function
/// is intended only for internal use.
/// </remarks>
/// <param name="LoadData">The delegate that reads some number of bytes to a given buffer</param>
/// <param name="stream">The input stream</param>
/// <exception cref="ArgumentNullException">if LoadData or 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 loaded data is invalid, if the loaded compression mode is
/// not supported, or if size of the object is more than 2 GB</exception>
internal static long Load(LoadDelegate LoadData, Stream stream)
{
if (null == stream)
throw new ArgumentNullException(nameof(stream));
if (null == LoadData)
throw new ArgumentNullException(nameof(LoadData));
if (!stream.CanRead)
throw new ArgumentException(nameof(stream));
try
{
SEALHeader header = new SEALHeader();
var pos = stream.Position;
LoadHeader(stream, header);
// Check the validity of the header
if (!IsCompatibleVersion(header))
throw new InvalidOperationException("Incompatible version");
if (!IsSupportedComprMode(header.ComprMode))
throw new InvalidOperationException("Unsupported compression mode");
if (!IsValidHeader(header))
throw new InvalidOperationException("Loaded SEALHeader is invalid");
if (header.Size > checked((ulong)int.MaxValue))
throw new InvalidOperationException("Object size is larger than 2 GB");
int sizeInt = checked((int)header.Size);
stream.Seek(pos, SeekOrigin.Begin);
byte[] buffer = null;
using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true))
{
buffer = reader.ReadBytes(sizeInt);
}
LoadData(buffer, header.Size, out long outBytes);
// Clear the buffer for safety reasons
Array.Clear(buffer, 0, sizeInt);
return outBytes;
}
catch (OverflowException ex)
{
throw new InvalidOperationException("Size indicated by loaded SEALHeader is out of bounds", ex);
}
}
}
/// <summary>Class to contain header information for legacy headers.</summary>
public abstract class LegacyHeaders
{
/// <summary>Class to enable compatibility with Microsoft SEAL 3.4 headers.</summary>
[StructLayout(LayoutKind.Explicit, Size=16)]
public class SEALHeader_3_4 : ISettable<SEALHeader_3_4>, ISettable<Serialization.SEALHeader>
{
/// <summary>SEALMagic</summary>
[FieldOffset(0)]public ushort Magic = Serialization.SEALMagic;
/// <summary>ZeroByte</summary>
[FieldOffset(2)]public byte ZeroByte = 0;
/// <summary>ComprModeType</summary>
[FieldOffset(3)]public ComprModeType ComprMode = Serialization.ComprModeDefault;
/// <summary>Size</summary>
[FieldOffset(4)]public uint Size = 0;
/// <summary>Reserved</summary>
[FieldOffset(8)]public ulong Reserved = 0;
/// <summary>Creates a new SEALHeader_3_4.</summary>
public SEALHeader_3_4()
{
}
/// <summary>
/// Constructs a new SEALHeader_3_4 by copying a given one.
/// </summary>
/// <param name="copy">The SEALHeader_3_4 to copy from</param>
/// <exception cref="ArgumentNullException">if copy is null</exception>
public SEALHeader_3_4(Serialization.SEALHeader copy)
{
if (null == copy)
throw new ArgumentNullException(nameof(copy));
Set(copy);
}
/// <summary>Copies a given SEALHeader_3_4 to the current one.</summary>
/// <param name="assign">The SEALHeader_3_4 to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(SEALHeader_3_4 assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
Magic = assign.Magic;
ZeroByte = assign.ZeroByte;
ComprMode = assign.ComprMode;
Size = assign.Size;
Reserved = assign.Reserved;
}
/// <summary>Copies a given SEALHeader to the current one as a byte array.</summary>
/// <param name="assign">The SEALHeader to copy from</param>
/// <exception cref="ArgumentNullException">if assign is null</exception>
public void Set(Serialization.SEALHeader assign)
{
if (null == assign)
throw new ArgumentNullException(nameof(assign));
GCHandle gch = GCHandle.Alloc(this, GCHandleType.Pinned);
Marshal.StructureToPtr(assign, gch.AddrOfPinnedObject(), false);
gch.Free();
}
};
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// Static methods for object validity checking.
/// </summary>
public static class ValCheck
{
/// <summary>
/// Check whether the given plaintext is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// plaintext data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="plaintext">The plaintext to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either plaintext or context is null</exception>
public static bool IsValidFor(Plaintext plaintext, SEALContext context)
{
if (null == plaintext)
throw new ArgumentNullException(nameof(plaintext));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_Plaintext_IsValidFor(plaintext.NativePtr, context.NativePtr, out bool result);
return result;
}
/// <summary>
/// Check whether the given ciphertext is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// ciphertext data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="ciphertext">The ciphertext to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either ciphertext or context is null</exception>
public static bool IsValidFor(Ciphertext ciphertext, SEALContext context)
{
if (null == ciphertext)
throw new ArgumentNullException(nameof(ciphertext));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_Ciphertext_IsValidFor(ciphertext.NativePtr, context.NativePtr, out bool result);
return result;
}
/// <summary>
/// Check whether the given secret key is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// secret key data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="secretKey">The secret key to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either secretKey or context is null</exception>
public static bool IsValidFor(SecretKey secretKey, SEALContext context)
{
if (null == secretKey)
throw new ArgumentNullException(nameof(secretKey));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_SecretKey_IsValidFor(secretKey.NativePtr, context.NativePtr, out bool result);
return result;
}
/// <summary>
/// Check whether the given public key is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// public key data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="publicKey">The public key to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either publicKey or context is null</exception>
public static bool IsValidFor(PublicKey publicKey, SEALContext context)
{
if (null == publicKey)
throw new ArgumentNullException(nameof(publicKey));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_PublicKey_IsValidFor(publicKey.NativePtr, context.NativePtr, out bool result);
return result;
}
/// <summary>
/// Check whether the given KSwitchKeys is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// KSwitchKeys data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="kswitchKeys">The KSwitchKeys to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either kswitchKeys or context is null</exception>
public static bool IsValidFor(KSwitchKeys kswitchKeys, SEALContext context)
{
if (null == kswitchKeys)
throw new ArgumentNullException(nameof(kswitchKeys));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_KSwitchKeys_IsValidFor(kswitchKeys.NativePtr, context.NativePtr, out bool result);
return result;
}
/// <summary>
/// Check whether the given RelinKeys is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// RelinKeys data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="relinKeys">The RelinKeys to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either relinKeys or context is null</exception>
public static bool IsValidFor(RelinKeys relinKeys, SEALContext context)
{
if (null == relinKeys)
throw new ArgumentNullException(nameof(relinKeys));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_RelinKeys_IsValidFor(relinKeys.NativePtr, context.NativePtr, out bool result);
return result;
}
/// <summary>
/// Check whether the given GaloisKeys is valid for a given SEALContext. If the
/// given SEALContext is not set, the encryption parameters are invalid, or the
/// GaloisKeys data does not match the SEALContext, this function returns false.
/// Otherwise, returns true.
/// </summary>
/// <param name="galoisKeys">The GaloisKeys to check</param>
/// <param name="context">The SEALContext</param>
/// <exception cref="ArgumentNullException">if either galoisKeys or context is null</exception>
public static bool IsValidFor(GaloisKeys galoisKeys, SEALContext context)
{
if (null == galoisKeys)
throw new ArgumentNullException(nameof(galoisKeys));
if (null == context)
throw new ArgumentNullException(nameof(context));
NativeMethods.ValCheck_GaloisKeys_IsValidFor(galoisKeys.NativePtr, context.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.IO;
using System.Text;
namespace Microsoft.Research.SEAL
{
/// <summary>
/// This class contains static methods for retrieving Microsoft SEAL's version numbers.
/// </summary>
/// <remark>
/// Use the name SEALVersion to distinguish it from System.Version.
/// </remark>
public static class SEALVersion
{
/// <summary>
/// Returns Microsoft SEAL's version number string.
/// </summary>
static public string Version => $"{SEALVersion.Major}.{SEALVersion.Minor}.{SEALVersion.Patch}";
///
/// <summary>
/// Returns Microsoft SEAL's major version number.
/// </summary>
static public byte Major
{
get
{
NativeMethods.Version_Major(out byte result);
return result;
}
}
/// <summary>
/// Returns Microsoft SEAL's minor version number.
/// </summary>
static public byte Minor
{
get
{
NativeMethods.Version_Minor(out byte result);
return result;
}
}
/// <summary>
/// Returns Microsoft SEAL's patch version number.
/// </summary>
static public byte Patch
{
get
{
NativeMethods.Version_Patch(out byte result);
return result;
}
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
namespace Microsoft.Research.SEAL.Tools
{
/// <summary>
/// Class that implements the Disposable pattern
/// </summary>
public class DisposableObject : IDisposable
{
/// <summary>
/// Derived classes should override this method to release managed resources.
/// </summary>
protected virtual void DisposeManagedResources()
{
}
/// <summary>
/// Derived classes should override this method to release native resources.
/// </summary>
protected virtual void DisposeNativeResources()
{
}
/// <summary>
/// Whether this object is disposed
/// </summary>
public bool IsDisposed
{
get
{
return disposedValue;
}
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
private void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
DisposeManagedResources();
}
DisposeNativeResources();
disposedValue = true;
}
}
/// <summary>
/// DisposableObject destructor
/// </summary>
~DisposableObject()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
/// <summary>
/// This code is added to correctly implement the disposable pattern.
/// </summary>
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
namespace Microsoft.Research.SEAL.Tools
{
/// <summary>
/// Class that encapsulates the behavior of a class backed by a
/// pointer to a native object.
///
/// In particular, this class encapsulates the correct disposal
/// of the native pointer.
/// </summary>
public abstract class NativeObject : DisposableObject
{
/// <summary>
/// Construct a NativeObject instance
/// </summary>
public NativeObject()
{
NativePtr = IntPtr.Zero;
owned_ = true;
}
/// <summary>
/// Construct a NativeObject instance initializing it with a pointer
/// to a native object.
/// </summary>
/// <param name="nativePtr">Pointer to native object.</param>
/// <param name="owned">Whether this instance owns the native pointer.</param>
public NativeObject(IntPtr nativePtr, bool owned = true)
{
NativePtr = nativePtr;
owned_ = owned;
}
/// <summary>
/// Descendants should call the appropriate method to
/// destroy the backing native object.
/// </summary>
protected abstract void DestroyNativeObject();
/// <summary>
/// Destroy native object if necessary
/// </summary>
protected override void DisposeNativeResources()
{
base.DisposeNativeResources();
if (owned_ && !IntPtr.Zero.Equals(NativePtr))
{
DestroyNativeObject();
}
NativePtr = IntPtr.Zero;
}
/// <summary>
/// Get/Set pointer to native object
/// </summary>
internal IntPtr NativePtr
{
get
{
if (IsDisposed)
{
Type objType = this.GetType();
string objName = objType?.FullName ?? "Unknown object name";
throw new ObjectDisposedException(objName);
}
return nativePtr_;
}
set
{
nativePtr_ = value;
}
}
/// <summary>
/// Whether this instance owns the native pointer.
/// </summary>
private readonly bool owned_ = true;
/// <summary>
/// Pointer to native object
/// </summary>
private IntPtr nativePtr_ = IntPtr.Zero;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
namespace Microsoft.Research.SEAL.Tools
{
static class Utilities
{
public static readonly int BitsPerUInt64 = 64;
public static readonly int BitsPerUInt8 = 8;
public static int DivideRoundUp(int value, int divisor)
{
return (value + divisor - 1) / divisor;
}
public static int ComputeArrayHashCode(ulong[] array)
{
const int hash_seed = 17;
const int hash_multiply = 23;
int hash = hash_seed;
unchecked
{
for (int i = 0; i < array.Length; i++)
{
ulong value = array[i];
if (value != 0)
{
hash *= hash_multiply;
hash += (int)value;
value >>= 32;
hash *= hash_multiply;
hash += (int)value;
}
}
}
return hash;
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
namespace SEALNetTest
{
[TestClass]
public class BatchEncoderTests
{
[TestMethod]
public void EncodeULongTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
parms.PolyModulusDegree = 64;
parms.CoeffModulus = CoeffModulus.Create(64, new int[]{ 60 });
parms.PlainModulus = new Modulus(257);
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
BatchEncoder encoder = new BatchEncoder(context);
Assert.AreEqual(64ul, encoder.SlotCount);
List<ulong> plainList = new List<ulong>();
for (ulong i = 0; i < encoder.SlotCount; i++)
{
plainList.Add((ulong)i);
}
Plaintext plain = new Plaintext();
encoder.Encode(plainList, plain);
List<ulong> plainList2 = new List<ulong>();
encoder.Decode(plain, plainList2);
for (ulong i = 0; i < encoder.SlotCount; i++)
{
Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
}
for (ulong i = 0; i < encoder.SlotCount; i++)
{
plainList[checked((int)i)] = 5;
}
encoder.Encode(plainList, plain);
Assert.AreEqual("5", plain.ToString());
encoder.Decode(plain, plainList2);
for (ulong i = 0; i < encoder.SlotCount; i++)
{
Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
}
List<ulong> shortList = new List<ulong>();
for (ulong i = 0; i < 20; i++)
{
shortList.Add(i);
}
encoder.Encode(shortList, plain);
List<ulong> shortList2 = new List<ulong>();
encoder.Decode(plain, shortList2);
Assert.AreEqual(20, shortList.Count);
Assert.AreEqual(64, shortList2.Count);
for (int i = 0; i < 20; i++)
{
Assert.AreEqual(shortList[i], shortList2[i]);
}
for (ulong i = 20; i < encoder.SlotCount; i++)
{
Assert.AreEqual(0ul, shortList2[checked((int)i)]);
}
}
[TestMethod]
public void EncodeLongTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
parms.PolyModulusDegree = 64;
parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 60 });
parms.PlainModulus = new Modulus(257);
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
BatchEncoder encoder = new BatchEncoder(context);
Assert.AreEqual(64ul, encoder.SlotCount);
List<long> plainList = new List<long>();
for (ulong i = 0; i < encoder.SlotCount; i++)
{
plainList.Add((long)i);
}
Plaintext plain = new Plaintext();
encoder.Encode(plainList, plain);
List<long> plainList2 = new List<long>();
encoder.Decode(plain, plainList2);
for (ulong i = 0; i < encoder.SlotCount; i++)
{
Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
}
for (ulong i = 0; i < encoder.SlotCount; i++)
{
plainList[checked((int)i)] = 5;
}
encoder.Encode(plainList, plain);
Assert.AreEqual("5", plain.ToString());
encoder.Decode(plain, plainList2);
for (ulong i = 0; i < encoder.SlotCount; i++)
{
Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
}
List<long> shortList = new List<long>();
for (int i = 0; i < 20; i++)
{
shortList.Add((long)i);
}
encoder.Encode(shortList, plain);
List<long> shortList2 = new List<long>();
encoder.Decode(plain, shortList2);
Assert.AreEqual(20, shortList.Count);
Assert.AreEqual(64, shortList2.Count);
for (int i = 0; i < 20; i++)
{
Assert.AreEqual(shortList[i], shortList2[i]);
}
for (ulong i = 20; i < encoder.SlotCount; i++)
{
Assert.AreEqual(0L, shortList2[checked((int)i)]);
}
}
[TestMethod]
public void EncodeInPlaceTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }),
PlainModulus = new Modulus(257)
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
BatchEncoder encoder = new BatchEncoder(context);
Assert.AreEqual(64ul, encoder.SlotCount);
Plaintext plain = new Plaintext("6x^5 + 5x^4 + 4x^3 + 3x^2 + 2x^1 + 1");
Assert.AreEqual(6ul, plain.CoeffCount);
encoder.Encode(plain);
Assert.AreEqual(64ul, plain.CoeffCount);
encoder.Decode(plain);
Assert.AreEqual(64ul, plain.CoeffCount);
for (ulong i = 0; i < 6; i++)
{
Assert.AreEqual((i + 1), plain[i]);
}
for (ulong i = 6; i < plain.CoeffCount; i++)
{
Assert.AreEqual(0ul, plain[i]);
}
}
[TestMethod]
public void SchemeIsCKKSTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 8,
CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
Utilities.AssertThrows<ArgumentException>(() =>
{
BatchEncoder encoder = new BatchEncoder(context);
});
}
[TestMethod]
public void ExceptionsTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }),
PlainModulus = new Modulus(257)
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
BatchEncoder enc = new BatchEncoder(context);
List<ulong> valu = new List<ulong>();
List<ulong> valu_null = null;
List<long> vall = new List<long>();
List<long> vall_null = null;
Plaintext plain = new Plaintext();
Plaintext plain_null = null;
MemoryPoolHandle pool_uninit = new MemoryPoolHandle();
Utilities.AssertThrows<ArgumentNullException>(() => enc = new BatchEncoder(null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(valu, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(valu_null, plain));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(vall, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(vall_null, plain));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(plain_null));
Utilities.AssertThrows<ArgumentException>(() => enc.Encode(plain, pool_uninit));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain, valu_null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain_null, valu));
Utilities.AssertThrows<ArgumentException>(() => enc.Decode(plain, valu, pool_uninit));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain, vall_null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain_null, vall));
Utilities.AssertThrows<ArgumentException>(() => enc.Decode(plain, vall, pool_uninit));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Decode(plain_null));
Utilities.AssertThrows<ArgumentException>(() => enc.Decode(plain, pool_uninit));
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Numerics;
namespace SEALNetTest
{
[TestClass]
public class BigUIntTests
{
[TestMethod]
public void EmptyConstructorTest()
{
BigUInt bui = new BigUInt();
Assert.IsTrue(bui.IsZero);
Assert.AreEqual(0, bui.BitCount);
}
[TestMethod]
public void BitCountConstructorTest()
{
BigUInt bui = new BigUInt(bitCount: 70);
Assert.IsTrue(bui.IsZero);
Assert.AreEqual(70, bui.BitCount);
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(0, bui.GetSignificantBitCount());
}
[TestMethod]
public void HexStringConstructorTest()
{
BigUInt bui = new BigUInt("1234567890ABCDEF1234567890ABCDEF");
Assert.IsFalse(bui.IsZero);
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(125, bui.BitCount);
Assert.AreEqual(125, bui.GetSignificantBitCount());
Assert.AreEqual(0x1234567890ABCDEFul, bui.Data(0));
Assert.AreEqual(0x1234567890ABCDEFul, bui.Data(1));
bui = new BigUInt("FEDCBAFEDCBA0987654321");
Assert.IsFalse(bui.IsZero);
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(88, bui.BitCount);
Assert.AreEqual(88, bui.GetSignificantBitCount());
Assert.AreEqual(0xFEDCBAul, bui.Data(1));
Assert.AreEqual(0xFEDCBA0987654321ul, bui.Data(0));
bui = new BigUInt(bitCount: 80, hexString: "DEADBEEF");
Assert.IsFalse(bui.IsZero);
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(80, bui.BitCount);
Assert.AreEqual(32, bui.GetSignificantBitCount());
Assert.AreEqual(0ul, bui.Data(1));
Assert.AreEqual(0xDEADBEEFul, bui.Data(0));
}
[TestMethod]
public void U64ConstructorTest()
{
BigUInt bui = new BigUInt(bitCount: 80, value: 12345ul);
Assert.IsFalse(bui.IsZero);
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(14, bui.GetSignificantBitCount());
Assert.AreEqual(0ul, bui.Data(1));
Assert.AreEqual(12345ul, bui.Data(0));
}
[TestMethod]
public void BigIntegerConstructorTest()
{
BigInteger bi = new BigInteger(12345);
BigUInt bui = new BigUInt(bi);
Assert.IsFalse(bui.IsZero);
Assert.AreEqual(14, bui.BitCount);
Assert.AreEqual(2ul, bui.ByteCount);
Assert.AreEqual(14, bui.GetSignificantBitCount());
Assert.AreEqual(1ul, bui.UInt64Count);
Assert.AreEqual(12345ul, bui.Data(0));
}
[TestMethod]
public void CopyConstructorTest()
{
BigUInt bui1 = new BigUInt("DEADBEEF");
BigUInt bui2 = new BigUInt("1234567890ABCDEF1234567890ABCDEF");
BigUInt bui3 = new BigUInt(bui1);
Assert.AreEqual(1ul, bui3.UInt64Count);
Assert.AreEqual(32, bui3.GetSignificantBitCount());
Assert.AreEqual(0xDEADBEEFul, bui3.Data(0));
Assert.IsTrue(bui1.Equals(bui3));
bui3 = new BigUInt(bui2);
Assert.AreEqual(2ul, bui3.UInt64Count);
Assert.AreEqual(125, bui3.BitCount);
Assert.AreEqual(125, bui3.GetSignificantBitCount());
Assert.AreEqual(0x1234567890ABCDEFul, bui3.Data(0));
Assert.AreEqual(0x1234567890ABCDEFul, bui3.Data(1));
Assert.IsTrue(bui2.Equals(bui3));
}
[TestMethod]
public void EmptyBigUIntNET()
{
var biguint = new BigUInt();
Assert.AreEqual(0, biguint.BitCount);
Assert.AreEqual(0ul, biguint.ByteCount);
Assert.AreEqual(0ul, biguint.UInt64Count);
Assert.IsTrue(biguint.UInt64Count == 0ul);
Assert.AreEqual(0, biguint.GetSignificantBitCount());
Assert.AreEqual("0", biguint.ToString());
Assert.IsTrue(biguint.IsZero);
Assert.IsFalse(biguint.IsAlias);
biguint.SetZero();
var biguint2 = new BigUInt();
Assert.IsTrue(biguint.Equals(biguint2));
biguint.Resize(1);
Assert.AreEqual(1, biguint.BitCount);
Assert.IsTrue(biguint.UInt64Count != 0ul);
Assert.IsFalse(biguint.IsAlias);
biguint.Resize(0);
Assert.AreEqual(0, biguint.BitCount);
Assert.IsTrue(biguint.UInt64Count == 0ul);
Assert.IsFalse(biguint.IsAlias);
}
[TestMethod]
public void BigUInt64BitsNET()
{
var biguint = new BigUInt(64);
Assert.AreEqual(64, biguint.BitCount);
Assert.AreEqual(8ul, biguint.ByteCount);
Assert.AreEqual(1ul, biguint.UInt64Count);
Assert.AreEqual(0, biguint.GetSignificantBitCount());
Assert.AreEqual("0", biguint.ToString());
Assert.IsTrue(biguint.IsZero);
Assert.IsTrue(biguint.UInt64Count != 0);
Assert.AreEqual(0UL, biguint.Data(0));
Assert.AreEqual(0, biguint[0]);
Assert.AreEqual(0, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
biguint.Set(1);
Assert.AreEqual(1, biguint.GetSignificantBitCount());
Assert.AreEqual("1", biguint.ToString());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual(1UL, biguint.Data(0));
Assert.AreEqual(1, biguint[0]);
Assert.AreEqual(0, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
biguint.SetZero();
Assert.IsTrue(biguint.IsZero);
Assert.AreEqual(0UL, biguint.Data(0));
biguint.Set("7FFFFFFFFFFFFFFF");
Assert.AreEqual(63, biguint.GetSignificantBitCount());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual("7FFFFFFFFFFFFFFF", biguint.ToString());
Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, biguint.Data(0));
Assert.AreEqual(0xFF, biguint[0]);
Assert.AreEqual(0xFF, biguint[1]);
Assert.AreEqual(0xFF, biguint[2]);
Assert.AreEqual(0xFF, biguint[3]);
Assert.AreEqual(0xFF, biguint[4]);
Assert.AreEqual(0xFF, biguint[5]);
Assert.AreEqual(0xFF, biguint[6]);
Assert.AreEqual(0x7F, biguint[7]);
biguint.Set("FFFFFFFFFFFFFFFF");
Assert.AreEqual(64, biguint.GetSignificantBitCount());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual("FFFFFFFFFFFFFFFF", biguint.ToString());
Assert.AreEqual(0xFFFFFFFFFFFFFFFFUL, biguint.Data(0));
Assert.AreEqual(0xFF, biguint[0]);
Assert.AreEqual(0xFF, biguint[1]);
Assert.AreEqual(0xFF, biguint[2]);
Assert.AreEqual(0xFF, biguint[3]);
Assert.AreEqual(0xFF, biguint[4]);
Assert.AreEqual(0xFF, biguint[5]);
Assert.AreEqual(0xFF, biguint[6]);
Assert.AreEqual(0xFF, biguint[7]);
biguint.Set(0x8001);
Assert.AreEqual(16, biguint.GetSignificantBitCount());
Assert.AreEqual("8001", biguint.ToString());
Assert.AreEqual(0x8001UL, biguint.Data(0));
Assert.AreEqual(0x01, biguint[0]);
Assert.AreEqual(0x80, biguint[1]);
Assert.AreEqual(0x00, biguint[2]);
Assert.AreEqual(0x00, biguint[3]);
Assert.AreEqual(0x00, biguint[4]);
Assert.AreEqual(0x00, biguint[5]);
Assert.AreEqual(0x00, biguint[6]);
Assert.AreEqual(0x00, biguint[7]);
}
[TestMethod]
public void BigUInt99BitsNET()
{
var biguint = new BigUInt(99);
Assert.AreEqual(99, biguint.BitCount);
Assert.IsTrue(biguint.UInt64Count != 0ul);
Assert.AreEqual(13ul, biguint.ByteCount);
Assert.AreEqual(2ul, biguint.UInt64Count);
Assert.AreEqual(0, biguint.GetSignificantBitCount());
Assert.AreEqual("0", biguint.ToString());
Assert.IsTrue(biguint.IsZero);
Assert.AreEqual(0UL, biguint.Data(0));
Assert.AreEqual(0UL, biguint.Data(1));
Assert.AreEqual(0, biguint[0]);
Assert.AreEqual(0, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
Assert.AreEqual(0, biguint[8]);
Assert.AreEqual(0, biguint[9]);
Assert.AreEqual(0, biguint[10]);
Assert.AreEqual(0, biguint[11]);
Assert.AreEqual(0, biguint[12]);
biguint.Set(1);
Assert.AreEqual(1, biguint.GetSignificantBitCount());
Assert.AreEqual("1", biguint.ToString());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual(13ul, biguint.ByteCount);
Assert.AreEqual(2ul, biguint.UInt64Count);
Assert.AreEqual(1UL, biguint.Data(0));
Assert.AreEqual(0UL, biguint.Data(1));
Assert.AreEqual(1, biguint[0]);
Assert.AreEqual(0, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
Assert.AreEqual(0, biguint[8]);
Assert.AreEqual(0, biguint[9]);
Assert.AreEqual(0, biguint[10]);
Assert.AreEqual(0, biguint[11]);
Assert.AreEqual(0, biguint[12]);
biguint.SetZero();
Assert.IsTrue(biguint.IsZero);
Assert.AreEqual(0UL, biguint.Data(0));
Assert.AreEqual(0UL, biguint.Data(1));
biguint.Set("7FFFFFFFFFFFFFFFFFFFFFFFF");
Assert.AreEqual(99, biguint.GetSignificantBitCount());
Assert.AreEqual("7FFFFFFFFFFFFFFFFFFFFFFFF", biguint.ToString());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual(0xFFFFFFFFFFFFFFFFUL, biguint.Data(0));
Assert.AreEqual(0x7FFFFFFFFUL, biguint.Data(1));
Assert.AreEqual(0xFF, biguint[0]);
Assert.AreEqual(0xFF, biguint[1]);
Assert.AreEqual(0xFF, biguint[2]);
Assert.AreEqual(0xFF, biguint[3]);
Assert.AreEqual(0xFF, biguint[4]);
Assert.AreEqual(0xFF, biguint[5]);
Assert.AreEqual(0xFF, biguint[6]);
Assert.AreEqual(0xFF, biguint[7]);
Assert.AreEqual(0xFF, biguint[8]);
Assert.AreEqual(0xFF, biguint[9]);
Assert.AreEqual(0xFF, biguint[10]);
Assert.AreEqual(0xFF, biguint[11]);
Assert.AreEqual(0x07, biguint[12]);
biguint.SetZero();
Assert.IsTrue(biguint.IsZero);
Assert.AreEqual(0UL, biguint.Data(0));
Assert.AreEqual(0UL, biguint.Data(1));
biguint.Set("4000000000000000000000000");
Assert.AreEqual(99, biguint.GetSignificantBitCount());
Assert.AreEqual("4000000000000000000000000", biguint.ToString());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual(0UL, biguint.Data(0));
Assert.AreEqual(0x400000000UL, biguint.Data(1));
Assert.AreEqual(0, biguint[0]);
Assert.AreEqual(0, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
Assert.AreEqual(0, biguint[8]);
Assert.AreEqual(0, biguint[9]);
Assert.AreEqual(0, biguint[10]);
Assert.AreEqual(0, biguint[11]);
Assert.AreEqual(0x04, biguint[12]);
biguint.Set(0x8001);
Assert.AreEqual(16, biguint.GetSignificantBitCount());
Assert.AreEqual("8001", biguint.ToString());
Assert.IsFalse(biguint.IsZero);
Assert.AreEqual(0x8001UL, biguint.Data(0));
Assert.AreEqual(0UL, biguint.Data(1));
Assert.AreEqual(0x01, biguint[0]);
Assert.AreEqual(0x80, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
Assert.AreEqual(0, biguint[8]);
Assert.AreEqual(0, biguint[9]);
Assert.AreEqual(0, biguint[10]);
Assert.AreEqual(0, biguint[11]);
Assert.AreEqual(0, biguint[12]);
var biguint2 = new BigUInt("123");
Assert.IsFalse(biguint.Equals(biguint2));
Assert.IsFalse(biguint2.Equals(biguint));
Assert.AreNotEqual(biguint.GetHashCode(), biguint2.GetHashCode());
biguint.Set(biguint2);
Assert.IsTrue(biguint.Equals(biguint2));
Assert.IsTrue(biguint2.Equals(biguint));
Assert.AreEqual(biguint.GetHashCode(), biguint2.GetHashCode());
Assert.AreEqual(9, biguint.GetSignificantBitCount());
Assert.AreEqual("123", biguint.ToString());
Assert.AreEqual(0x123UL, biguint.Data(0));
Assert.AreEqual(0UL, biguint.Data(1));
Assert.AreEqual(0x23, biguint[0]);
Assert.AreEqual(0x01, biguint[1]);
Assert.AreEqual(0, biguint[2]);
Assert.AreEqual(0, biguint[3]);
Assert.AreEqual(0, biguint[4]);
Assert.AreEqual(0, biguint[5]);
Assert.AreEqual(0, biguint[6]);
Assert.AreEqual(0, biguint[7]);
Assert.AreEqual(0, biguint[8]);
Assert.AreEqual(0, biguint[9]);
Assert.AreEqual(0, biguint[10]);
Assert.AreEqual(0, biguint[11]);
Assert.AreEqual(0, biguint[12]);
biguint.Resize(8);
Assert.AreEqual(8, biguint.BitCount);
Assert.AreEqual(1ul, biguint.UInt64Count);
Assert.AreEqual("23", biguint.ToString());
biguint.Resize(100);
Assert.AreEqual(100, biguint.BitCount);
Assert.AreEqual(2ul, biguint.UInt64Count);
Assert.AreEqual("23", biguint.ToString());
biguint.Resize(0);
Assert.AreEqual(0, biguint.BitCount);
Assert.AreEqual(0ul, biguint.UInt64Count);
Assert.IsTrue(biguint.UInt64Count == 0);
}
[TestMethod]
public void SaveLoadUIntNET()
{
using (MemoryStream stream = new MemoryStream())
{
var value = new BigUInt();
var value2 = new BigUInt("100");
stream.Seek(0, SeekOrigin.Begin);
value.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
value2.Load(stream);
Assert.AreEqual(value, value2);
value.Set("123");
stream.Seek(0, SeekOrigin.Begin);
value.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
value2.Load(stream);
Assert.AreEqual(value, value2);
value.Set("FFFFFFFFFFFFFFFFFFFFFFFFFF");
stream.Seek(0, SeekOrigin.Begin);
value.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
value2.Load(stream);
Assert.AreEqual(value, value2);
value.Set("0");
stream.Seek(0, SeekOrigin.Begin);
value.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
value2.Load(stream);
Assert.AreEqual(value, value2);
}
}
[TestMethod]
public void DuplicateToNET()
{
var original = new BigUInt(123);
original.Set(56789);
var target = new BigUInt();
original.DuplicateTo(target);
Assert.AreEqual(target.BitCount, original.BitCount);
Assert.IsTrue(target.Equals(original));
}
[TestMethod]
public void DuplicateFromNET()
{
var original = new BigUInt(123);
original.Set(56789);
var target = new BigUInt();
target.DuplicateFrom(original);
Assert.AreEqual(target.BitCount, original.BitCount);
Assert.IsTrue(target.Equals(original));
}
[TestMethod]
public void ToBigIntegerTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigInteger bi = bui.ToBigInteger();
Assert.IsNotNull(bi);
Assert.IsFalse(bi.IsEven);
Assert.IsFalse(bi.IsZero);
Assert.AreEqual(0, bi.CompareTo(0xDEADBEEFul));
}
[TestMethod]
public void ToDecimalStringTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
string decStr = bui.ToDecimalString();
Assert.IsNotNull(decStr);
Assert.IsTrue("3735928559".Equals(decStr));
}
[TestMethod]
public void CompareToTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt other = new BigUInt("DEADBFFF");
Assert.IsTrue(bui.CompareTo(other) < 0);
Assert.IsTrue(other.CompareTo(bui) > 0);
BigUInt third = new BigUInt(bui);
Assert.AreNotSame(bui, third);
Assert.AreEqual(0, bui.CompareTo(third));
Assert.IsTrue(bui.CompareTo(null) > 0);
}
[TestMethod]
public void ModuloInvertFail1Test()
{
// Should fail when modulus is zero
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt mod = new BigUInt();
Assert.IsTrue(mod.IsZero);
Assert.IsFalse(bui.IsZero);
Utilities.AssertThrows<ArgumentException>(() => bui.ModuloInvert(mod));
}
[TestMethod]
public void ModuloInvertFail2Test()
{
// Should fail when modulus is not greater than the BigUInt value
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt mod = new BigUInt("BEEF");
Assert.IsFalse(mod.IsZero);
Assert.IsFalse(bui.IsZero);
Utilities.AssertThrows<ArgumentException>(() => bui.ModuloInvert(mod));
}
[TestMethod]
public void ModuloInvertFail3Test()
{
// Should fail when biguint value and modulus are not coprime
BigUInt bui = new BigUInt(bitCount: 64, value: 12);
BigUInt mod = new BigUInt(bitCount: 64, value: 24);
Assert.IsFalse(mod.IsZero);
Assert.IsFalse(bui.IsZero);
Utilities.AssertThrows<ArgumentException>(() => bui.ModuloInvert(mod));
}
[TestMethod]
public void ModuloInvertTest()
{
BigUInt bui = new BigUInt(bitCount: 64, value: 12);
BigUInt mod = new BigUInt(bitCount: 64, value: 25);
BigUInt inverse1 = bui.ModuloInvert(mod);
Assert.AreEqual(23ul, inverse1.Data(0));
BigUInt inverse2 = bui.ModuloInvert(modulus: 25ul);
Assert.AreEqual(23ul, inverse2.Data(0));
}
[TestMethod]
public void TryModuloInvertFail1Test()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt mod = new BigUInt();
BigUInt inverse = new BigUInt();
// Should fail when modulus is zero
Assert.IsTrue(mod.IsZero);
Utilities.AssertThrows<ArgumentException>(() => bui.TryModuloInvert(mod, inverse));
}
[TestMethod]
public void TryModuloInvertFail2Test()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt mod = new BigUInt("BEEF");
BigUInt inverse = new BigUInt();
// Should fail when biguint is bigger than modulus
Assert.IsFalse(mod.IsZero);
Utilities.AssertThrows<ArgumentException>(() => bui.TryModuloInvert(mod, inverse));
}
[TestMethod]
public void TryModuloInvertTest()
{
BigUInt bui = new BigUInt(bitCount: 64, value: 12);
BigUInt mod = new BigUInt(bitCount: 64, value: 25);
BigUInt inverse1 = new BigUInt();
BigUInt inverse2 = new BigUInt();
Assert.IsTrue(bui.TryModuloInvert(mod, inverse1));
Assert.AreEqual(23ul, inverse1.Data(0));
Assert.IsTrue(bui.TryModuloInvert(modulus: 25ul, inverse: inverse2));
Assert.AreEqual(23ul, inverse2.Data(0));
// Should fail (but not throw) when biguint value and modulus are not coprime
BigUInt bui2 = new BigUInt(bitCount: 64, value: 12);
BigUInt mod2 = new BigUInt(bitCount: 64, value: 24);
Assert.IsFalse(mod2.IsZero);
Assert.IsFalse(bui2.IsZero);
Assert.IsFalse(bui2.TryModuloInvert(mod2, inverse1));
}
[TestMethod]
public void DivideRemainderTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt op = new BigUInt("BEEF");
BigUInt remainder = new BigUInt();
BigUInt result = bui.DivideRemainder(op, remainder);
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x12a90ul, result.Data(0));
Assert.AreEqual(1ul, remainder.UInt64Count);
Assert.AreEqual(0x227Ful, remainder.Data(0));
BigUInt result2 = bui.DivideRemainder(0xDEADul, remainder);
Assert.AreEqual(1ul, result2.UInt64Count);
Assert.AreEqual(0x10000ul, result2.Data(0));
Assert.AreEqual(1ul, remainder.UInt64Count);
Assert.AreEqual(0xBEEFul, remainder.Data(0));
}
[TestMethod]
public void OperatorPlusTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt newone = +bui;
Assert.AreEqual(1ul, newone.UInt64Count);
Assert.AreEqual(0xDEADBEEFul, newone.Data(0));
}
[TestMethod]
public void OperatorMinusTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt newone = -bui;
Assert.AreEqual(1ul, newone.UInt64Count);
Assert.AreEqual(0x21524111ul, newone.Data(0));
}
[TestMethod]
public void OperatorTildeTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt newone = ~bui;
Assert.AreEqual(1ul, newone.UInt64Count);
Assert.AreEqual(0x21524110ul, newone.Data(0));
}
[TestMethod]
public void OperatorPlusPlusTest()
{
BigUInt bui = new BigUInt("12345678901234567890");
bui++;
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(0x1234ul, bui.Data(1));
Assert.AreEqual(0x5678901234567891ul, bui.Data(0));
}
[TestMethod]
public void OperatorMinusMinusTest()
{
BigUInt bui = new BigUInt("12345678901234567890");
bui--;
Assert.AreEqual(2ul, bui.UInt64Count);
Assert.AreEqual(0x1234ul, bui.Data(1));
Assert.AreEqual(0x567890123456788Ful, bui.Data(0));
}
[TestMethod]
public void OperatorAddTest()
{
BigUInt bui = new BigUInt("1234567890");
BigUInt op = new BigUInt("6543210");
BigUInt result = bui + op;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x123AAAAAA0ul, result.Data(0));
BigUInt result2 = bui + 0x9876543210ul;
Assert.AreEqual(1ul, result2.UInt64Count);
Assert.AreEqual(0xAAAAAAAAA0ul, result2.Data(0));
}
[TestMethod]
public void OperatorSubTest()
{
BigUInt bui = new BigUInt("1234567890");
BigUInt op = new BigUInt("6543210");
BigUInt result = bui - op;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x122E024680ul, result.Data(0));
result = bui - 0x76543210ul;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x11BE024680ul, result.Data(0));
}
[TestMethod]
public void OperatorMultTest()
{
BigUInt bui = new BigUInt("12345");
BigUInt op = new BigUInt("ABCDEF");
BigUInt result = bui * op;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0xC379652E6Bul, result.Data(0));
result = bui * 0xFEDCBAul;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x121F998EC22ul, result.Data(0));
}
[TestMethod]
public void OperatorDivTest()
{
BigUInt bui = new BigUInt("1234567890");
BigUInt op = new BigUInt("BEEF");
BigUInt result = bui / op;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x18687Dul, result.Data(0));
result = bui / 0xDEAD;
Assert.AreEqual(1ul, result.UInt64Count);
Assert.AreEqual(0x14EDC6ul, result.Data(0));
}
[TestMethod]
public void OperatorAndTest()
{
BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
BigUInt op = new BigUInt("FEFEFEFEFEFEFEFEFEFEFEFE");
BigUInt result = bui & op;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0xCCCCCCCCul, result.Data(1));
Assert.AreEqual(0xAAAAAAAAAAAAAAAAul, result.Data(0));
result = bui & 0xF0F0F0F0F0;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0ul, result.Data(1));
Assert.AreEqual(0xA0A0A0A0A0ul, result.Data(0));
}
[TestMethod]
public void OperatorOrTest()
{
BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
BigUInt op = new BigUInt("E0E0E0E0E0E0E0E0E0E0E0E0");
BigUInt result = bui | op;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0xEDEDEDEDul, result.Data(1));
Assert.AreEqual(0xEBEBEBEBEBEBEBEBul, result.Data(0));
result = bui | 0x1010101010;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0xCDCDCDCDul, result.Data(1));
Assert.AreEqual(0xABABABBBBBBBBBBBul, result.Data(0));
}
[TestMethod]
public void OperatorXorTest()
{
BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
BigUInt op = new BigUInt("0000FFFFFFFF000000000000");
BigUInt result = bui ^ op;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0xCDCD3232ul, result.Data(1));
Assert.AreEqual(0x5454ABABABABABABul, result.Data(0));
result = bui ^ 0xF0F0F0F0F0;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0xCDCDCDCDul, result.Data(1));
Assert.AreEqual(0xABABAB5B5B5B5B5Bul, result.Data(0));
}
[TestMethod]
public void OperatorShiftLeftTest()
{
BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
BigUInt result = bui << 1;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0x19B9B9B9Bul, result.Data(1));
Assert.AreEqual(0x5757575757575756ul, result.Data(0));
result = bui << 2;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0x337373736ul, result.Data(1));
Assert.AreEqual(0xAEAEAEAEAEAEAEACul, result.Data(0));
}
[TestMethod]
public void OperatorShiftRightTest()
{
BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
BigUInt result = bui >> 1;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0x66E6E6E6ul, result.Data(1));
Assert.AreEqual(0xD5D5D5D5D5D5D5D5ul, result.Data(0));
result = bui >> 2;
Assert.AreEqual(2ul, result.UInt64Count);
Assert.AreEqual(0x33737373ul, result.Data(1));
Assert.AreEqual(0x6AEAEAEAEAEAEAEAul, result.Data(0));
}
[TestMethod]
public void OperatorDoubleTest()
{
BigUInt bui = new BigUInt("12345");
double value = (double)bui;
Assert.AreEqual(74565.0, value, delta: 0.1);
bui = new BigUInt("12345678901234567890");
value = (double)bui;
Assert.AreEqual(8.59680582719788E+22, value, delta: 3.5e7);
}
[TestMethod]
public void OperatorFloatTest()
{
BigUInt bui = new BigUInt("12345");
float value = (float)bui;
Assert.AreEqual(74565.0f, value, delta: 0.1);
bui.Set("12345678901234567890");
value = (float)bui;
Assert.AreEqual(8.59680582719788E+22f, value, delta: 0.1f);
}
[TestMethod]
public void OperatorUInt64Test()
{
BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF");
ulong value = (ulong)bui;
Assert.AreEqual(0x1234567890ABCDEFul, value);
}
[TestMethod]
public void OperatorInt64Test()
{
BigUInt bui = new BigUInt("ABCDEF124567890ABCDEF");
long value = (long)bui;
Assert.AreEqual(-1070635735584092689, value);
}
[TestMethod]
public void OperatorUInt32Test()
{
BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF");
uint value = (uint)bui;
Assert.AreEqual(0x90ABCDEFu, value);
}
[TestMethod]
public void OperatorInt32Test()
{
BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF");
int value = (int)bui;
Assert.AreEqual(-1867788817, value);
}
[TestMethod]
public void ExceptionsTest()
{
BigUInt bui = new BigUInt("DEADBEEF");
BigUInt bui1 = null;
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = new BigUInt((BigUInt)null));
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = new BigUInt((string)null));
Utilities.AssertThrows<ArgumentException>(() => bui1 = new BigUInt(bitCount: -1));
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = new BigUInt(bitCount: 64, hexString: null));
Utilities.AssertThrows<ArgumentException>(() => bui1 = new BigUInt(bitCount: -1, hexString: "ABCDEF"));
Utilities.AssertThrows<ArgumentException>(() => bui1 = new BigUInt(bitCount: -1, value: 10ul));
bui1 = new BigUInt();
BigUInt bui2 = new BigUInt();
Utilities.AssertThrows<ArgumentOutOfRangeException>(() => bui.Data(1));
Utilities.AssertThrows<ArgumentOutOfRangeException>(() => bui[5] );
Utilities.AssertThrows<ArgumentOutOfRangeException>(() => bui[5] = 2);
Utilities.AssertThrows<ArgumentNullException>(() => bui.DivideRemainder(bui1, null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.DivideRemainder(null, bui2));
Utilities.AssertThrows<ArgumentException>(() => bui.DivideRemainder(bui1, bui2));
Utilities.AssertThrows<ArgumentNullException>(() => bui.DivideRemainder(1ul, null));
Utilities.AssertThrows<ArgumentException>(() => bui.DivideRemainder(0ul, bui2));
Utilities.AssertThrows<ArgumentNullException>(() => bui.DuplicateFrom(null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.DuplicateTo(null));
Assert.IsFalse(bui.Equals(null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.Load(null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.ModuloInvert(null));
Utilities.AssertThrows<ArgumentException>(() => bui.Resize(bitCount: -1));
Utilities.AssertThrows<ArgumentNullException>(() => bui.Save(null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.Set((BigUInt)null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.Set((string)null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.TryModuloInvert(bui1, null));
Utilities.AssertThrows<ArgumentNullException>(() => bui.TryModuloInvert(null, bui2));
Utilities.AssertThrows<ArgumentException>(() => bui.TryModuloInvert(bui1, bui2));
Utilities.AssertThrows<ArgumentNullException>(() => bui.TryModuloInvert(1ul, null));
bui2 = null;
Utilities.AssertThrows<ArgumentNullException>(() => bui2 = +bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui2 = -bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui2 = ~bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui2++);
Utilities.AssertThrows<ArgumentNullException>(() => bui2--);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui + bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 + bui);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 + 1ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui - bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 - bui);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 - 1ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui * bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 * bui);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 * 1ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui / bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 / bui);
Utilities.AssertThrows<ArgumentException>(() => bui1 = bui / bui1);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 / 1ul);
Utilities.AssertThrows<ArgumentException>(() => bui1 = bui / 0ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui ^ bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 ^ bui);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 ^ 1ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui & bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 & bui);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 & 1ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui | bui2);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 | bui);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 | 1ul);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 << 5);
Utilities.AssertThrows<ArgumentException>(() => bui1 = bui1 << -1);
Utilities.AssertThrows<ArgumentNullException>(() => bui1 = bui2 >> 5);
Utilities.AssertThrows<ArgumentException>(() => bui1 = bui1 >> -1);
Utilities.AssertThrows<ArgumentNullException>(() => { double d = (double)bui2; });
Utilities.AssertThrows<ArgumentNullException>(() => { float f = (float)bui2; });
Utilities.AssertThrows<ArgumentNullException>(() => { ulong u = (ulong)bui2; });
Utilities.AssertThrows<ArgumentNullException>(() => { long l = (long)bui2; });
Utilities.AssertThrows<ArgumentNullException>(() => { uint u = (uint)bui2; });
Utilities.AssertThrows<ArgumentNullException>(() => { int i = (int)bui2; });
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Numerics;
namespace SEALNetTest
{
[TestClass]
public class CKKSEncoderTests
{
[TestMethod]
public void EncodeDecodeDoubleTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
parms.PolyModulusDegree = 64;
parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 });
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
int slots = 16;
Plaintext plain = new Plaintext();
double delta = 1 << 16;
List<Complex> result = new List<Complex>();
CKKSEncoder encoder = new CKKSEncoder(context);
Assert.AreEqual(32ul, encoder.SlotCount);
double value = 10d;
encoder.Encode(value, delta, plain);
encoder.Decode(plain, result);
for (int i = 0; i < slots; i++)
{
double tmp = Math.Abs(value - result[i].Real);
Assert.IsTrue(tmp < 0.5);
}
}
[TestMethod]
public void EncodeDecodeUlongTest()
{
int slots = 32;
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
parms.PolyModulusDegree = (ulong)slots * 2;
parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 });
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
CKKSEncoder encoder = new CKKSEncoder(context);
Plaintext plain = new Plaintext();
List<Complex> result = new List<Complex>();
long value = 15;
encoder.Encode(value, plain);
encoder.Decode(plain, result);
for (int i = 0; i < slots; i++)
{
double tmp = Math.Abs(value - result[i].Real);
Assert.IsTrue(tmp < 0.5);
}
}
[TestMethod]
public void EncodeDecodeComplexTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 64,
CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
CKKSEncoder encoder = new CKKSEncoder(context);
Plaintext plain = new Plaintext();
Complex value = new Complex(3.1415, 2.71828);
encoder.Encode(value, scale: Math.Pow(2, 20), destination: plain);
List<Complex> result = new List<Complex>();
encoder.Decode(plain, result);
Assert.IsTrue(result.Count > 0);
Assert.AreEqual(3.1415, result[0].Real, delta: 0.0001);
Assert.AreEqual(2.71828, result[0].Imaginary, delta: 0.0001);
}
[TestMethod]
public void EncodeDecodeVectorTest()
{
int slots = 32;
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
parms.PolyModulusDegree = (ulong)slots * 2;
parms.CoeffModulus = CoeffModulus.Create((ulong)slots * 2, new int[] { 60, 60, 60, 60 });
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
CKKSEncoder encoder = new CKKSEncoder(context);
List<Complex> values = new List<Complex>(slots);
Random rnd = new Random();
int dataBound = 1 << 30;
double delta = 1ul << 40;
for (int i = 0; i < slots; i++)
{
values.Add(new Complex(rnd.Next() % dataBound, 0));
}
Plaintext plain = new Plaintext();
encoder.Encode(values, delta, plain);
List<Complex> result = new List<Complex>();
encoder.Decode(plain, result);
for (int i = 0; i < slots; i++)
{
double tmp = Math.Abs(values[i].Real - result[i].Real);
Assert.IsTrue(tmp < 0.5);
}
}
[TestMethod]
public void EncodeDecodeVectorDoubleTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 64,
CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
CKKSEncoder encoder = new CKKSEncoder(context);
Plaintext plain = new Plaintext();
double[] values = new double[] { 0.1, 2.3, 34.4 };
encoder.Encode(values, scale: Math.Pow(2, 20), destination: plain);
List<double> result = new List<double>();
encoder.Decode(plain, result);
Assert.IsNotNull(result);
Assert.AreEqual(0.1, result[0], delta: 0.001);
Assert.AreEqual(2.3, result[1], delta: 0.001);
Assert.AreEqual(34.4, result[2], delta: 0.001);
}
[TestMethod]
public void ExceptionsTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 64,
CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
CKKSEncoder encoder = new CKKSEncoder(context);
List<double> vald = new List<double>();
List<double> vald_null = null;
List<Complex> valc = new List<Complex>();
List<Complex> valc_null = null;
Plaintext plain = new Plaintext();
Plaintext plain_null = null;
MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal);
Complex complex = new Complex(1, 2);
Utilities.AssertThrows<ArgumentNullException>(() => encoder = new CKKSEncoder(null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald, ParmsId.Zero, 10.0, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald, null, 10.0, plain));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald_null, ParmsId.Zero, 10.0, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(vald, ParmsId.Zero, 10.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc, ParmsId.Zero, 10.0, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc, null, 10.0, plain));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc_null, ParmsId.Zero, 10.0, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(valc, ParmsId.Zero, 10.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald, 10.0, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(vald_null, 10.0, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(vald, -10.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc, 10.0, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(valc_null, 10.0, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(valc, -10.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10.0, ParmsId.Zero, 20.0, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10.0, null, 20.0, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(10.0, ParmsId.Zero, 20.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10.0, 20.0, plain_null));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(10.0, -20.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(complex, ParmsId.Zero, 10.0, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(complex, null, 10.0, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(complex, ParmsId.Zero, 10.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(complex, 10.0, plain_null));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(complex, -10.0, plain, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10, ParmsId.Zero, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10, null, plain));
Utilities.AssertThrows<ArgumentException>(() => encoder.Encode(10, ParmsId.Zero, plain));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Encode(10, plain_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain, vald_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain_null, vald));
Utilities.AssertThrows<ArgumentException>(() => encoder.Decode(plain, vald, pool));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain, valc_null));
Utilities.AssertThrows<ArgumentNullException>(() => encoder.Decode(plain_null, valc));
Utilities.AssertThrows<ArgumentException>(() => encoder.Decode(plain, valc, pool));
}
}
}
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