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

testing

parent d8df7d47

Too many changes to show.

To preserve performance only 268 of 268+ files are displayed.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using 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));
}
}
}
// 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.IO;
using System.Numerics;
namespace SEALNetTest
{
[TestClass]
public class CiphertextTests
{
[TestMethod]
public void CreateTest()
{
Ciphertext cipher = new Ciphertext();
Assert.IsNotNull(cipher);
Assert.AreEqual(0ul, cipher.Size);
Assert.AreEqual(0ul, cipher.PolyModulusDegree);
Assert.AreEqual(0ul, cipher.CoeffModulusSize);
Ciphertext copy = new Ciphertext(cipher);
Assert.IsNotNull(copy);
Assert.AreEqual(0ul, copy.Size);
Assert.AreEqual(0ul, copy.PolyModulusDegree);
Assert.AreEqual(0ul, copy.CoeffModulusSize);
}
[TestMethod]
public void Create2Test()
{
SEALContext context = GlobalContext.BFVContext;
ParmsId parms = context.FirstParmsId;
Assert.AreNotEqual(0ul, parms.Block[0]);
Assert.AreNotEqual(0ul, parms.Block[1]);
Assert.AreNotEqual(0ul, parms.Block[2]);
Assert.AreNotEqual(0ul, parms.Block[3]);
Ciphertext cipher = new Ciphertext(context, parms);
Assert.AreEqual(parms, cipher.ParmsId);
}
[TestMethod]
public void Create3Test()
{
SEALContext context = GlobalContext.BFVContext;
ParmsId parms = context.FirstParmsId;
Assert.AreNotEqual(0ul, parms.Block[0]);
Assert.AreNotEqual(0ul, parms.Block[1]);
Assert.AreNotEqual(0ul, parms.Block[2]);
Assert.AreNotEqual(0ul, parms.Block[3]);
Ciphertext cipher = new Ciphertext(context, parms, sizeCapacity: 5);
Assert.AreEqual(5ul, cipher.SizeCapacity);
}
[TestMethod]
public void ResizeTest()
{
SEALContext context = GlobalContext.BFVContext;
ParmsId parms = context.FirstParmsId;
Ciphertext cipher = new Ciphertext(context, parms);
Assert.AreEqual(2ul, cipher.SizeCapacity);
cipher.Reserve(context, parms, sizeCapacity: 10);
Assert.AreEqual(10ul, cipher.SizeCapacity);
Ciphertext cipher2 = new Ciphertext();
Assert.AreEqual(0ul, cipher2.SizeCapacity);
cipher2.Reserve(context, 5);
Assert.AreEqual(5ul, cipher2.SizeCapacity);
Ciphertext cipher3 = new Ciphertext();
Assert.AreEqual(0ul, cipher3.SizeCapacity);
cipher3.Reserve(4);
Assert.AreEqual(0ul, cipher3.SizeCapacity);
Ciphertext cipher4 = new Ciphertext(context);
cipher4.Resize(context, context.GetContextData(context.FirstParmsId).NextContextData.ParmsId, 4);
Assert.AreEqual(10ul, cipher.SizeCapacity);
Ciphertext cipher5 = new Ciphertext(context);
cipher5.Resize(context, 6ul);
Assert.AreEqual(6ul, cipher5.SizeCapacity);
}
[TestMethod]
public void ReleaseTest()
{
Ciphertext cipher = new Ciphertext();
Assert.AreEqual(0ul, cipher.Size);
cipher.Resize(4);
Assert.AreEqual(4ul, cipher.Size);
cipher.Release();
Assert.AreEqual(0ul, cipher.Size);
}
[TestMethod]
public void SaveLoadTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Plaintext plain = new Plaintext("2x^3 + 4x^2 + 5x^1 + 6");
Ciphertext cipher = new Ciphertext();
encryptor.Encrypt(plain, cipher);
Assert.AreEqual(2ul, cipher.Size);
Assert.AreEqual(8192ul, cipher.PolyModulusDegree);
Assert.AreEqual(4ul, cipher.CoeffModulusSize);
Ciphertext loaded = new Ciphertext();
Assert.AreEqual(0ul, loaded.Size);
Assert.AreEqual(0ul, loaded.PolyModulusDegree);
Assert.AreEqual(0ul, loaded.CoeffModulusSize);
using (MemoryStream mem = new MemoryStream())
{
cipher.Save(mem);
mem.Seek(offset: 0, loc: SeekOrigin.Begin);
loaded.Load(context, mem);
}
Assert.AreEqual(2ul, loaded.Size);
Assert.AreEqual(8192ul, loaded.PolyModulusDegree);
Assert.AreEqual(4ul, loaded.CoeffModulusSize);
Assert.IsTrue(ValCheck.IsValidFor(loaded, context));
ulong ulongCount = cipher.Size * cipher.PolyModulusDegree * cipher.CoeffModulusSize;
for (ulong i = 0; i < ulongCount; i++)
{
Assert.AreEqual(cipher[i], loaded[i]);
}
}
[TestMethod]
public void IndexTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Plaintext plain = new Plaintext("1");
Ciphertext cipher = new Ciphertext();
encryptor.Encrypt(plain, cipher);
Assert.AreEqual(2ul, cipher.Size);
Assert.AreNotEqual(0ul, cipher[0, 0]);
Assert.AreNotEqual(0ul, cipher[0, 1]);
Assert.AreNotEqual(0ul, cipher[0, 2]);
Assert.AreNotEqual(0ul, cipher[1, 0]);
Assert.AreNotEqual(0ul, cipher[1, 1]);
Assert.AreNotEqual(0ul, cipher[1, 2]);
}
[TestMethod]
public void IndexRangeFail1Test()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Plaintext plain = new Plaintext("1");
Ciphertext cipher = new Ciphertext(context);
encryptor.Encrypt(plain, cipher);
Utilities.AssertThrows<IndexOutOfRangeException>(() =>
{
// We only have 2 polynomials
ulong data = cipher[2, 0];
});
}
[TestMethod]
public void IndexRangeFail2Test()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Plaintext plain = new Plaintext("1");
Ciphertext cipher = new Ciphertext();
encryptor.Encrypt(plain, cipher);
// We only have 2 polynomials
ulong data = cipher[1, 0];
// We should have 8192 coefficients
data = cipher[0, 32767]; // This will succeed
Utilities.AssertThrows<IndexOutOfRangeException>(() =>
{
data = cipher[0, 32768]; // This will fail
});
}
[TestMethod]
public void IndexRangeFail3Test()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Plaintext plain = new Plaintext("1");
Ciphertext cipher = new Ciphertext();
encryptor.Encrypt(plain, cipher);
ulong data = 0;
Utilities.AssertThrows<IndexOutOfRangeException>(() => data = cipher[65536]);
Utilities.AssertThrows<IndexOutOfRangeException>(() => cipher[65536] = 10ul);
}
[TestMethod]
public void ScaleTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 8,
CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: true,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys galoisKeys = keygen.GaloisKeysLocal();
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Evaluator evaluator = new Evaluator(context);
CKKSEncoder encoder = new CKKSEncoder(context);
MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceNew);
Assert.AreEqual(0ul, pool.AllocByteCount);
Ciphertext encrypted = new Ciphertext(pool);
Plaintext plain = new Plaintext();
MemoryPoolHandle cipherPool = encrypted.Pool;
Assert.IsNotNull(cipherPool);
Assert.AreEqual(0ul, cipherPool.AllocByteCount);
List<Complex> input = new List<Complex>()
{
new Complex(1, 1),
new Complex(2, 2),
new Complex(3, 3),
new Complex(4, 4)
};
double delta = Math.Pow(2, 70);
encoder.Encode(input, context.FirstParmsId, delta, plain);
encryptor.Encrypt(plain, encrypted);
Assert.AreEqual(delta, encrypted.Scale, delta: Math.Pow(2, 60));
Ciphertext encrypted2 = new Ciphertext();
encrypted2.Set(encrypted);
Assert.AreEqual(delta, encrypted2.Scale, delta: Math.Pow(2, 60));
evaluator.RescaleToNextInplace(encrypted);
Assert.AreEqual(Math.Pow(2, 30), encrypted.Scale, delta: 10000);
Assert.AreNotEqual(0ul, cipherPool.AllocByteCount);
double newScale = Math.Pow(2, 10);
encrypted.Scale = newScale;
Assert.AreEqual(newScale, encrypted.Scale, delta: 100);
}
[TestMethod]
public void ExceptionsTest()
{
SEALContext context = GlobalContext.BFVContext;
MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal);
MemoryPoolHandle poolu = new MemoryPoolHandle();
Ciphertext cipher = new Ciphertext();
Ciphertext copy = null;
Utilities.AssertThrows<ArgumentNullException>(() => copy = new Ciphertext((Ciphertext)null));
Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(context, null, pool));
Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(null, context.FirstParmsId, pool));
Utilities.AssertThrows<ArgumentException>(() => cipher = new Ciphertext(context, ParmsId.Zero, pool));
Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext((SEALContext)null, poolu));
Utilities.AssertThrows<ArgumentException>(() => cipher = new Ciphertext(context, poolu));
Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(context, null, 6ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher = new Ciphertext(null, context.FirstParmsId, 6ul, poolu));
Utilities.AssertThrows<ArgumentException>(() => cipher = new Ciphertext(context, ParmsId.Zero, 6ul, poolu));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Reserve(context, null, 10ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Reserve(null, ParmsId.Zero, 10ul));
Utilities.AssertThrows<ArgumentException>(() => cipher.Reserve(context, ParmsId.Zero, 10ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Reserve(null, 10ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Resize(context, null, 10ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Resize(null, ParmsId.Zero, 10ul));
Utilities.AssertThrows<ArgumentException>(() => cipher.Resize(context, ParmsId.Zero, 10ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Resize(null, 10ul));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Set(null));
Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(cipher, null));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Save(null));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.UnsafeLoad(context, null));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.UnsafeLoad(null, new MemoryStream()));
Utilities.AssertThrows<EndOfStreamException>(() => cipher.UnsafeLoad(context, new MemoryStream()));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Load(null, new MemoryStream()));
Utilities.AssertThrows<ArgumentNullException>(() => cipher.Load(context, null));
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace SEALNetTest
{
[TestClass]
public class DecryptorTests
{
SEALContext context_;
KeyGenerator keyGen_;
SecretKey secretKey_;
PublicKey publicKey_;
[TestInitialize]
public void TestInit()
{
context_ = GlobalContext.BFVContext;
keyGen_ = new KeyGenerator(context_);
secretKey_ = keyGen_.SecretKey;
publicKey_ = keyGen_.PublicKey;
}
[TestMethod]
public void CreateTest()
{
Decryptor decryptor = new Decryptor(context_, secretKey_);
Assert.IsNotNull(decryptor);
}
[TestMethod]
public void DecryptTest()
{
Encryptor encryptor = new Encryptor(context_, publicKey_);
Decryptor decryptor = new Decryptor(context_, secretKey_);
Plaintext plain = new Plaintext("1x^1 + 2");
Ciphertext cipher = new Ciphertext();
Assert.AreEqual(0ul, cipher.Size);
encryptor.Encrypt(plain, cipher);
Assert.AreEqual(2ul, cipher.Size);
Plaintext decrypted = new Plaintext();
Assert.AreEqual(0ul, decrypted.CoeffCount);
decryptor.Decrypt(cipher, decrypted);
Assert.AreEqual(2ul, decrypted.CoeffCount);
Assert.AreEqual(2ul, decrypted[0]);
Assert.AreEqual(1ul, decrypted[1]);
}
[TestMethod]
public void InvariantNoiseBudgetTest()
{
Encryptor encryptor = new Encryptor(context_, publicKey_);
Decryptor decryptor = new Decryptor(context_, secretKey_);
Plaintext plain = new Plaintext("1");
Ciphertext cipher = new Ciphertext();
encryptor.Encrypt(plain, cipher);
int budget = decryptor.InvariantNoiseBudget(cipher);
Assert.IsTrue(budget > 80);
}
[TestMethod]
public void ExceptionsTest()
{
Decryptor decryptor = new Decryptor(context_, secretKey_);
SecretKey secret = new SecretKey();
Ciphertext cipher = new Ciphertext();
Plaintext plain = new Plaintext();
Utilities.AssertThrows<ArgumentNullException>(() => decryptor = new Decryptor(context_, null));
Utilities.AssertThrows<ArgumentNullException>(() => decryptor = new Decryptor(null, secretKey_));
Utilities.AssertThrows<ArgumentException>(() => decryptor = new Decryptor(context_, secret));
Utilities.AssertThrows<ArgumentNullException>(() => decryptor.Decrypt(cipher, null));
Utilities.AssertThrows<ArgumentNullException>(() => decryptor.Decrypt(null, plain));
Utilities.AssertThrows<ArgumentException>(() => decryptor.Decrypt(cipher, plain));
Utilities.AssertThrows<ArgumentNullException>(() => decryptor.InvariantNoiseBudget(null));
}
}
}
using Microsoft.Research.SEAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
namespace SEALNetTest
{
[TestClass]
public class EncryptionParameterQualifiersTests
{
[TestMethod]
public void PropertiesTest()
{
SEALContext context = GlobalContext.BFVContext;
Assert.IsTrue(context.FirstContextData.Qualifiers.ParametersSet);
Assert.IsTrue(context.FirstContextData.Qualifiers.UsingBatching);
Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFastPlainLift);
Assert.IsTrue(context.FirstContextData.Qualifiers.UsingFFT);
Assert.AreEqual(SecLevelType.TC128, context.FirstContextData.Qualifiers.SecLevel);
Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain);
Assert.IsTrue(context.FirstContextData.Qualifiers.UsingNTT);
Assert.IsTrue(context.UsingKeyswitching);
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 4096,
CoeffModulus = CoeffModulus.BFVDefault(4096)
};
SEALContext context2 = new SEALContext(parms);
Assert.IsTrue(context2.FirstContextData.Qualifiers.ParametersSet);
Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingBatching);
Assert.IsFalse(context2.FirstContextData.Qualifiers.UsingFastPlainLift);
Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingFFT);
Assert.AreEqual(SecLevelType.TC128, context2.FirstContextData.Qualifiers.SecLevel);
Assert.IsFalse(context.FirstContextData.Qualifiers.UsingDescendingModulusChain);
Assert.IsTrue(context2.FirstContextData.Qualifiers.UsingNTT);
Assert.IsTrue(context.UsingKeyswitching);
EncryptionParameterQualifiers qualifiers = new EncryptionParameterQualifiers(context2.FirstContextData.Qualifiers);
Assert.IsNotNull(qualifiers);
Assert.IsTrue(qualifiers.ParametersSet);
Assert.IsTrue(qualifiers.UsingBatching);
Assert.IsFalse(qualifiers.UsingFastPlainLift);
Assert.IsTrue(qualifiers.UsingFFT);
Assert.AreEqual(SecLevelType.TC128, qualifiers.SecLevel);
Assert.IsTrue(qualifiers.UsingDescendingModulusChain);
Assert.IsTrue(qualifiers.UsingNTT);
}
[TestMethod]
public void ParameterErrorTest()
{
SEALContext context = GlobalContext.BFVContext;
EncryptionParameterQualifiers qualifiers = context.FirstContextData.Qualifiers;
Assert.AreEqual(qualifiers.ParametersErrorName(), "success");
Assert.AreEqual(qualifiers.ParametersErrorMessage(), "valid");
EncryptionParameters encParam = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 127,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 })
};
context = new SEALContext(encParam, expandModChain: true, secLevel: SecLevelType.None);
qualifiers = context.FirstContextData.Qualifiers;
Assert.AreEqual(qualifiers.ParametersErrorName(), "invalid_poly_modulus_degree_non_power_of_two");
Assert.AreEqual(qualifiers.ParametersErrorMessage(), "poly_modulus_degree is not a power of two");
}
[TestMethod]
public void ExceptionsTest()
{
EncryptionParameterQualifiers epq1 = GlobalContext.BFVContext.FirstContextData.Qualifiers;
EncryptionParameterQualifiers epq2 = null;
Utilities.AssertThrows<ArgumentNullException>(() => epq2 = new EncryptionParameterQualifiers(null));
}
}
}
// 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.IO;
namespace SEALNetTest
{
public delegate void TestDelegate(SchemeType scheme);
[TestClass]
public class EncryptionParametersTests
{
[TestMethod]
public void CreateTest()
{
EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV);
Assert.IsNotNull(encParams);
Assert.AreEqual(SchemeType.BFV, encParams.Scheme);
EncryptionParameters encParams2 = new EncryptionParameters(SchemeType.CKKS);
Assert.IsNotNull(encParams2);
Assert.AreEqual(SchemeType.CKKS, encParams2.Scheme);
EncryptionParameters encParams3 = new EncryptionParameters(SchemeType.CKKS);
Assert.IsNotNull(encParams3);
Assert.AreEqual(SchemeType.CKKS, encParams3.Scheme);
EncryptionParameters copy = new EncryptionParameters(encParams);
Assert.AreEqual(SchemeType.BFV, copy.Scheme);
Assert.AreEqual(encParams, copy);
Assert.AreEqual(encParams.GetHashCode(), copy.GetHashCode());
EncryptionParameters third = new EncryptionParameters(SchemeType.CKKS);
third.Set(copy);
Assert.AreEqual(SchemeType.BFV, third.Scheme);
Assert.AreEqual(encParams, third);
Assert.AreEqual(encParams.GetHashCode(), third.GetHashCode());
}
[TestMethod]
public void SetPlainModulusCKKSTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
Utilities.AssertThrows<InvalidOperationException>(() =>
{
parms.PlainModulus = new Modulus(8192);
});
Utilities.AssertThrows<InvalidOperationException>(() =>
{
parms.SetPlainModulus(8192);
});
}
[TestMethod]
public void CoeffModulusTest()
{
EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV);
Assert.IsNotNull(encParams);
List<Modulus> coeffs = new List<Modulus>(encParams.CoeffModulus);
Assert.IsNotNull(coeffs);
Assert.AreEqual(0, coeffs.Count);
encParams.CoeffModulus = CoeffModulus.BFVDefault(4096);
List<Modulus> newCoeffs = new List<Modulus>(encParams.CoeffModulus);
Assert.IsNotNull(newCoeffs);
Assert.AreEqual(3, newCoeffs.Count);
Assert.AreEqual(0xffffee001ul, newCoeffs[0].Value);
Assert.AreEqual(0xffffc4001ul, newCoeffs[1].Value);
Assert.AreEqual(0x1ffffe0001ul, newCoeffs[2].Value);
}
[TestMethod]
public void SaveLoadTest()
{
TestDelegate save_load_test = delegate(SchemeType scheme)
{
List<Modulus> coeffModulus = (List<Modulus>)CoeffModulus.Create(8, new int[] { 40, 40 });
EncryptionParameters parms = new EncryptionParameters(scheme)
{
PolyModulusDegree = 8,
CoeffModulus = coeffModulus
};
if (scheme == SchemeType.BFV)
parms.SetPlainModulus(257);
EncryptionParameters loaded = new EncryptionParameters();
using (MemoryStream stream = new MemoryStream())
{
parms.Save(stream);
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
loaded.Load(stream);
}
Assert.AreEqual(scheme, loaded.Scheme);
Assert.AreEqual(8ul, loaded.PolyModulusDegree);
if (scheme == SchemeType.BFV)
Assert.AreEqual(257ul, loaded.PlainModulus.Value);
else if (scheme == SchemeType.CKKS)
Assert.AreEqual(0ul, loaded.PlainModulus.Value);
List<Modulus> loadedCoeffModulus = new List<Modulus>(loaded.CoeffModulus);
Assert.AreEqual(2, loadedCoeffModulus.Count);
Assert.AreNotSame(coeffModulus[0], loadedCoeffModulus[0]);
Assert.AreNotSame(coeffModulus[1], loadedCoeffModulus[1]);
Assert.AreEqual(coeffModulus[0], loadedCoeffModulus[0]);
Assert.AreEqual(coeffModulus[1], loadedCoeffModulus[1]);
};
save_load_test(SchemeType.BFV);
save_load_test(SchemeType.CKKS);
}
[TestMethod]
public void EqualsTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 8,
PlainModulus = new Modulus(257),
CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 })
};
EncryptionParameters parms2 = new EncryptionParameters(SchemeType.CKKS);
Assert.AreNotEqual(parms, parms2);
Assert.IsFalse(parms.Equals(null));
}
[TestMethod]
public void ExceptionsTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
Utilities.AssertThrows<ArgumentNullException>(() => parms = new EncryptionParameters(null));
Utilities.AssertThrows<ArgumentNullException>(() => parms.Set(null));
Utilities.AssertThrows<ArgumentNullException>(() => parms.CoeffModulus = null);
Utilities.AssertThrows<ArgumentNullException>(() => parms.Save(null));
Utilities.AssertThrows<ArgumentNullException>(() => parms.Load(null));
Utilities.AssertThrows<EndOfStreamException>(() => parms.Load(new MemoryStream()));
}
}
}
// 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.IO;
using System.Numerics;
namespace SEALNetTest
{
[TestClass]
public class EncryptorTests
{
[TestMethod]
public void EncryptTest()
{
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keyGen = new KeyGenerator(context);
PublicKey publicKey = keyGen.PublicKey;
SecretKey secretKey = keyGen.SecretKey;
Encryptor encryptor = new Encryptor(context, publicKey, secretKey);
Assert.IsNotNull(encryptor);
Plaintext plain = new Plaintext("1x^1 + 1");
Ciphertext cipher = new Ciphertext();
Assert.AreEqual(0ul, cipher.Size);
encryptor.Encrypt(plain, cipher);
Assert.IsNotNull(cipher);
Assert.AreEqual(2ul, cipher.Size);
}
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keyGen = new KeyGenerator(context);
SecretKey secretKey = keyGen.SecretKey;
Encryptor encryptor = new Encryptor(context, secretKey);
Assert.IsNotNull(encryptor);
Plaintext plain = new Plaintext("1x^1 + 1");
Ciphertext cipher = new Ciphertext();
Assert.AreEqual(0ul, cipher.Size);
encryptor.EncryptSymmetric(plain, cipher);
Assert.IsNotNull(cipher);
Assert.AreEqual(2ul, cipher.Size);
}
}
[TestMethod]
public void EncryptZeroTest()
{
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keyGen = new KeyGenerator(context);
PublicKey publicKey = keyGen.PublicKey;
SecretKey secretKey = keyGen.SecretKey;
Decryptor decryptor = new Decryptor(context, secretKey);
Assert.IsNotNull(decryptor);
Ciphertext cipher = new Ciphertext();
Plaintext plain = new Plaintext();
ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId;
{
Encryptor encryptor = new Encryptor(context, publicKey);
Assert.IsNotNull(encryptor);
encryptor.EncryptZero(cipher);
Assert.IsFalse(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
decryptor.Decrypt(cipher, plain);
Assert.IsTrue(plain.IsZero);
encryptor.EncryptZero(nextParms, cipher);
Assert.IsFalse(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
Assert.AreEqual(cipher.ParmsId, nextParms);
decryptor.Decrypt(cipher, plain);
Assert.IsTrue(plain.IsZero);
}
{
Encryptor encryptor = new Encryptor(context, secretKey);
encryptor.EncryptZeroSymmetric(cipher);
Assert.IsFalse(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
decryptor.Decrypt(cipher, plain);
Assert.IsTrue(plain.IsZero);
encryptor.EncryptZeroSymmetric(nextParms, cipher);
Assert.IsFalse(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
Assert.AreEqual(cipher.ParmsId, nextParms);
decryptor.Decrypt(cipher, plain);
Assert.IsTrue(plain.IsZero);
}
using (MemoryStream stream = new MemoryStream())
{
Encryptor encryptor = new Encryptor(context, secretKey);
encryptor.EncryptZeroSymmetric().Save(stream);
stream.Seek(0, SeekOrigin.Begin);
cipher.Load(context, stream);
Assert.IsFalse(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
decryptor.Decrypt(cipher, plain);
Assert.IsTrue(plain.IsZero);
}
using (MemoryStream stream = new MemoryStream())
{
Encryptor encryptor = new Encryptor(context, secretKey);
encryptor.EncryptZeroSymmetric(nextParms).Save(stream);
stream.Seek(0, SeekOrigin.Begin);
cipher.Load(context, stream);
Assert.IsFalse(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
Assert.AreEqual(cipher.ParmsId, nextParms);
decryptor.Decrypt(cipher, plain);
Assert.IsTrue(plain.IsZero);
}
}
{
SEALContext context = GlobalContext.CKKSContext;
KeyGenerator keyGen = new KeyGenerator(context);
PublicKey publicKey = keyGen.PublicKey;
SecretKey secretKey = keyGen.SecretKey;
Decryptor decryptor = new Decryptor(context, secretKey);
CKKSEncoder encoder = new CKKSEncoder(context);
Assert.IsNotNull(decryptor);
Ciphertext cipher = new Ciphertext();
Plaintext plain = new Plaintext();
ParmsId nextParms = context.FirstContextData.NextContextData.ParmsId;
List<Complex> res = new List<Complex>();
{
Encryptor encryptor = new Encryptor(context, publicKey);
Assert.IsNotNull(encryptor);
encryptor.EncryptZero(cipher);
Assert.IsTrue(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
cipher.Scale = Math.Pow(2.0, 30);
decryptor.Decrypt(cipher, plain);
encoder.Decode(plain, res);
foreach (Complex val in res)
{
Assert.AreEqual(val.Real, 0.0, 0.01);
Assert.AreEqual(val.Imaginary, 0.0, 0.01);
}
encryptor.EncryptZero(nextParms, cipher);
Assert.IsTrue(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
cipher.Scale = Math.Pow(2.0, 30);
Assert.AreEqual(cipher.ParmsId, nextParms);
decryptor.Decrypt(cipher, plain);
Assert.AreEqual(plain.ParmsId, nextParms);
encoder.Decode(plain, res);
foreach (Complex val in res)
{
Assert.AreEqual(val.Real, 0.0, 0.01);
Assert.AreEqual(val.Imaginary, 0.0, 0.01);
}
}
{
Encryptor encryptor = new Encryptor(context, secretKey);
encryptor.EncryptZeroSymmetric(cipher);
Assert.IsTrue(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
cipher.Scale = Math.Pow(2.0, 30);
decryptor.Decrypt(cipher, plain);
encoder.Decode(plain, res);
foreach (Complex val in res)
{
Assert.AreEqual(val.Real, 0.0, 0.01);
Assert.AreEqual(val.Imaginary, 0.0, 0.01);
}
encryptor.EncryptZeroSymmetric(nextParms, cipher);
Assert.IsTrue(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
cipher.Scale = Math.Pow(2.0, 30);
Assert.AreEqual(cipher.ParmsId, nextParms);
decryptor.Decrypt(cipher, plain);
Assert.AreEqual(plain.ParmsId, nextParms);
encoder.Decode(plain, res);
foreach (Complex val in res)
{
Assert.AreEqual(val.Real, 0.0, 0.01);
Assert.AreEqual(val.Imaginary, 0.0, 0.01);
}
}
using (MemoryStream stream = new MemoryStream())
{
Encryptor encryptor = new Encryptor(context, secretKey);
encryptor.EncryptZeroSymmetric().Save(stream);
stream.Seek(0, SeekOrigin.Begin);
cipher.Load(context, stream);
Assert.IsTrue(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
cipher.Scale = Math.Pow(2.0, 30);
decryptor.Decrypt(cipher, plain);
encoder.Decode(plain, res);
foreach (Complex val in res)
{
Assert.AreEqual(val.Real, 0.0, 0.01);
Assert.AreEqual(val.Imaginary, 0.0, 0.01);
}
}
using (MemoryStream stream = new MemoryStream())
{
Encryptor encryptor = new Encryptor(context, secretKey);
encryptor.EncryptZeroSymmetric(nextParms).Save(stream);
stream.Seek(0, SeekOrigin.Begin);
cipher.Load(context, stream);
Assert.IsTrue(cipher.IsNTTForm);
Assert.IsFalse(cipher.IsTransparent);
Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
cipher.Scale = Math.Pow(2.0, 30);
Assert.AreEqual(cipher.ParmsId, nextParms);
decryptor.Decrypt(cipher, plain);
Assert.AreEqual(plain.ParmsId, nextParms);
encoder.Decode(plain, res);
foreach (Complex val in res)
{
Assert.AreEqual(val.Real, 0.0, 0.01);
Assert.AreEqual(val.Imaginary, 0.0, 0.01);
}
}
}
}
[TestMethod]
public void ExceptionsTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
PublicKey pubKey = keygen.PublicKey;
PublicKey pubKey_invalid = new PublicKey();
SecretKey secKey = keygen.SecretKey;
SecretKey secKey_invalid = new SecretKey();
Encryptor encryptor = new Encryptor(context, pubKey);
Plaintext plain = new Plaintext();
Ciphertext cipher = new Ciphertext();
MemoryPoolHandle pool_invalid = new MemoryPoolHandle();
ParmsId parmsId_invalid = new ParmsId();
Utilities.AssertThrows<ArgumentNullException>(() => encryptor = new Encryptor(context, null));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor = new Encryptor(null, pubKey));
Utilities.AssertThrows<ArgumentException>(() => encryptor = new Encryptor(context, pubKey_invalid));
Utilities.AssertThrows<ArgumentException>(() => encryptor = new Encryptor(context, pubKey_invalid, secKey));
encryptor = new Encryptor(context, pubKey, secKey);
Utilities.AssertThrows<ArgumentException>(() => encryptor.SetPublicKey(pubKey_invalid));
Utilities.AssertThrows<ArgumentException>(() => encryptor.SetSecretKey(secKey_invalid));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor.Encrypt(plain, null));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor.Encrypt(null, cipher));
Utilities.AssertThrows<ArgumentException>(() => encryptor.Encrypt(plain, cipher, pool_invalid));
Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZero(cipher, pool_invalid));
Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZero(parmsId_invalid, cipher));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptSymmetric(plain, destination: null));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptSymmetric(null, cipher));
Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptSymmetric(plain, cipher, pool_invalid));
Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZeroSymmetric(cipher, pool_invalid));
Utilities.AssertThrows<ArgumentException>(() => encryptor.EncryptZeroSymmetric(parmsId_invalid, cipher));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptSymmetric(plain).Save(null));
Utilities.AssertThrows<ArgumentNullException>(() => encryptor.EncryptZeroSymmetric().Save(null));
}
}
}
// 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.Linq;
using System.Numerics;
namespace SEALNetTest
{
[TestClass]
public class EvaluatorTests
{
[TestMethod]
public void CreateTest()
{
Evaluator evaluator = new Evaluator(GlobalContext.BFVContext);
Assert.IsNotNull(evaluator);
}
[TestMethod]
public void NegateTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Assert.IsTrue(context.ParametersSet);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdestination = new Ciphertext();
Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(plain, encrypted);
evaluator.Negate(encrypted, encdestination);
decryptor.Decrypt(encdestination, plaindest);
// coefficients are negated (modulo 64)
Assert.AreEqual(0x3Ful, plaindest[0]);
Assert.AreEqual(0x3Eul, plaindest[1]);
Assert.AreEqual(0x3Dul, plaindest[2]);
plain = new Plaintext("6x^3 + 7x^2 + 8x^1 + 9");
encryptor.Encrypt(plain, encrypted);
evaluator.NegateInplace(encrypted);
decryptor.Decrypt(encrypted, plain);
// coefficients are negated (modulo 64)
Assert.AreEqual(0x37ul, plain[0]);
Assert.AreEqual(0x38ul, plain[1]);
Assert.AreEqual(0x39ul, plain[2]);
Assert.AreEqual(0x3Aul, plain[3]);
}
[TestMethod]
public void AddTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted1 = new Ciphertext();
Ciphertext encrypted2 = new Ciphertext();
Ciphertext encdestination = new Ciphertext();
Plaintext plain1 = new Plaintext("5x^4 + 4x^3 + 3x^2 + 2x^1 + 1");
Plaintext plain2 = new Plaintext("4x^7 + 5x^6 + 6x^5 + 7x^4 + 8x^3 + 9x^2 + Ax^1 + B");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(plain1, encrypted1);
encryptor.Encrypt(plain2, encrypted2);
evaluator.Add(encrypted1, encrypted2, encdestination);
decryptor.Decrypt(encdestination, plaindest);
Assert.AreEqual(12ul, plaindest[0]);
Assert.AreEqual(12ul, plaindest[1]);
Assert.AreEqual(12ul, plaindest[2]);
Assert.AreEqual(12ul, plaindest[3]);
Assert.AreEqual(12ul, plaindest[4]);
Assert.AreEqual(6ul, plaindest[5]);
Assert.AreEqual(5ul, plaindest[6]);
Assert.AreEqual(4ul, plaindest[7]);
plain1 = new Plaintext("1x^2 + 2x^1 + 3");
plain2 = new Plaintext("2x^3 + 2x^2 + 2x^1 + 2");
encryptor.Encrypt(plain1, encrypted1);
encryptor.Encrypt(plain2, encrypted2);
evaluator.AddInplace(encrypted1, encrypted2);
decryptor.Decrypt(encrypted1, plaindest);
Assert.AreEqual(5ul, plaindest[0]);
Assert.AreEqual(4ul, plaindest[1]);
Assert.AreEqual(3ul, plaindest[2]);
Assert.AreEqual(2ul, plaindest[3]);
}
[TestMethod]
public void AddPlainTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(new Plaintext("2x^2 + 2x^1 + 2"), encrypted);
evaluator.AddPlain(encrypted, plain, encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.AreEqual(3ul, plaindest[0]);
Assert.AreEqual(4ul, plaindest[1]);
Assert.AreEqual(5ul, plaindest[2]);
plain.Set("1x^2 + 1x^1 + 1");
encryptor.Encrypt(new Plaintext("2x^3 + 2x^2 + 2x^1 + 2"), encrypted);
evaluator.AddPlainInplace(encrypted, plain);
decryptor.Decrypt(encrypted, plaindest);
Assert.AreEqual(4ul, plaindest.CoeffCount);
Assert.AreEqual(3ul, plaindest[0]);
Assert.AreEqual(3ul, plaindest[1]);
Assert.AreEqual(3ul, plaindest[2]);
Assert.AreEqual(2ul, plaindest[3]);
}
[TestMethod]
public void AddManyTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext[] encrypteds = new Ciphertext[6];
for(int i = 0; i < encrypteds.Length; i++)
{
encrypteds[i] = new Ciphertext();
encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]);
}
Ciphertext encdest = new Ciphertext();
Plaintext plaindest = new Plaintext();
evaluator.AddMany(encrypteds, encdest);
decryptor.Decrypt(encdest, plaindest);
// 1+2+3+4+5+6
Assert.AreEqual(21ul, plaindest[0]);
}
[TestMethod]
public void SubTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted1 = new Ciphertext();
Ciphertext encrypted2 = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plain1 = new Plaintext("Ax^2 + Bx^1 + C");
Plaintext plain2 = new Plaintext("5x^3 + 5x^2 + 5x^1 + 5");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(plain1, encrypted1);
encryptor.Encrypt(plain2, encrypted2);
evaluator.Sub(encrypted1, encrypted2, encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.AreEqual(7ul, plaindest[0]);
Assert.AreEqual(6ul, plaindest[1]);
Assert.AreEqual(5ul, plaindest[2]);
Assert.AreEqual(0x3Bul, plaindest[3]);
plain1.Set("Ax^3 + Bx^2 + Cx^1 + D");
plain2.Set("5x^2 + 5x^1 + 5");
encryptor.Encrypt(plain1, encrypted1);
encryptor.Encrypt(plain2, encrypted2);
evaluator.SubInplace(encrypted1, encrypted2);
decryptor.Decrypt(encrypted1, plaindest);
Assert.AreEqual(8ul, plaindest[0]);
Assert.AreEqual(7ul, plaindest[1]);
Assert.AreEqual(6ul, plaindest[2]);
Assert.AreEqual(10ul, plaindest[3]);
}
[TestMethod]
public void SubPlainTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plain = new Plaintext("5x^2 + 4x^1 + 3");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(new Plaintext("3x^1 + 4"), encrypted);
evaluator.SubPlain(encrypted, plain, encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.AreEqual(3ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
Assert.AreEqual(0x3Ful, plaindest[1]); // -1
Assert.AreEqual(0x3Bul, plaindest[2]); // -5
plain.Set("6x^3 + 1x^2 + 7x^1 + 2");
encryptor.Encrypt(new Plaintext("Ax^2 + Bx^1 + C"), encrypted);
evaluator.SubPlainInplace(encrypted, plain);
decryptor.Decrypt(encrypted, plaindest);
Assert.AreEqual(4ul, plaindest.CoeffCount);
Assert.AreEqual(10ul, plaindest[0]);
Assert.AreEqual(4ul, plaindest[1]);
Assert.AreEqual(9ul, plaindest[2]);
Assert.AreEqual(0x3Aul, plaindest[3]); // -6
}
[TestMethod]
public void MultiplyTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted1 = new Ciphertext();
Ciphertext encrypted2 = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(new Plaintext("1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"), encrypted1);
encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted2);
evaluator.Multiply(encrypted1, encrypted2, encdest);
decryptor.Decrypt(encdest, plaindest);
// {3x^6 + 8x^5 + Ex^4 + 14x^3 + 1Ax^2 + Ex^1 + 5}
Assert.AreEqual(7ul, plaindest.CoeffCount);
Assert.AreEqual(5ul, plaindest[0]);
Assert.AreEqual(14ul, plaindest[1]);
Assert.AreEqual(26ul, plaindest[2]);
Assert.AreEqual(20ul, plaindest[3]);
Assert.AreEqual(14ul, plaindest[4]);
Assert.AreEqual(8ul, plaindest[5]);
Assert.AreEqual(3ul, plaindest[6]);
encryptor.Encrypt(new Plaintext("2x^2 + 3x^1 + 4"), encrypted1);
encryptor.Encrypt(new Plaintext("4x^1 + 5"), encrypted2);
evaluator.MultiplyInplace(encrypted1, encrypted2);
decryptor.Decrypt(encrypted1, plaindest);
// {8x^3 + 16x^2 + 1Fx^1 + 14}
Assert.AreEqual(4ul, plaindest.CoeffCount);
Assert.AreEqual(20ul, plaindest[0]);
Assert.AreEqual(31ul, plaindest[1]);
Assert.AreEqual(22ul, plaindest[2]);
Assert.AreEqual(8ul, plaindest[3]);
}
[TestMethod]
public void MultiplyManyTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
RelinKeys relinKeys = keygen.RelinKeysLocal();
Ciphertext[] encrypteds = new Ciphertext[4];
Ciphertext encdest = new Ciphertext();
Plaintext plaindest = new Plaintext();
for (int i = 0; i < encrypteds.Length; i++)
{
encrypteds[i] = new Ciphertext();
encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]);
}
evaluator.MultiplyMany(encrypteds, relinKeys, encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.AreEqual(1ul, plaindest.CoeffCount);
Assert.AreEqual(24ul, plaindest[0]);
Utilities.AssertThrows<ArgumentException>(() =>
{
// Uninitialized memory pool handle
MemoryPoolHandle pool = new MemoryPoolHandle();
evaluator.MultiplyMany(encrypteds, relinKeys, encdest, pool);
});
}
[TestMethod]
public void MultiplyPlainTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
RelinKeys relinKeys = keygen.RelinKeysLocal();
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plain = new Plaintext("2x^2 + 1");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(new Plaintext("3x^2 + 2"), encrypted);
evaluator.MultiplyPlain(encrypted, plain, encdest);
decryptor.Decrypt(encdest, plaindest);
// {6x^4 + 7x^2 + 2}
Assert.AreEqual(5ul, plaindest.CoeffCount);
Assert.AreEqual(2ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(7ul, plaindest[2]);
Assert.AreEqual(0ul, plaindest[3]);
Assert.AreEqual(6ul, plaindest[4]);
encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted);
plain.Set("2x^2 + 1");
evaluator.MultiplyPlainInplace(encrypted, plain);
decryptor.Decrypt(encrypted, plaindest);
// {8x^3 + 6x^2 + 4x^1 + 3}
Assert.AreEqual(4ul, plaindest.CoeffCount);
Assert.AreEqual(3ul, plaindest[0]);
Assert.AreEqual(4ul, plaindest[1]);
Assert.AreEqual(6ul, plaindest[2]);
Assert.AreEqual(8ul, plaindest[3]);
encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted);
plain.Set("3x^5");
evaluator.MultiplyPlainInplace(encrypted, plain);
decryptor.Decrypt(encrypted, plaindest);
// {Cx^6 + 9x^5}
Assert.AreEqual(7ul, plaindest.CoeffCount);
Assert.AreEqual(2ul, plaindest.NonZeroCoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(0ul, plaindest[2]);
Assert.AreEqual(0ul, plaindest[3]);
Assert.AreEqual(0ul, plaindest[4]);
Assert.AreEqual(9ul, plaindest[5]);
Assert.AreEqual(12ul, plaindest[6]);
Utilities.AssertThrows<ArgumentException>(() =>
{
// Uninitialized pool
MemoryPoolHandle pool = new MemoryPoolHandle();
evaluator.MultiplyPlain(encrypted, plain, encdest, pool);
});
}
[TestMethod]
public void SquareTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plain = new Plaintext("2x^2 + 3x^1 + 4");
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(plain, encrypted);
evaluator.Square(encrypted, encdest);
decryptor.Decrypt(encdest, plaindest);
// {4x^4 + Cx^3 + 19x^2 + 18x^1 + 10}
Assert.AreEqual(5ul, plaindest.CoeffCount);
Assert.AreEqual(16ul, plaindest[0]);
Assert.AreEqual(24ul, plaindest[1]);
Assert.AreEqual(25ul, plaindest[2]);
Assert.AreEqual(12ul, plaindest[3]);
Assert.AreEqual(4ul, plaindest[4]);
encryptor.Encrypt(new Plaintext("3x^1 + 2"), encrypted);
evaluator.SquareInplace(encrypted);
decryptor.Decrypt(encrypted, plaindest);
// {9x^2 + Cx^1 + 4}
Assert.AreEqual(3ul, plaindest.CoeffCount);
Assert.AreEqual(4ul, plaindest[0]);
Assert.AreEqual(12ul, plaindest[1]);
Assert.AreEqual(9ul, plaindest[2]);
}
[TestMethod]
public void ExponentiateTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
RelinKeys relinKeys = keygen.RelinKeysLocal();
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plain = new Plaintext();
encryptor.Encrypt(new Plaintext("2x^2 + 1"), encrypted);
evaluator.Exponentiate(encrypted, 3, relinKeys, encdest);
decryptor.Decrypt(encdest, plain);
// {8x^6 + Cx^4 + 6x^2 + 1}
Assert.AreEqual(7ul, plain.CoeffCount);
Assert.AreEqual(1ul, plain[0]);
Assert.AreEqual(0ul, plain[1]);
Assert.AreEqual(6ul, plain[2]);
Assert.AreEqual(0ul, plain[3]);
Assert.AreEqual(12ul, plain[4]);
Assert.AreEqual(0ul, plain[5]);
Assert.AreEqual(8ul, plain[6]);
encryptor.Encrypt(new Plaintext("3x^3 + 2"), encrypted);
evaluator.ExponentiateInplace(encrypted, 4, relinKeys);
decryptor.Decrypt(encrypted, plain);
// {11x^12 + 18x^9 + 18x^6 + 20x^3 + 10}
Assert.AreEqual(13ul, plain.CoeffCount);
Assert.AreEqual(16ul, plain[0]);
Assert.AreEqual(0ul, plain[1]);
Assert.AreEqual(0ul, plain[2]);
Assert.AreEqual(32ul, plain[3]);
Assert.AreEqual(0ul, plain[4]);
Assert.AreEqual(0ul, plain[5]);
Assert.AreEqual(24ul, plain[6]);
Assert.AreEqual(0ul, plain[7]);
Assert.AreEqual(0ul, plain[8]);
Assert.AreEqual(24ul, plain[9]);
Assert.AreEqual(0ul, plain[10]);
Assert.AreEqual(0ul, plain[11]);
Assert.AreEqual(17ul, plain[12]);
}
[TestMethod]
public void ApplyGaloisTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 8,
PlainModulus = new Modulus(257),
CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys galoisKeys = keygen.GaloisKeysLocal(galoisElts: new uint[] { 1u, 3u, 5u, 15u });
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Plaintext plain = new Plaintext("1");
Plaintext plaindest = new Plaintext();
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
encryptor.Encrypt(plain, encrypted);
evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.AreEqual(1ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
plain.Set("1x^1");
encryptor.Encrypt(plain, encrypted);
evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest);
decryptor.Decrypt(encdest, plaindest);
// {1x^1}
Assert.AreEqual(2ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(1ul, plaindest[1]);
evaluator.ApplyGalois(encdest, galoisElt: 3, galoisKeys: galoisKeys, destination: encrypted);
decryptor.Decrypt(encrypted, plaindest);
// {1x^3}
Assert.AreEqual(4ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(0ul, plaindest[2]);
Assert.AreEqual(1ul, plaindest[3]);
evaluator.ApplyGalois(encrypted, galoisElt: 5, galoisKeys: galoisKeys, destination: encdest);
decryptor.Decrypt(encdest, plaindest);
// {100x^7}
Assert.AreEqual(8ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(0ul, plaindest[2]);
Assert.AreEqual(0ul, plaindest[3]);
Assert.AreEqual(0ul, plaindest[4]);
Assert.AreEqual(0ul, plaindest[5]);
Assert.AreEqual(0ul, plaindest[6]);
Assert.AreEqual(256ul, plaindest[7]);
plain.Set("1x^2");
encryptor.Encrypt(plain, encrypted);
evaluator.ApplyGaloisInplace(encrypted, 1, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
// {1x^2}
Assert.AreEqual(3ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(1ul, plaindest[2]);
evaluator.ApplyGaloisInplace(encrypted, 3, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
// {1x^6}
Assert.AreEqual(7ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(0ul, plaindest[2]);
Assert.AreEqual(0ul, plaindest[3]);
Assert.AreEqual(0ul, plaindest[4]);
Assert.AreEqual(0ul, plaindest[5]);
Assert.AreEqual(1ul, plaindest[6]);
evaluator.ApplyGaloisInplace(encrypted, 5, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
// {100x^6}
Assert.AreEqual(7ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(0ul, plaindest[1]);
Assert.AreEqual(0ul, plaindest[2]);
Assert.AreEqual(0ul, plaindest[3]);
Assert.AreEqual(0ul, plaindest[4]);
Assert.AreEqual(0ul, plaindest[5]);
Assert.AreEqual(256ul, plaindest[6]);
}
[TestMethod]
public void TransformPlainToNTTTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
Evaluator evaluator = new Evaluator(context);
Plaintext plain = new Plaintext("0");
Plaintext plaindest = new Plaintext();
Assert.IsFalse(plain.IsNTTForm);
evaluator.TransformToNTT(plain, context.FirstParmsId, plaindest);
Assert.IsTrue(plaindest.IsZero);
Assert.IsTrue(plaindest.IsNTTForm);
Assert.IsTrue(plaindest.ParmsId == context.FirstParmsId);
plain = new Plaintext("1");
Assert.IsFalse(plain.IsNTTForm);
evaluator.TransformToNTTInplace(plain, context.FirstParmsId);
Assert.IsTrue(plain.IsNTTForm);
for (ulong i = 0; i < 256; i++)
{
Assert.AreEqual(1ul, plain[i]);
}
}
[TestMethod]
public void TransformEncryptedToNTTTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Ciphertext encdest2 = new Ciphertext();
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(new Plaintext("0"), encrypted);
Assert.IsFalse(encrypted.IsNTTForm);
evaluator.TransformToNTT(encrypted, encdest);
Assert.IsTrue(encdest.IsNTTForm);
evaluator.TransformFromNTT(encdest, encdest2);
Assert.IsFalse(encdest2.IsNTTForm);
decryptor.Decrypt(encdest2, plaindest);
Assert.AreEqual(1ul, plaindest.CoeffCount);
Assert.AreEqual(0ul, plaindest[0]);
Assert.AreEqual(context.FirstParmsId, encdest2.ParmsId);
encryptor.Encrypt(new Plaintext("1"), encrypted);
Assert.IsFalse(encrypted.IsNTTForm);
evaluator.TransformToNTTInplace(encrypted);
Assert.IsTrue(encrypted.IsNTTForm);
evaluator.TransformFromNTTInplace(encrypted);
Assert.IsFalse(encrypted.IsNTTForm);
decryptor.Decrypt(encrypted, plaindest);
Assert.AreEqual(1ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
Assert.AreEqual(context.FirstParmsId, encrypted.ParmsId);
}
[TestMethod]
public void ModSwitchToNextTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 })
};
SEALContext context = new SEALContext(parms,
expandModChain: true,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext(context);
Ciphertext encdest = new Ciphertext();
Plaintext plain = new Plaintext();
plain.Set("0");
encryptor.Encrypt(plain, encrypted);
evaluator.ModSwitchToNext(encrypted, encdest);
decryptor.Decrypt(encdest, plain);
Assert.AreEqual(1ul, plain.CoeffCount);
Assert.AreEqual(0ul, plain[0]);
plain.Set("1");
encryptor.Encrypt(plain, encrypted);
evaluator.ModSwitchToNextInplace(encrypted);
decryptor.Decrypt(encrypted, plain);
Assert.AreEqual(1ul, plain.CoeffCount);
Assert.AreEqual(1ul, plain[0]);
}
[TestMethod]
public void ModSwitchToTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30, 30 })
};
SEALContext context = new SEALContext(parms,
expandModChain: true,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted = new Ciphertext(context);
Ciphertext encdest = new Ciphertext(context);
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(new Plaintext("1"), encrypted);
ParmsId destParmsId = context.FirstContextData.NextContextData
.NextContextData.ParmsId;
evaluator.ModSwitchTo(encrypted, context.FirstParmsId, encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId);
Assert.IsTrue(encdest.ParmsId == context.FirstParmsId);
Assert.AreEqual(1ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
evaluator.ModSwitchTo(encrypted, destParmsId, encdest);
decryptor.Decrypt(encdest, plaindest);
Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId);
Assert.IsTrue(encdest.ParmsId == destParmsId);
Assert.AreEqual(1ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted);
evaluator.ModSwitchToInplace(encrypted, context.FirstParmsId);
decryptor.Decrypt(encrypted, plaindest);
Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId);
Assert.AreEqual(3ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
Assert.AreEqual(2ul, plaindest[1]);
Assert.AreEqual(3ul, plaindest[2]);
evaluator.ModSwitchToInplace(encrypted, destParmsId);
decryptor.Decrypt(encrypted, plaindest);
Assert.IsTrue(encrypted.ParmsId == destParmsId);
Assert.AreEqual(3ul, plaindest.CoeffCount);
Assert.AreEqual(1ul, plaindest[0]);
Assert.AreEqual(2ul, plaindest[1]);
Assert.AreEqual(3ul, plaindest[2]);
}
[TestMethod]
public void ModSwitchToPlainTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 1024,
CoeffModulus = CoeffModulus.Create(1024, new int[] { 40, 40, 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: true,
secLevel: SecLevelType.None);
CKKSEncoder encoder = new CKKSEncoder(context);
KeyGenerator keygen = new KeyGenerator(context);
SecretKey secretKey = keygen.SecretKey;
PublicKey publicKey = keygen.PublicKey;
RelinKeys relinKeys = keygen.RelinKeysLocal();
Encryptor encryptor = new Encryptor(context, publicKey);
Evaluator evaluator = new Evaluator(context);
Decryptor decryptor = new Decryptor(context, secretKey);
double scale = parms.CoeffModulus.Last().Value;
Plaintext coeff1 = new Plaintext();
Plaintext coeff2 = new Plaintext();
Plaintext coeff3 = new Plaintext();
encoder.Encode(2.0, scale, coeff1);
encoder.Encode(3.0, scale, coeff2);
encoder.Encode(1.0, scale, coeff3);
Ciphertext encX1 = new Ciphertext();
Ciphertext encX2 = new Ciphertext();
Ciphertext encX3 = new Ciphertext();
encryptor.Encrypt(coeff1, encX1);
evaluator.Square(encX1, encX3);
evaluator.MultiplyPlain(encX1, coeff2, encX2);
evaluator.RelinearizeInplace(encX3, relinKeys);
evaluator.RescaleToNextInplace(encX3);
evaluator.RelinearizeInplace(encX2, relinKeys);
evaluator.RescaleToInplace(encX2, encX3.ParmsId);
evaluator.ModSwitchToInplace(coeff3, encX3.ParmsId);
evaluator.ModSwitchToNextInplace(coeff2);
evaluator.MultiplyPlainInplace(encX3, coeff3);
Plaintext result = new Plaintext();
decryptor.Decrypt(encX3, result);
Assert.IsNotNull(result);
List<double> destination = new List<double>();
encoder.Decode(result, destination);
Assert.IsNotNull(destination);
foreach(double val in destination)
{
Assert.AreEqual(4.0, val, delta: 0.001);
}
encoder.Decode(coeff2, destination);
foreach(double val in destination)
{
Assert.AreEqual(3.0, val, delta: 0.001);
}
decryptor.Decrypt(encX2, result);
encoder.Decode(result, destination);
foreach (double val in destination)
{
Assert.AreEqual(6.0, val, delta: 0.001);
}
}
[TestMethod]
public void RotateMatrixTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 8,
PlainModulus = new Modulus(257),
CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys galoisKeys = keygen.GaloisKeysLocal();
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
BatchEncoder encoder = new BatchEncoder(context);
Plaintext plain = new Plaintext();
List<ulong> vec = new List<ulong>
{
1, 2, 3, 4,
5, 6, 7, 8
};
encoder.Encode(vec, plain);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(plain, encrypted);
evaluator.RotateColumns(encrypted, galoisKeys, encdest);
decryptor.Decrypt(encdest, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
5, 6, 7, 8,
1, 2, 3, 4
}));
evaluator.RotateRows(encdest, -1, galoisKeys, encrypted);
decryptor.Decrypt(encrypted, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
8, 5, 6, 7,
4, 1, 2, 3
}));
evaluator.RotateRowsInplace(encrypted, 2, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
6, 7, 8, 5,
2, 3, 4, 1
}));
evaluator.RotateColumnsInplace(encrypted, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
2, 3, 4, 1,
6, 7, 8, 5
}));
}
[TestMethod]
public void RelinearizeTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 128,
PlainModulus = new Modulus(1 << 6),
CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
RelinKeys relinKeys = keygen.RelinKeysLocal();
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
Ciphertext encrypted1 = new Ciphertext(context);
Ciphertext encrypted2 = new Ciphertext(context);
Plaintext plain1 = new Plaintext();
Plaintext plain2 = new Plaintext();
plain1.Set(0);
encryptor.Encrypt(plain1, encrypted1);
evaluator.SquareInplace(encrypted1);
evaluator.RelinearizeInplace(encrypted1, relinKeys);
decryptor.Decrypt(encrypted1, plain2);
Assert.AreEqual(1ul, plain2.CoeffCount);
Assert.AreEqual(0ul, plain2[0]);
plain1.Set("1x^10 + 2");
encryptor.Encrypt(plain1, encrypted1);
evaluator.SquareInplace(encrypted1);
evaluator.RelinearizeInplace(encrypted1, relinKeys);
evaluator.SquareInplace(encrypted1);
evaluator.Relinearize(encrypted1, relinKeys, encrypted2);
decryptor.Decrypt(encrypted2, plain2);
// {1x^40 + 8x^30 + 18x^20 + 20x^10 + 10}
Assert.AreEqual(41ul, plain2.CoeffCount);
Assert.AreEqual(16ul, plain2[0]);
Assert.AreEqual(32ul, plain2[10]);
Assert.AreEqual(24ul, plain2[20]);
Assert.AreEqual(8ul, plain2[30]);
Assert.AreEqual(1ul, plain2[40]);
}
[TestMethod]
public void RotateVectorTest()
{
int slotSize = 4;
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 2 * (ulong)slotSize,
CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys galoisKeys = keygen.GaloisKeysLocal();
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
CKKSEncoder encoder = new CKKSEncoder(context);
const double delta = 1ul << 30;
Ciphertext encrypted = new Ciphertext();
Plaintext plain = new Plaintext();
List<Complex> input = new List<Complex>
{
new Complex(1, 1),
new Complex(2, 2),
new Complex(3, 3),
new Complex(4, 4)
};
List<Complex> output = new List<Complex>();
encoder.Encode(input, context.FirstParmsId, delta, plain);
int shift = 1;
encryptor.Encrypt(plain, encrypted);
evaluator.RotateVectorInplace(encrypted, shift, galoisKeys);
decryptor.Decrypt(encrypted, plain);
encoder.Decode(plain, output);
for (int i = 0; i < slotSize; i++)
{
Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1);
Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1);
}
encoder.Encode(input, context.FirstParmsId, delta, plain);
shift = 3;
encryptor.Encrypt(plain, encrypted);
evaluator.RotateVectorInplace(encrypted, shift, galoisKeys);
decryptor.Decrypt(encrypted, plain);
encoder.Decode(plain, output);
for (int i = 0; i < slotSize; i++)
{
Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1);
Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1);
}
}
[TestMethod]
public void ComplexConjugateTest()
{
int slotSize = 4;
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 2 * (ulong)slotSize,
CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys galoisKeys = keygen.GaloisKeysLocal();
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
CKKSEncoder encoder = new CKKSEncoder(context);
const double delta = 1ul << 30;
Ciphertext encrypted = new Ciphertext();
Plaintext plain = new Plaintext();
List<Complex> input = new List<Complex>
{
new Complex(1, 1),
new Complex(2, 2),
new Complex(3, 3),
new Complex(4, 4)
};
List<Complex> output = new List<Complex>();
encoder.Encode(input, context.FirstParmsId, delta, plain);
encryptor.Encrypt(plain, encrypted);
evaluator.ComplexConjugateInplace(encrypted, galoisKeys);
decryptor.Decrypt(encrypted, plain);
encoder.Decode(plain, output);
for (int i = 0; i < slotSize; i++)
{
Assert.AreEqual(input[i].Real, output[i].Real, delta: 0.1);
Assert.AreEqual(-input[i].Imaginary, output[i].Imaginary, delta: 0.1);
}
}
[TestMethod]
public void ExceptionsTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 64,
PlainModulus = new Modulus(65537ul),
CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
Evaluator evaluator = null;
Utilities.AssertThrows<ArgumentNullException>(() => evaluator = new Evaluator(null));
evaluator = new Evaluator(context);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys galoisKeys = keygen.GaloisKeysLocal();
RelinKeys relinKeys = keygen.RelinKeysLocal();
Ciphertext encrypted1 = new Ciphertext();
Ciphertext encrypted2 = new Ciphertext();
Ciphertext encrypted3 = new Ciphertext();
Plaintext plain1 = new Plaintext();
Plaintext plain2 = new Plaintext();
List<Ciphertext> encrypteds = new List<Ciphertext>();
MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal);
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(null, encrypted2, encrypted3));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, null, encrypted3));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, encrypted2, null));
Utilities.AssertThrows<ArgumentException>(() => evaluator.Add(encrypted1, encrypted2, encrypted3));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(encrypteds, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, plain1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(null, plain1, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.AddPlain(encrypted1, plain1, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlainInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlainInplace(null, plain1));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(null, 1, galoisKeys, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(encrypted1, 1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(null, 1, galoisKeys));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, galoisKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(null, galoisKeys, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(null, galoisKeys));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, relinKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(null, 2, relinKeys, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(encrypted1, 2, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(null, 2, relinKeys));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, ParmsId.Zero, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, null, plain2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, plain2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted: null, parmsId: ParmsId.Zero));
Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToInplace(encrypted1, ParmsId.Zero, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain: null, parmsId: ParmsId.Zero));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(plain1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, plain2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNext(encrypted1, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(encrypted: null));
Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNextInplace(encrypted1, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, encrypted2, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, null, encrypted3));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(null, encrypted2, encrypted3));
Utilities.AssertThrows<ArgumentException>(() => evaluator.Multiply(encrypted1, encrypted2, encrypted3, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(null, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyInplace(encrypted1, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(null, relinKeys, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, plain1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(null, plain1, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyPlain(encrypted1, plain1, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(null, plain1));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(null, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.Negate(encrypted1, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.NegateInplace(null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, relinKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(null, relinKeys, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.Relinearize(encrypted1, relinKeys, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(null, relinKeys));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RelinearizeInplace(encrypted1, relinKeys, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(null, ParmsId.Zero, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(null, ParmsId.Zero));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToInplace(encrypted1, ParmsId.Zero, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(null, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNext(encrypted1, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNextInplace(null));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNextInplace(encrypted1, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(null, galoisKeys, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(null, galoisKeys));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumnsInplace(encrypted1, galoisKeys, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(null, 1, galoisKeys, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(encrypted1, 1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(null, 1, galoisKeys));
Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRowsInplace(encrypted1, 1, galoisKeys, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, galoisKeys, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(null, 1, galoisKeys, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(encrypted1, 1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(null, 1, galoisKeys));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(null, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.Square(encrypted1, encrypted2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SquareInplace(null));
Utilities.AssertThrows<ArgumentException>(() => evaluator.SquareInplace(encrypted1, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, encrypted2, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, null, encrypted3));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(null, encrypted2, encrypted3));
Utilities.AssertThrows<ArgumentException>(() => evaluator.Sub(encrypted1, encrypted2, encrypted3));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, plain1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(null, plain1, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.SubPlain(encrypted1, plain1, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlainInplace(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlainInplace(null, plain1));
Utilities.AssertThrows<ArgumentException>(() => evaluator.SubPlainInplace(encrypted1, plain1));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(null, encrypted2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformFromNTT(encrypted1, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTTInplace(null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(encrypted1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, encrypted2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, null, plain2));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, ParmsId.Zero, plain2));
Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, plain2, pool));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(plain1, null));
Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null, ParmsId.Zero));
Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTTInplace(plain1, ParmsId.Zero, pool));
}
/// <summary>
/// Returns true if the two given collections have equivalent elements, false otherwise
/// </summary>
private static bool AreCollectionsEqual<T>(IEnumerable<T> coll1, IEnumerable<T> coll2)
{
int size1 = coll1.Count();
int size2 = coll2.Count();
if (size1 != size2)
return false;
IEnumerator<T> en1 = coll1.GetEnumerator();
IEnumerator<T> en2 = coll2.GetEnumerator();
while (en1.MoveNext() && en2.MoveNext())
{
if (!en1.Current.Equals(en2.Current))
return false;
}
return true;
}
}
}
// 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.IO;
using System.Linq;
namespace SEALNetTest
{
[TestClass]
public class GaloisKeysTests
{
[TestMethod]
public void CreateTest()
{
GaloisKeys keys = new GaloisKeys();
Assert.IsNotNull(keys);
Assert.AreEqual(0ul, keys.Size);
}
[TestMethod]
public void CreateNonEmptyTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys keys = keygen.GaloisKeysLocal();
Assert.IsNotNull(keys);
Assert.AreEqual(24ul, keys.Size);
GaloisKeys copy = new GaloisKeys(keys);
Assert.IsNotNull(copy);
Assert.AreEqual(24ul, copy.Size);
}
[TestMethod]
public void SaveLoadTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keyGen = new KeyGenerator(context);
GaloisKeys keys = keyGen.GaloisKeysLocal();
GaloisKeys other = new GaloisKeys();
Assert.IsNotNull(keys);
Assert.AreEqual(24ul, keys.Size);
using (MemoryStream ms = new MemoryStream())
{
keys.Save(ms);
ms.Seek(offset: 0, loc: SeekOrigin.Begin);
other.Load(context, ms);
}
Assert.AreEqual(24ul, other.Size);
Assert.IsTrue(ValCheck.IsValidFor(other, context));
List<IEnumerable<PublicKey>> keysData = new List<IEnumerable<PublicKey>>(keys.Data);
List<IEnumerable<PublicKey>> otherData = new List<IEnumerable<PublicKey>>(other.Data);
Assert.AreEqual(keysData.Count, otherData.Count);
for (int i = 0; i < keysData.Count; i++)
{
List<PublicKey> keysCiphers = new List<PublicKey>(keysData[i]);
List<PublicKey> otherCiphers = new List<PublicKey>(otherData[i]);
Assert.AreEqual(keysCiphers.Count, otherCiphers.Count);
for (int j = 0; j < keysCiphers.Count; j++)
{
PublicKey keysCipher = keysCiphers[j];
PublicKey otherCipher = otherCiphers[j];
Assert.AreEqual(keysCipher.Data.Size, otherCipher.Data.Size);
Assert.AreEqual(keysCipher.Data.PolyModulusDegree, otherCipher.Data.PolyModulusDegree);
Assert.AreEqual(keysCipher.Data.CoeffModulusSize, otherCipher.Data.CoeffModulusSize);
ulong coeffCount = keysCipher.Data.Size * keysCipher.Data.PolyModulusDegree * keysCipher.Data.CoeffModulusSize;
for (ulong k = 0; k < coeffCount; k++)
{
Assert.AreEqual(keysCipher.Data[k], otherCipher.Data[k]);
}
}
}
}
[TestMethod]
public void SeededKeyTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 8,
PlainModulus = new Modulus(257),
CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
Encryptor encryptor = new Encryptor(context, keygen.PublicKey);
Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
Evaluator evaluator = new Evaluator(context);
BatchEncoder encoder = new BatchEncoder(context);
GaloisKeys galoisKeys = new GaloisKeys();
using (MemoryStream stream = new MemoryStream())
{
keygen.GaloisKeys().Save(stream);
stream.Seek(0, SeekOrigin.Begin);
galoisKeys.Load(context, stream);
}
Plaintext plain = new Plaintext();
List<ulong> vec = new List<ulong>
{
1, 2, 3, 4,
5, 6, 7, 8
};
encoder.Encode(vec, plain);
Ciphertext encrypted = new Ciphertext();
Ciphertext encdest = new Ciphertext();
Plaintext plaindest = new Plaintext();
encryptor.Encrypt(plain, encrypted);
evaluator.RotateColumns(encrypted, galoisKeys, encdest);
decryptor.Decrypt(encdest, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
5, 6, 7, 8,
1, 2, 3, 4
}));
evaluator.RotateRows(encdest, -1, galoisKeys, encrypted);
decryptor.Decrypt(encrypted, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
8, 5, 6, 7,
4, 1, 2, 3
}));
evaluator.RotateRowsInplace(encrypted, 2, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
6, 7, 8, 5,
2, 3, 4, 1
}));
evaluator.RotateColumnsInplace(encrypted, galoisKeys);
decryptor.Decrypt(encrypted, plaindest);
encoder.Decode(plaindest, vec);
Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
{
2, 3, 4, 1,
6, 7, 8, 5
}));
}
[TestMethod]
public void SetTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys keys = keygen.GaloisKeysLocal();
Assert.IsNotNull(keys);
Assert.AreEqual(24ul, keys.Size);
GaloisKeys keys2 = new GaloisKeys();
Assert.IsNotNull(keys2);
Assert.AreEqual(0ul, keys2.Size);
keys2.Set(keys);
Assert.AreNotSame(keys, keys2);
Assert.AreEqual(24ul, keys2.Size);
}
[TestMethod]
public void KeyTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys keys = keygen.GaloisKeysLocal();
MemoryPoolHandle handle = keys.Pool;
Assert.IsNotNull(keys);
Assert.AreEqual(24ul, keys.Size);
Assert.IsFalse(keys.HasKey(galoisElt: 1));
Assert.IsTrue(keys.HasKey(galoisElt: 3));
Assert.IsFalse(keys.HasKey(galoisElt: 5));
Assert.IsFalse(keys.HasKey(galoisElt: 7));
Assert.IsTrue(keys.HasKey(galoisElt: 9));
Assert.IsFalse(keys.HasKey(galoisElt: 11));
IEnumerable<PublicKey> key = keys.Key(3);
Assert.AreEqual(4, key.Count());
IEnumerable<PublicKey> key2 = keys.Key(9);
Assert.AreEqual(4, key2.Count());
Assert.IsTrue(handle.AllocByteCount > 0ul);
}
[TestMethod]
public void KeyEltTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys keys = keygen.GaloisKeysLocal(galoisElts: new uint[] { 1, 3 });
Assert.IsNotNull(keys);
Assert.AreEqual(2ul, keys.Size);
Assert.IsTrue(keys.HasKey(1));
Assert.IsTrue(keys.HasKey(3));
Assert.IsFalse(keys.HasKey(5));
}
[TestMethod]
public void KeyStepTest()
{
EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 64,
CoeffModulus = CoeffModulus.Create(64, new int[] { 60, 60 })
};
SEALContext context = new SEALContext(parms,
expandModChain: false,
secLevel: SecLevelType.None);
KeyGenerator keygen = new KeyGenerator(context);
GaloisKeys keys = keygen.GaloisKeysLocal(steps: new int[] { 1, 2, 3 });
Assert.IsNotNull(keys);
Assert.AreEqual(3ul, keys.Size);
Assert.IsFalse(keys.HasKey(1));
Assert.IsTrue(keys.HasKey(3));
Assert.IsFalse(keys.HasKey(5));
Assert.IsFalse(keys.HasKey(7));
Assert.IsTrue(keys.HasKey(9));
Assert.IsFalse(keys.HasKey(11));
Assert.IsFalse(keys.HasKey(13));
Assert.IsFalse(keys.HasKey(15));
Assert.IsFalse(keys.HasKey(17));
Assert.IsFalse(keys.HasKey(19));
Assert.IsFalse(keys.HasKey(21));
Assert.IsFalse(keys.HasKey(23));
Assert.IsFalse(keys.HasKey(25));
Assert.IsTrue(keys.HasKey(27));
}
[TestMethod]
public void ExceptionsTest()
{
SEALContext context = GlobalContext.BFVContext;
GaloisKeys keys = new GaloisKeys();
Utilities.AssertThrows<ArgumentNullException>(() => keys = new GaloisKeys(null));
Utilities.AssertThrows<ArgumentNullException>(() => keys.Set(null));
Utilities.AssertThrows<ArgumentNullException>(() => ValCheck.IsValidFor(keys, null));
Utilities.AssertThrows<ArgumentNullException>(() => keys.Save(null));
Utilities.AssertThrows<ArgumentNullException>(() => keys.UnsafeLoad(context, null));
Utilities.AssertThrows<EndOfStreamException>(() => keys.UnsafeLoad(context, new MemoryStream()));
Utilities.AssertThrows<ArgumentNullException>(() => keys.UnsafeLoad(null, new MemoryStream()));
Utilities.AssertThrows<ArgumentNullException>(() => keys.Load(context, null));
Utilities.AssertThrows<ArgumentNullException>(() => keys.Load(null, new MemoryStream()));
}
/// <summary>
/// Returns true if the two given collections have equivalent elements, false otherwise
/// </summary>
private static bool AreCollectionsEqual<T>(IEnumerable<T> coll1, IEnumerable<T> coll2)
{
int size1 = coll1.Count();
int size2 = coll2.Count();
if (size1 != size2)
return false;
IEnumerator<T> en1 = coll1.GetEnumerator();
IEnumerator<T> en2 = coll2.GetEnumerator();
while (en1.MoveNext() && en2.MoveNext())
{
if (!en1.Current.Equals(en2.Current))
return false;
}
return true;
}
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL;
namespace SEALNetTest
{
/// <summary>
/// Provides a global SEALContext that can be used by Tests.
/// Necessary to run tests fast, as creating a SEALContext can take around
/// 2 seconds.
/// </summary>
static class GlobalContext
{
static GlobalContext()
{
EncryptionParameters encParams = new EncryptionParameters(SchemeType.BFV)
{
PolyModulusDegree = 8192,
CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192)
};
encParams.SetPlainModulus(65537ul);
BFVContext = new SEALContext(encParams);
encParams = new EncryptionParameters(SchemeType.CKKS)
{
PolyModulusDegree = 8192,
CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree: 8192)
};
CKKSContext = new SEALContext(encParams);
}
public static SEALContext BFVContext { get; private set; } = null;
public static SEALContext CKKSContext { get; private set; } = null;
}
}
using Microsoft.Research.SEAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace SEALNetTest
{
[TestClass]
public class IntegerEncoderTests
{
[TestMethod]
public void CreateTest()
{
IntegerEncoder encoder = new IntegerEncoder(GlobalContext.BFVContext);
Assert.IsNotNull(encoder);
Assert.AreEqual(65537ul, encoder.PlainModulus.Value);
}
[TestMethod]
public void EncodeTest()
{
IntegerEncoder encoder = new IntegerEncoder(GlobalContext.BFVContext);
Plaintext plain = encoder.Encode(10);
Assert.IsNotNull(plain);
Assert.AreEqual(4ul, plain.CoeffCount);
Assert.AreEqual(0ul, plain[0]);
Assert.AreEqual(1ul, plain[1]);
Assert.AreEqual(0ul, plain[2]);
Assert.AreEqual(1ul, plain[3]);
plain = encoder.Encode(13u);
Assert.AreEqual(4ul, plain.CoeffCount);
Assert.AreEqual(1ul, plain[0]);
Assert.AreEqual(0ul, plain[1]);
Assert.AreEqual(1ul, plain[2]);
Assert.AreEqual(1ul, plain[3]);
plain = encoder.Encode(20L);
Assert.AreEqual(5ul, plain.CoeffCount);
Assert.AreEqual(0ul, plain[0]);
Assert.AreEqual(0ul, plain[1]);
Assert.AreEqual(1ul, plain[2]);
Assert.AreEqual(0ul, plain[3]);
Assert.AreEqual(1ul, plain[4]);
plain = encoder.Encode(15ul);
Assert.AreEqual(4ul, plain.CoeffCount);
Assert.AreEqual(1ul, plain[0]);
Assert.AreEqual(1ul, plain[1]);
Assert.AreEqual(1ul, plain[2]);
Assert.AreEqual(1ul, plain[3]);
BigUInt bui = new BigUInt("AB");
plain = encoder.Encode(bui);
Assert.AreEqual(8ul, plain.CoeffCount);
Assert.AreEqual(1ul, plain[0]);
Assert.AreEqual(1ul, plain[1]);
Assert.AreEqual(0ul, plain[2]);
Assert.AreEqual(1ul, plain[3]);
Assert.AreEqual(0ul, plain[4]);
Assert.AreEqual(1ul, plain[5]);
Assert.AreEqual(0ul, plain[6]);
Assert.AreEqual(1ul, plain[7]);
Plaintext plain2 = new Plaintext();
encoder.Encode(10, plain2);
Assert.AreEqual(4ul, plain2.CoeffCount);
Assert.AreEqual(0ul, plain2[0]);
Assert.AreEqual(1ul, plain2[1]);
Assert.AreEqual(0ul, plain2[2]);
Assert.AreEqual(1ul, plain2[3]);
encoder.Encode(13u, plain2);
Assert.AreEqual(4ul, plain2.CoeffCount);
Assert.AreEqual(1ul, plain2[0]);
Assert.AreEqual(0ul, plain2[1]);
Assert.AreEqual(1ul, plain2[2]);
Assert.AreEqual(1ul, plain2[3]);
encoder.Encode(20L, plain2);
Assert.AreEqual(5ul, plain2.CoeffCount);
Assert.AreEqual(0ul, plain2[0]);
Assert.AreEqual(0ul, plain2[1]);
Assert.AreEqual(1ul, plain2[2]);
Assert.AreEqual(0ul, plain2[3]);
Assert.AreEqual(1ul, plain2[4]);
encoder.Encode(15ul, plain2);
Assert.AreEqual(4ul, plain2.CoeffCount);
Assert.AreEqual(1ul, plain2[0]);
Assert.AreEqual(1ul, plain2[1]);
Assert.AreEqual(1ul, plain2[2]);
Assert.AreEqual(1ul, plain2[3]);
encoder.Encode(bui, plain2);
Assert.AreEqual(8ul, plain2.CoeffCount);
Assert.AreEqual(1ul, plain2[0]);
Assert.AreEqual(1ul, plain2[1]);
Assert.AreEqual(0ul, plain2[2]);
Assert.AreEqual(1ul, plain2[3]);
Assert.AreEqual(0ul, plain2[4]);
Assert.AreEqual(1ul, plain2[5]);
Assert.AreEqual(0ul, plain2[6]);
Assert.AreEqual(1ul, plain2[7]);
}
[TestMethod]
public void DecodeTest()
{
IntegerEncoder encoder = new IntegerEncoder(GlobalContext.BFVContext);
Plaintext plain = new Plaintext("0x^5 + 1x^4 + 1x^3 + 1x^1 + 0");
Assert.AreEqual(6ul, plain.CoeffCount);
ulong resultU64 = encoder.DecodeUInt64(plain);
Assert.AreEqual(26UL, resultU64);
long resultI64 = encoder.DecodeInt64(plain);
Assert.AreEqual(26L, resultI64);
uint resultU32 = encoder.DecodeUInt32(plain);
Assert.AreEqual(26U, resultU32);
int resultI32 = encoder.DecodeInt32(plain);
Assert.AreEqual(26, resultI32);
BigUInt bui = encoder.DecodeBigUInt(plain);
Assert.IsNotNull(bui);
Assert.AreEqual(0, bui.CompareTo(26ul));
}
[TestMethod]
public void ExceptionsTest()
{
SEALContext context = GlobalContext.BFVContext;
SEALContext context_null = null;
IntegerEncoder enc = new IntegerEncoder(context);
BigUInt bui_null = null;
BigUInt bui = new BigUInt(5ul);
Plaintext plain = new Plaintext();
Utilities.AssertThrows<ArgumentNullException>(() => enc = new IntegerEncoder(context_null));
Utilities.AssertThrows<ArgumentException>(() => enc = new IntegerEncoder(GlobalContext.CKKSContext));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1ul, null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1L, null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1, null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(1u, null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(bui_null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(bui, null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.Encode(bui_null, plain));
Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeUInt32(null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeUInt64(null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeInt32(null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeInt64(null));
Utilities.AssertThrows<ArgumentNullException>(() => enc.DecodeBigUInt(null));
}
}
}
// 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.IO;
namespace SEALNetTest
{
[TestClass]
public class KeyGeneratorTests
{
[TestMethod]
public void CreateTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
Assert.IsNotNull(keygen);
PublicKey pubKey = keygen.PublicKey;
SecretKey secKey = keygen.SecretKey;
Assert.IsNotNull(pubKey);
Assert.IsNotNull(secKey);
Ciphertext cipher = pubKey.Data;
Assert.IsNotNull(cipher);
Plaintext plain = secKey.Data;
Assert.IsNotNull(plain);
Assert.AreEqual(40960ul, plain.CoeffCount);
}
[TestMethod]
public void Create2Test()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen1 = new KeyGenerator(context);
Encryptor encryptor1 = new Encryptor(context, keygen1.PublicKey);
Decryptor decryptor1 = new Decryptor(context, keygen1.SecretKey);
Ciphertext cipher = new Ciphertext();
Plaintext plain = new Plaintext("2x^1 + 5");
Plaintext plain2 = new Plaintext();
encryptor1.Encrypt(plain, cipher);
decryptor1.Decrypt(cipher, plain2);
Assert.AreNotSame(plain, plain2);
Assert.AreEqual(plain, plain2);
KeyGenerator keygen2 = new KeyGenerator(context, keygen1.SecretKey);
Encryptor encryptor2 = new Encryptor(context, keygen2.PublicKey);
Decryptor decryptor2 = new Decryptor(context, keygen2.SecretKey);
Plaintext plain3 = new Plaintext();
decryptor2.Decrypt(cipher, plain3);
Assert.AreNotSame(plain, plain3);
Assert.AreEqual(plain, plain3);
}
[TestMethod]
public void KeyCopyTest()
{
SEALContext context = GlobalContext.BFVContext;
PublicKey pk = null;
SecretKey sk = null;
using (KeyGenerator keygen = new KeyGenerator(context))
{
pk = keygen.PublicKey;
sk = keygen.SecretKey;
}
ParmsId parmsIdPK = pk.ParmsId;
ParmsId parmsIdSK = sk.ParmsId;
Assert.AreEqual(parmsIdPK, parmsIdSK);
Assert.AreEqual(parmsIdPK, context.KeyParmsId);
}
[TestMethod]
public void ExceptionsTest()
{
SEALContext context = GlobalContext.BFVContext;
KeyGenerator keygen = new KeyGenerator(context);
SecretKey secret = new SecretKey();
List<uint> elts = new List<uint> { 16385 };
List<uint> elts_null = null;
List<int> steps = new List<int> { 4096 };
List<int> steps_null = null;
Utilities.AssertThrows<ArgumentNullException>(() => keygen = new KeyGenerator(null));
Utilities.AssertThrows<ArgumentNullException>(() => keygen = new KeyGenerator(context, null));
Utilities.AssertThrows<ArgumentNullException>(() => keygen = new KeyGenerator(null, keygen.SecretKey));
Utilities.AssertThrows<ArgumentException>(() => keygen = new KeyGenerator(context, secret));
Utilities.AssertThrows<ArgumentNullException>(() => keygen.GaloisKeys(elts_null));
Utilities.AssertThrows<ArgumentException>(() => keygen.GaloisKeys(elts));
Utilities.AssertThrows<ArgumentNullException>(() => keygen.GaloisKeys(steps_null));
Utilities.AssertThrows<ArgumentException>(() => keygen.GaloisKeys(steps));
EncryptionParameters smallParms = new EncryptionParameters(SchemeType.CKKS);
smallParms.PolyModulusDegree = 128;
smallParms.CoeffModulus = CoeffModulus.Create(smallParms.PolyModulusDegree, new int[] { 60 });
context = new SEALContext(smallParms, true, SecLevelType.None);
keygen = new KeyGenerator(context);
Utilities.AssertThrows<InvalidOperationException>(() => keygen.RelinKeys());
Utilities.AssertThrows<InvalidOperationException>(() => keygen.GaloisKeys());
}
}
}
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