// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using Microsoft.Research.SEAL.Tools; using System; namespace Microsoft.Research.SEAL { /// /// Encodes integers into plaintext polynomials that Encryptor can encrypt. An instance of /// the IntegerEncoder class converts an integer into a plaintext polynomial by placing its /// binary digits as the coefficients of the polynomial. Decoding the integer amounts to /// evaluating the plaintext polynomial at x=2. /// /// Addition and multiplication on the integer side translate into addition and multiplication /// on the encoded plaintext polynomial side, provided that the length of the polynomial /// never grows to be of the size of the polynomial modulus (PolyModulus), and that the /// coefficients of the plaintext polynomials appearing throughout the computations never /// experience coefficients larger than the plaintext modulus (PlainModulus). /// /// /// /// Negative Integers /// Negative integers are represented by using -1 instead of 1 in the binary representation, /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 /// would be stored as a polynomial coefficient PlainModulus-1. /// /// public class IntegerEncoder : NativeObject { /// /// Creates a IntegerEncoder object. The constructor takes as input a pointer to /// a SEALContext object which contains the plaintext modulus. /// /// The SEALContext /// if context is null /// if the context is not set /// if the PlainModulus set in context is not /// at least 2 public IntegerEncoder(SEALContext context) { if (null == context) throw new ArgumentNullException(nameof(context)); if (!context.ParametersSet) throw new ArgumentException("Encryption parameters are not set correctly"); SEALContext.ContextData contextData = context.FirstContextData; if (contextData.Parms.Scheme != SchemeType.BFV) throw new ArgumentException("Unsupported scheme"); NativeMethods.IntegerEncoder_Create(context.NativePtr, out IntPtr encoderPtr); NativePtr = encoderPtr; } /// /// Encodes an unsigned integer (represented by ulong) into a plaintext polynomial. /// /// The unsigned integer to encode public Plaintext Encode(ulong value) { Plaintext plain = new Plaintext(); NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); return plain; } /// /// Encodes an unsigned integer(represented by ulong) into a plaintext polynomial. /// /// The unsigned integer to encode /// The plaintext to overwrite with the encoding /// if destination is null public void Encode(ulong value, Plaintext destination) { if (null == destination) throw new ArgumentNullException(nameof(destination)); NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); } /// /// Decodes a plaintext polynomial and returns the result as uint. Mathematically /// this amounts to evaluating the input polynomial at X = 2. /// /// The plaintext to be decoded /// if plain is null /// if plain does not represent a valid plaintext polynomial /// if the output does not fit in uint public uint DecodeUInt32(Plaintext plain) { if (null == plain) throw new ArgumentNullException(nameof(plain)); NativeMethods.IntegerEncoder_DecodeUInt32(NativePtr, plain.NativePtr, out uint result); return result; } /// /// Decodes a plaintext polynomial and returns the result as ulong. Mathematically /// this amounts to evaluating the input polynomial at X=2. /// /// The plaintext to be decoded /// if plain is null /// if plain does not represent a valid plaintext polynomial /// if the output does not fit in ulong public ulong DecodeUInt64(Plaintext plain) { if (null == plain) throw new ArgumentNullException(nameof(plain)); NativeMethods.IntegerEncoder_DecodeUInt64(NativePtr, plain.NativePtr, out ulong result); return result; } /// /// Encodes a signed integer (represented by long) into a plaintext polynomial. /// /// /// /// Negative Integers /// Negative integers are represented by using -1 instead of 1 in the binary representation, /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 /// would be stored as a polynomial coefficient PlainModulus-1. /// /// /// The signed integer to encode public Plaintext Encode(long value) { Plaintext plain = new Plaintext(); NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); return plain; } /// /// Encodes a signed integer(represented by long) into a plaintext polynomial. /// /// /// /// Negative Integers /// Negative integers are represented by using -1 instead of 1 in the binary representation, /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 /// would be stored as a polynomial coefficient PlainModulus-1. /// /// /// The signed integer to encode /// The plaintext to overwrite with the encoding public void Encode(long value, Plaintext destination) { if (null == destination) throw new ArgumentNullException(nameof(destination)); NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); } /// /// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial. /// /// The unsigned integer to encode /// if value is null public Plaintext Encode(BigUInt value) { if (null == value) throw new ArgumentNullException(nameof(value)); Plaintext plain = new Plaintext(); NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, plain.NativePtr); return plain; } /// /// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial. /// /// The unsigned integer to encode /// The plaintext to overwrite with the encoding /// if either value or destination are null public void Encode(BigUInt value, Plaintext destination) { if (null == value) throw new ArgumentNullException(nameof(value)); if (null == destination) throw new ArgumentNullException(nameof(destination)); NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, destination.NativePtr); } /// /// Decodes a plaintext polynomial and returns the result as int. Mathematically /// this amounts to evaluating the input polynomial at X = 2. /// /// The plaintext to be decoded /// if plain is null /// if plain does not represent a valid plaintext polynomial /// if the output does not fit in int public int DecodeInt32(Plaintext plain) { if (null == plain) throw new ArgumentNullException(nameof(plain)); NativeMethods.IntegerEncoder_DecodeInt32(NativePtr, plain.NativePtr, out int result); return result; } /// /// Decodes a plaintext polynomial and returns the result as long. Mathematically /// this amounts to evaluating the input polynomial at X = 2. /// /// The plaintext to be decoded /// if plain is null /// if plain does not represent a valid plaintext polynomial /// if the output does not fit in long public long DecodeInt64(Plaintext plain) { if (null == plain) throw new ArgumentNullException(nameof(plain)); NativeMethods.IntegerEncoder_DecodeInt64(NativePtr, plain.NativePtr, out long result); return result; } /// /// Decodes a plaintext polynomial and returns the result as BigUInt. /// Mathematically this amounts to evaluating the input polynomial at X = 2. /// /// The plaintext to be decoded /// if plain is null /// if plain does not represent a valid plaintext polynomial /// if the output is negative public BigUInt DecodeBigUInt(Plaintext plain) { if (null == plain) throw new ArgumentNullException(nameof(plain)); NativeMethods.IntegerEncoder_DecodeBigUInt(NativePtr, plain.NativePtr, out IntPtr buiPtr); BigUInt bui = new BigUInt(buiPtr); return bui; } /// /// Encodes a signed integer(represented by int) into a plaintext polynomial. /// /// /// /// Negative Integers /// Negative integers are represented by using -1 instead of 1 in the binary representation, /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 /// would be stored as a polynomial coefficient PlainModulus-1. /// /// /// The signed integer to encode public Plaintext Encode(int value) { Plaintext plain = new Plaintext(); NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); return plain; } /// /// Encodes an unsigned integer(represented by uint) into a plaintext polynomial. /// /// The unsigned integer to encode public Plaintext Encode(uint value) { Plaintext plain = new Plaintext(); NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr); return plain; } /// /// Encodes a signed integer(represented by int) into a plaintext polynomial. /// /// /// /// Negative Integers /// Negative integers are represented by using -1 instead of 1 in the binary representation, /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1 /// would be stored as a polynomial coefficient PlainModulus-1. /// /// /// The signed integer to encode /// The plaintext to overwrite with the encoding /// if destination is null public void Encode(int value, Plaintext destination) { if (null == destination) throw new ArgumentNullException(nameof(destination)); NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); } /// /// Encodes an unsigned integer(represented by uint) into a plaintext polynomial. /// /// The unsigned integer to encode /// The plaintext to overwrite with the encoding /// if destination is null public void Encode(uint value, Plaintext destination) { if (null == destination) throw new ArgumentNullException(nameof(destination)); NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr); } /// /// Get a copy of the plaintext modulus. /// public Modulus PlainModulus { get { NativeMethods.IntegerEncoder_PlainModulus(NativePtr, out IntPtr sm); Modulus result = new Modulus(sm); return result; } } /// /// Destroy the native object /// protected override void DestroyNativeObject() { NativeMethods.IntegerEncoder_Destroy(NativePtr); } } }