示例#1
0
        public void KeyCopyTest()
        {
            {
                SEALContext context = GlobalContext.BFVContext;
                PublicKey   pk;
                SecretKey   sk = null;

                using (KeyGenerator keygen = new KeyGenerator(context))
                {
                    keygen.CreatePublicKey(out pk);
                    sk = keygen.SecretKey;
                }

                ParmsId parmsIdPK = pk.ParmsId;
                ParmsId parmsIdSK = sk.ParmsId;
                Assert.AreEqual(parmsIdPK, parmsIdSK);
                Assert.AreEqual(parmsIdPK, context.KeyParmsId);
            }
            {
                SEALContext context = GlobalContext.BGVContext;
                PublicKey   pk;
                SecretKey   sk = null;

                using (KeyGenerator keygen = new KeyGenerator(context))
                {
                    keygen.CreatePublicKey(out pk);
                    sk = keygen.SecretKey;
                }

                ParmsId parmsIdPK = pk.ParmsId;
                ParmsId parmsIdSK = sk.ParmsId;
                Assert.AreEqual(parmsIdPK, parmsIdSK);
                Assert.AreEqual(parmsIdPK, context.KeyParmsId);
            }
        }
示例#2
0
        public void ParamIDConstructorTest()
        {
            ParmsId id = new ParmsId();

            Assert.AreEqual(0ul, id.Block[0]);
            Assert.AreEqual(0ul, id.Block[1]);
            Assert.AreEqual(0ul, id.Block[2]);
            Assert.AreEqual(0ul, id.Block[3]);

            id.Block[0] = 5;
            id.Block[1] = 4;
            id.Block[2] = 3;
            id.Block[3] = 2;

            ParmsId id2 = new ParmsId(id);

            id.Block[1] = 7;

            Assert.AreEqual(5ul, id2.Block[0]);
            Assert.AreEqual(4ul, id2.Block[1]);
            Assert.AreEqual(3ul, id2.Block[2]);
            Assert.AreEqual(2ul, id2.Block[3]);
            Assert.AreEqual(7ul, id.Block[1]);

            Assert.IsFalse(id2.Equals(null));
            Assert.AreNotEqual(id.GetHashCode(), id2.GetHashCode());
        }
示例#3
0
        public void ExceptionsTest()
        {
            ParmsId id      = new ParmsId();
            ParmsId id_null = null;

            Utilities.AssertThrows <ArgumentNullException>(() => id = new ParmsId(id_null));
        }
示例#4
0
        public void ExceptionsTest()
        {
            ParmsId id      = new ParmsId();
            ParmsId id_null = null;

            Assert.ThrowsException <ArgumentNullException>(() => id = new ParmsId(id_null));

            Assert.ThrowsException <ArgumentNullException>(() => id.Load(null));
            Assert.ThrowsException <ArgumentNullException>(() => id.Save(null));
        }
示例#5
0
        public void ToStringTest()
        {
            ParmsId id = new ParmsId();

            id.Block[0] = 1;
            id.Block[1] = 2;
            id.Block[2] = 3;
            id.Block[3] = 4;

            Assert.AreEqual("0000000000000001 0000000000000002 0000000000000003 0000000000000004", id.ToString());
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
        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, 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.EncryptSymmetricSave(plain, null));
            Utilities.AssertThrows <ArgumentNullException>(() => encryptor.EncryptZeroSymmetricSave(null));
            Utilities.AssertThrows <ArgumentException>(() => encryptor.EncryptZeroSymmetricSave(parmsId_invalid, null));
        }
示例#9
0
        public void ResizeTest()
        {
            SEALContext context = GlobalContext.Context;
            ParmsId     parms   = context.FirstParmsId;

            Ciphertext cipher = new Ciphertext(context, parms);

            Assert.AreEqual(2ul, cipher.SizeCapacity);
            Assert.AreEqual(16384ul, cipher.UInt64CountCapacity);

            cipher.Reserve(context, parms, sizeCapacity: 10);
            Assert.AreEqual(10ul, cipher.SizeCapacity);
            Assert.AreEqual(16384ul * 5, cipher.UInt64CountCapacity);

            Ciphertext cipher2 = new Ciphertext();

            Assert.AreEqual(2ul, cipher2.SizeCapacity);

            cipher2.Reserve(context, 5);
            Assert.AreEqual(5ul, cipher2.SizeCapacity);

            Ciphertext cipher3 = new Ciphertext();

            Assert.AreEqual(2ul, cipher3.SizeCapacity);

            cipher3.Reserve(4);
            Assert.AreEqual(4ul, cipher3.SizeCapacity);

            Ciphertext cipher4 = new Ciphertext(context);

            cipher4.Resize(context, context.GetContextData(context.FirstParmsId).NextContextData.Parms.ParmsId, 4);
            Assert.AreEqual(10ul, cipher.SizeCapacity);

            Ciphertext cipher5 = new Ciphertext(context);

            cipher5.Resize(context, 6ul);
            Assert.AreEqual(2ul, cipher5.SizeCapacity);
        }
示例#10
0
        public void OperatorsTest()
        {
            ParmsId id = new ParmsId();

            id.Block[0] = 1;
            id.Block[1] = 2;
            id.Block[2] = 3;
            id.Block[3] = 4;

            ParmsId id2 = new ParmsId(id);

            ParmsId id3 = new ParmsId(id);

            id3.Block[0] = 2;

            Assert.IsTrue(id == id2);
            Assert.IsFalse(id == id3);

            ParmsId id_null1 = null;
            ParmsId id_null2 = null;

            Assert.IsFalse(id_null1 != id_null2);
            Assert.IsTrue(id_null1 != id);
        }
示例#11
0
        private static void ExampleCKKSBasics()
        {
            Utilities.PrintExampleBanner("Example: CKKS Basics");

            /*
             * In this example we demonstrate evaluating a polynomial function
             *
             *  PI*x^3 + 0.4*x + 1
             *
             * on encrypted floating-point input data x for a set of 4096 equidistant points
             * in the interval [0, 1]. This example demonstrates many of the main features
             * of the CKKS scheme, but also the challenges in using it.
             *
             * We start by setting up the CKKS scheme.
             */
            using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

            /*
             * We saw in `2_Encoders.cs' that multiplication in CKKS causes scales in
             * ciphertexts to grow. The scale of any ciphertext must not get too close to
             * the total size of CoeffModulus, or else the ciphertext simply runs out of
             * room to store the scaled-up plaintext. The CKKS scheme provides a `rescale'
             * functionality that can reduce the scale, and stabilize the scale expansion.
             *
             * Rescaling is a kind of modulus switch operation (recall `3_Levels.cs').
             * As modulus switching, it removes the last of the primes from CoeffModulus,
             * but as a side-effect it scales down the ciphertext by the removed prime.
             * Usually we want to have perfect control over how the scales are changed,
             * which is why for the CKKS scheme it is more common to use carefully selected
             * primes for the CoeffModulus.
             *
             * More precisely, suppose that the scale in a CKKS ciphertext is S, and the
             * last prime in the current CoeffModulus (for the ciphertext) is P. Rescaling
             * to the next level changes the scale to S/P, and removes the prime P from the
             * CoeffModulus, as usual in modulus switching. The number of primes limits
             * how many rescalings can be done, and thus limits the multiplicative depth of
             * the computation.
             *
             * It is possible to choose the initial scale freely. One good strategy can be
             * to is to set the initial scale S and primes P_i in the CoeffModulus to be
             * very close to each other. If ciphertexts have scale S before multiplication,
             * they have scale S^2 after multiplication, and S^2/P_i after rescaling. If all
             * P_i are close to S, then S^2/P_i is close to S again. This way we stabilize the
             * scales to be close to S throughout the computation. Generally, for a circuit
             * of depth D, we need to rescale D times, i.e., we need to be able to remove D
             * primes from the coefficient modulus. Once we have only one prime left in the
             * coeff_modulus, the remaining prime must be larger than S by a few bits to
             * preserve the pre-decimal-point value of the plaintext.
             *
             * Therefore, a generally good strategy is to choose parameters for the CKKS
             * scheme as follows:
             *
             *  (1) Choose a 60-bit prime as the first prime in CoeffModulus. This will
             *      give the highest precision when decrypting;
             *  (2) Choose another 60-bit prime as the last element of CoeffModulus, as
             *      this will be used as the special prime and should be as large as the
             *      largest of the other primes;
             *  (3) Choose the intermediate primes to be close to each other.
             *
             * We use CoeffModulus.Create to generate primes of the appropriate size. Note
             * that our CoeffModulus is 200 bits total, which is below the bound for our
             * PolyModulusDegree: CoeffModulus.MaxBitCount(8192) returns 218.
             */
            ulong polyModulusDegree = 8192;

            parms.PolyModulusDegree = polyModulusDegree;
            parms.CoeffModulus      = CoeffModulus.Create(
                polyModulusDegree, new int[] { 60, 40, 40, 60 });

            /*
             * We choose the initial scale to be 2^40. At the last level, this leaves us
             * 60-40=20 bits of precision before the decimal point, and enough (roughly
             * 10-20 bits) of precision after the decimal point. Since our intermediate
             * primes are 40 bits (in fact, they are very close to 2^40), we can achieve
             * scale stabilization as described above.
             */
            double scale = Math.Pow(2.0, 40);

            using SEALContext context = new SEALContext(parms);
            Utilities.PrintParameters(context);
            Console.WriteLine();

            using KeyGenerator keygen = new KeyGenerator(context);
            using PublicKey publicKey = keygen.PublicKey;
            using SecretKey secretKey = keygen.SecretKey;
            using RelinKeys relinKeys = keygen.RelinKeysLocal();
            using Encryptor encryptor = new Encryptor(context, publicKey);
            using Evaluator evaluator = new Evaluator(context);
            using Decryptor decryptor = new Decryptor(context, secretKey);

            using CKKSEncoder encoder = new CKKSEncoder(context);
            ulong slotCount = encoder.SlotCount;

            Console.WriteLine($"Number of slots: {slotCount}");

            List <double> input = new List <double>((int)slotCount);
            double        currPoint = 0, stepSize = 1.0 / (slotCount - 1);

            for (ulong i = 0; i < slotCount; i++, currPoint += stepSize)
            {
                input.Add(currPoint);
            }
            Console.WriteLine("Input vector:");
            Utilities.PrintVector(input, 3, 7);

            Console.WriteLine("Evaluating polynomial PI*x^3 + 0.4x + 1 ...");

            /*
             * We create plaintexts for PI, 0.4, and 1 using an overload of CKKSEncoder.Encode
             * that encodes the given floating-point value to every slot in the vector.
             */
            using Plaintext plainCoeff3 = new Plaintext(),
                  plainCoeff1           = new Plaintext(),
                  plainCoeff0           = new Plaintext();
            encoder.Encode(3.14159265, scale, plainCoeff3);
            encoder.Encode(0.4, scale, plainCoeff1);
            encoder.Encode(1.0, scale, plainCoeff0);

            using Plaintext xPlain = new Plaintext();
            Utilities.PrintLine();
            Console.WriteLine("Encode input vectors.");
            encoder.Encode(input, scale, xPlain);
            using Ciphertext x1Encrypted = new Ciphertext();
            encryptor.Encrypt(xPlain, x1Encrypted);

            /*
             * To compute x^3 we first compute x^2 and relinearize. However, the scale has
             * now grown to 2^80.
             */
            using Ciphertext x3Encrypted = new Ciphertext();
            Utilities.PrintLine();
            Console.WriteLine("Compute x^2 and relinearize:");
            evaluator.Square(x1Encrypted, x3Encrypted);
            evaluator.RelinearizeInplace(x3Encrypted, relinKeys);
            Console.WriteLine("    + Scale of x^2 before rescale: {0} bits",
                              Math.Log(x3Encrypted.Scale, newBase: 2));

            /*
             * Now rescale; in addition to a modulus switch, the scale is reduced down by
             * a factor equal to the prime that was switched away (40-bit prime). Hence, the
             * new scale should be close to 2^40. Note, however, that the scale is not equal
             * to 2^40: this is because the 40-bit prime is only close to 2^40.
             */
            Utilities.PrintLine();
            Console.WriteLine("Rescale x^2.");
            evaluator.RescaleToNextInplace(x3Encrypted);
            Console.WriteLine("    + Scale of x^2 after rescale: {0} bits",
                              Math.Log(x3Encrypted.Scale, newBase: 2));

            /*
             * Now x3Encrypted is at a different level than x1Encrypted, which prevents us
             * from multiplying them to compute x^3. We could simply switch x1Encrypted to
             * the next parameters in the modulus switching chain. However, since we still
             * need to multiply the x^3 term with PI (plainCoeff3), we instead compute PI*x
             * first and multiply that with x^2 to obtain PI*x^3. To this end, we compute
             * PI*x and rescale it back from scale 2^80 to something close to 2^40.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute and rescale PI*x.");
            using Ciphertext x1EncryptedCoeff3 = new Ciphertext();
            evaluator.MultiplyPlain(x1Encrypted, plainCoeff3, x1EncryptedCoeff3);
            Console.WriteLine("    + Scale of PI*x before rescale: {0} bits",
                              Math.Log(x1EncryptedCoeff3.Scale, newBase: 2));
            evaluator.RescaleToNextInplace(x1EncryptedCoeff3);
            Console.WriteLine("    + Scale of PI*x after rescale: {0} bits",
                              Math.Log(x1EncryptedCoeff3.Scale, newBase: 2));

            /*
             * Since x3Encrypted and x1EncryptedCoeff3 have the same exact scale and use
             * the same encryption parameters, we can multiply them together. We write the
             * result to x3Encrypted, relinearize, and rescale. Note that again the scale
             * is something close to 2^40, but not exactly 2^40 due to yet another scaling
             * by a prime. We are down to the last level in the modulus switching chain.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute, relinearize, and rescale (PI*x)*x^2.");
            evaluator.MultiplyInplace(x3Encrypted, x1EncryptedCoeff3);
            evaluator.RelinearizeInplace(x3Encrypted, relinKeys);
            Console.WriteLine("    + Scale of PI*x^3 before rescale: {0} bits",
                              Math.Log(x3Encrypted.Scale, newBase: 2));
            evaluator.RescaleToNextInplace(x3Encrypted);
            Console.WriteLine("    + Scale of PI*x^3 after rescale: {0} bits",
                              Math.Log(x3Encrypted.Scale, newBase: 2));

            /*
             * Next we compute the degree one term. All this requires is one MultiplyPlain
             * with plainCoeff1. We overwrite x1Encrypted with the result.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute and rescale 0.4*x.");
            evaluator.MultiplyPlainInplace(x1Encrypted, plainCoeff1);
            Console.WriteLine("    + Scale of 0.4*x before rescale: {0} bits",
                              Math.Log(x1Encrypted.Scale, newBase: 2));
            evaluator.RescaleToNextInplace(x1Encrypted);
            Console.WriteLine("    + Scale of 0.4*x after rescale: {0} bits",
                              Math.Log(x1Encrypted.Scale, newBase: 2));

            /*
             * Now we would hope to compute the sum of all three terms. However, there is
             * a serious problem: the encryption parameters used by all three terms are
             * different due to modulus switching from rescaling.
             *
             * Encrypted addition and subtraction require that the scales of the inputs are
             * the same, and also that the encryption parameters (ParmsId) match. If there
             * is a mismatch, Evaluator will throw an exception.
             */
            Console.WriteLine();
            Utilities.PrintLine();
            Console.WriteLine("Parameters used by all three terms are different:");
            Console.WriteLine("    + Modulus chain index for x3Encrypted: {0}",
                              context.GetContextData(x3Encrypted.ParmsId).ChainIndex);
            Console.WriteLine("    + Modulus chain index for x1Encrypted: {0}",
                              context.GetContextData(x1Encrypted.ParmsId).ChainIndex);
            Console.WriteLine("    + Modulus chain index for plainCoeff0: {0}",
                              context.GetContextData(plainCoeff0.ParmsId).ChainIndex);
            Console.WriteLine();

            /*
             * Let us carefully consider what the scales are at this point. We denote the
             * primes in coeff_modulus as P_0, P_1, P_2, P_3, in this order. P_3 is used as
             * the special modulus and is not involved in rescalings. After the computations
             * above the scales in ciphertexts are:
             *
             *  - Product x^2 has scale 2^80 and is at level 2;
             *  - Product PI*x has scale 2^80 and is at level 2;
             *  - We rescaled both down to scale 2^80/P2 and level 1;
             *  - Product PI*x^3 has scale (2^80/P_2)^2;
             *  - We rescaled it down to scale (2^80/P_2)^2/P_1 and level 0;
             *  - Product 0.4*x has scale 2^80;
             *  - We rescaled it down to scale 2^80/P_2 and level 1;
             *  - The contant term 1 has scale 2^40 and is at level 2.
             *
             * Although the scales of all three terms are approximately 2^40, their exact
             * values are different, hence they cannot be added together.
             */
            Utilities.PrintLine();
            Console.WriteLine("The exact scales of all three terms are different:");
            Console.WriteLine("    + Exact scale in PI*x^3: {0:0.0000000000}", x3Encrypted.Scale);
            Console.WriteLine("    + Exact scale in  0.4*x: {0:0.0000000000}", x1Encrypted.Scale);
            Console.WriteLine("    + Exact scale in      1: {0:0.0000000000}", plainCoeff0.Scale);
            Console.WriteLine();

            /*
             * There are many ways to fix this problem. Since P_2 and P_1 are really close
             * to 2^40, we can simply "lie" to Microsoft SEAL and set the scales to be the
             * same. For example, changing the scale of PI*x^3 to 2^40 simply means that we
             * scale the value of PI*x^3 by 2^120/(P_2^2*P_1), which is very close to 1.
             * This should not result in any noticeable error.
             *
             * Another option would be to encode 1 with scale 2^80/P_2, do a MultiplyPlain
             * with 0.4*x, and finally rescale. In this case we would need to additionally
             * make sure to encode 1 with appropriate encryption parameters (ParmsId).
             *
             * In this example we will use the first (simplest) approach and simply change
             * the scale of PI*x^3 and 0.4*x to 2^40.
             */
            Utilities.PrintLine();
            Console.WriteLine("Normalize scales to 2^40.");
            x3Encrypted.Scale = Math.Pow(2.0, 40);
            x1Encrypted.Scale = Math.Pow(2.0, 40);

            /*
             * We still have a problem with mismatching encryption parameters. This is easy
             * to fix by using traditional modulus switching (no rescaling). CKKS supports
             * modulus switching just like the BFV scheme, allowing us to switch away parts
             * of the coefficient modulus when it is simply not needed.
             */
            Utilities.PrintLine();
            Console.WriteLine("Normalize encryption parameters to the lowest level.");
            ParmsId lastParmsId = x3Encrypted.ParmsId;

            evaluator.ModSwitchToInplace(x1Encrypted, lastParmsId);
            evaluator.ModSwitchToInplace(plainCoeff0, lastParmsId);

            /*
             * All three ciphertexts are now compatible and can be added.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute PI*x^3 + 0.4*x + 1.");
            using Ciphertext encryptedResult = new Ciphertext();
            evaluator.Add(x3Encrypted, x1Encrypted, encryptedResult);
            evaluator.AddPlainInplace(encryptedResult, plainCoeff0);

            /*
             * First print the true result.
             */
            using Plaintext plainResult = new Plaintext();
            Utilities.PrintLine();
            Console.WriteLine("Decrypt and decode PI * x ^ 3 + 0.4x + 1.");
            Console.WriteLine("    + Expected result:");
            List <double> trueResult = new List <double>(input.Count);

            foreach (double x in input)
            {
                trueResult.Add((3.14159265 * x * x + 0.4) * x + 1);
            }
            Utilities.PrintVector(trueResult, 3, 7);

            /*
             * We decrypt, decode, and print the result.
             */
            decryptor.Decrypt(encryptedResult, plainResult);
            List <double> result = new List <double>();

            encoder.Decode(plainResult, result);
            Console.WriteLine("    + Computed result ...... Correct.");
            Utilities.PrintVector(result, 3, 7);

            /*
             * While we did not show any computations on complex numbers in these examples,
             * the CKKSEncoder would allow us to have done that just as easily. Additions
             * and multiplications of complex numbers behave just as one would expect.
             */
        }
示例#12
0
        // Function for classification of samples
        // I follow the SEAL eamples recomandations to rescale and relinearize after each calculation.
        // useRelinearizeInplace and useReScale should be always true.
        // This parametrs are enabled only for debugging and learning purpose.
        public Ciphertext  Predict(Ciphertext featuresCiphertexts, bool useRelinearizeInplace, bool useReScale,
                                   Stopwatch innerProductStopwatch, Stopwatch degreeStopwatch, Stopwatch negateStopwatch, Stopwatch serverDecisionStopWatch)
        {
            Ciphertext tempCt = new Ciphertext();

            // Level 1
            for (int i = 0; i < _numOfrowsCount; i++)
            {
                //inner product
                //calculate IP = < x, x'>
                innerProductStopwatch.Start();
                if (UseBatchInnerProduct)
                {
                    _kernels[i] = InnerProduct(featuresCiphertexts, _svPlaintexts, i, _sums, _numOfcolumnsCount, tempCt);
                }


                innerProductStopwatch.Stop();
                SvcUtilities.PrintCyprherText(_decryptor, _kernels[i], _encoder, $"inner product TotalValue {i}");
                SvcUtilities.PrintScale(_kernels[i], "0. kernels" + i);
                if (useRelinearizeInplace)
                {
                    _evaluator.RelinearizeInplace(_kernels[i], _relinKeys);
                }

                if (useReScale)
                {
                    _evaluator.RescaleToNextInplace(_kernels[i]);
                }

                SvcUtilities.PrintScale(_kernels[i], "1. kernels" + i);
                _kernels[i].Scale = _scale;

                //For polynimial kernel calculate
                if (_kernel == Kernel.Poly)
                {
                    // calculate (y *IP+r)^d
                    // IP is calculated previously
                    // y = gamma
                    // r = _coef0
                    if (useReScale)
                    {
                        ParmsId lastParmsId = _kernels[i].ParmsId;
                        _evaluator.ModSwitchToInplace(_gamaPlaintext, lastParmsId);
                    }
                    //calculate y * IP
                    _evaluator.MultiplyPlainInplace(_kernels[i], _gamaPlaintext);
                    SvcUtilities.PrintScale(_kernels[i], "2. kernels" + i);
                    if (useRelinearizeInplace)
                    {
                        _evaluator.RelinearizeInplace(_kernels[i], _relinKeys);
                    }

                    if (useReScale)
                    {
                        _evaluator.RescaleToNextInplace(_kernels[i]);
                    }
                    SvcUtilities.PrintScale(_kernels[i], "3.  kernels" + i);

                    // add r
                    if (Math.Abs(_coef0) > 0)
                    {
                        Plaintext coef0Plaintext = new Plaintext();
                        _encoder.Encode(_coef0, _kernels[i].Scale, coef0Plaintext);
                        if (useReScale)
                        {
                            ParmsId lastParmsId = _kernels[i].ParmsId;
                            _evaluator.ModSwitchToInplace(coef0Plaintext, lastParmsId);
                        }

                        //kernels[i].Scale = coef0Plaintext.Scale;

                        _evaluator.AddPlainInplace(_kernels[i], coef0Plaintext);
                    }

                    SvcUtilities.PrintScale(_kernels[i], "4.  kernels" + i);
                    degreeStopwatch.Start();
                    // calculate the polynom degree
                    var kernel = new Ciphertext(_kernels[i]);
                    for (int d = 0; d < (int)_degree - 1; d++)
                    {
                        kernel.Scale = _kernels[i].Scale;
                        if (useReScale)
                        {
                            ParmsId lastParmsId = _kernels[i].ParmsId;
                            _evaluator.ModSwitchToInplace(kernel, lastParmsId);
                        }
                        _evaluator.MultiplyInplace(_kernels[i], kernel);
                        SvcUtilities.PrintScale(_kernels[i], d + "  5. kernels" + i);
                        if (useRelinearizeInplace)
                        {
                            _evaluator.RelinearizeInplace(_kernels[i], _relinKeys);
                        }

                        if (useReScale)
                        {
                            _evaluator.RescaleToNextInplace(_kernels[i]);
                        }
                        SvcUtilities.PrintScale(_kernels[i], d + " rescale  6. kernels" + i);
                    }
                    SvcUtilities.PrintScale(_kernels[i], "7. kernels" + i);
                    degreeStopwatch.Stop();
                }

                negateStopwatch.Start();

                _evaluator.NegateInplace(_kernels[i]);
                negateStopwatch.Stop();

                SvcUtilities.PrintScale(_kernels[i], "8. kernel" + i);

                SvcUtilities.PrintCyprherText(_decryptor, _kernels[i], _encoder, "kernel" + i);
            }
            serverDecisionStopWatch.Start();
            // Encode coefficients : ParmsId! , scale!
            double scale2 = Math.Pow(2.0, _power);

            if (useReScale)
            {
                scale2 = _kernels[0].Scale;
            }

            for (int i = 0; i < _numOfrowsCount; i++)
            {
                _encoder.Encode(_coefficients[0][i], scale2, _coefArr[i]);
                SvcUtilities.PrintScale(_coefArr[i], "coefPlainText" + i);
            }

            if (useReScale)
            {
                for (int i = 0; i < _numOfrowsCount; i++)
                {
                    ParmsId lastParmsId = _kernels[i].ParmsId;
                    _evaluator.ModSwitchToInplace(_coefArr[i], lastParmsId);
                }
            }
            // Level 2
            // Calculate decisionArr
            for (int i = 0; i < _numOfrowsCount; i++)
            {
                _evaluator.MultiplyPlain(_kernels[i], _coefArr[i], _decisionsArr[i]);
                if (useRelinearizeInplace)
                {
                    _evaluator.RelinearizeInplace(_decisionsArr[i], _relinKeys);
                }

                if (useReScale)
                {
                    _evaluator.RescaleToNextInplace(_decisionsArr[i]);
                }
                SvcUtilities.PrintScale(_decisionsArr[i], "decision" + i);
                SvcUtilities.PrintCyprherText(_decryptor, _decisionsArr[i], _encoder, "decision" + i);
            }



            // Calculate decisionTotal
            Ciphertext decisionTotal = new Ciphertext();

            //=================================================================
            _evaluator.AddMany(_decisionsArr, decisionTotal);
            //=================================================================

            SvcUtilities.PrintScale(decisionTotal, "decisionTotal");
            SvcUtilities.PrintCyprherText(_decryptor, decisionTotal, _encoder, "decision total");


            // Encode intercepts : ParmsId! , scale!
            Plaintext interceptsPlainText = new Plaintext();

            double scale3 = Math.Pow(2.0, _power * 3);

            if (useReScale)
            {
                scale3 = decisionTotal.Scale;
            }
            _encoder.Encode(_intercepts[0], scale3, interceptsPlainText);
            if (useReScale)
            {
                ParmsId lastParmsId = decisionTotal.ParmsId;
                _evaluator.ModSwitchToInplace(interceptsPlainText, lastParmsId);
            }

            SvcUtilities.PrintScale(interceptsPlainText, "interceptsPlainText");
            SvcUtilities.PrintScale(decisionTotal, "decisionTotal");


            //// Calculate finalTotal
            Ciphertext finalTotal = new Ciphertext();

            //=================================================================
            _evaluator.AddPlainInplace(decisionTotal, interceptsPlainText);
            //=================================================================

            SvcUtilities.PrintScale(decisionTotal, "decisionTotal");  //Level 3
            List <double> result = SvcUtilities.PrintCyprherText(_decryptor, decisionTotal, _encoder, "finalTotal", true);

            serverDecisionStopWatch.Stop();
            long innerProductMilliseconds = innerProductStopwatch.ElapsedMilliseconds;
            //Console.WriteLine($"server innerProductStopwatch elapsed {innerProductMilliseconds} ms");
            long negateMilliseconds = negateStopwatch.ElapsedMilliseconds;
            //Console.WriteLine($"server negateStopwatch elapsed {negateMilliseconds} ms");
            long degreeMilliseconds = degreeStopwatch.ElapsedMilliseconds;
            //Console.WriteLine($"server degreeStopwatch elapsed {degreeMilliseconds} ms");
            long serverDecisionMilliseconds = serverDecisionStopWatch.ElapsedMilliseconds;

            //Console.WriteLine($"server Decision elapsed {serverDecisionMilliseconds} ms");


            return(decisionTotal);
        }
            public int Predict(double[] features, int power, bool useRelinearizeInplace, bool useReScale, Stopwatch timePredictSum)
            {
                EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

                if (power < 60)
                {
                    ulong polyModulusDegree = 8192;
                    parms.PolyModulusDegree = polyModulusDegree;
                    parms.CoeffModulus      = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 40, 40, 60 });
                }
                else
                {
                    ulong polyModulusDegree = 16384;
                    parms.PolyModulusDegree = polyModulusDegree;
                    parms.CoeffModulus      = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 60, 60, 60, 60, 60 });
                }
                //

                double scale = Math.Pow(2.0, power);

                SEALContext context = new SEALContext(parms);

                Console.WriteLine();

                KeyGenerator keygen    = new KeyGenerator(context);
                PublicKey    publicKey = keygen.PublicKey;
                SecretKey    secretKey = keygen.SecretKey;
                RelinKeys    relinKeys = keygen.RelinKeys();
                Encryptor    encryptor = new Encryptor(context, publicKey);
                Evaluator    evaluator = new Evaluator(context);
                Decryptor    decryptor = new Decryptor(context, secretKey);

                CKKSEncoder encoder = new CKKSEncoder(context);

                ulong slotCount = encoder.SlotCount;

                Console.WriteLine($"Number of slots: {slotCount}");
                timePredictSum.Start();
                var featuresLength = features.Length;

                var plaintexts          = new Plaintext[featuresLength];
                var featuresCiphertexts = new Ciphertext[featuresLength];

                //Encode and encrypt features
                for (int i = 0; i < featuresLength; i++)
                {
                    plaintexts[i] = new Plaintext();

                    encoder.Encode(features[i], scale, plaintexts[i]);

                    SvcUtilities.PrintScale(plaintexts[i], "featurePlaintext" + i);
                    featuresCiphertexts[i] = new Ciphertext();

                    encryptor.Encrypt(plaintexts[i], featuresCiphertexts[i]);
                    SvcUtilities.PrintScale(featuresCiphertexts[i], "featurefEncrypted" + i);
                }

                // Handle SV
                var numOfrows    = _vectors.Length;
                var numOfcolumns = _vectors[0].Length;
                var svPlaintexts = new Plaintext[numOfrows, numOfcolumns];

                //Encode SV
                for (int i = 0; i < numOfrows; i++)
                {
                    for (int j = 0; j < numOfcolumns; j++)
                    {
                        svPlaintexts[i, j] = new Plaintext();
                        encoder.Encode(_vectors[i][j], scale, svPlaintexts[i, j]);
                        SvcUtilities.PrintScale(svPlaintexts[i, j], "supportVectorsPlaintext" + i + j);
                    }
                }
                // Prepare sum of inner product
                var sums = new Ciphertext[numOfcolumns];

                for (int i = 0; i < numOfcolumns; i++)
                {
                    sums[i] = new Ciphertext();
                }

                var kernels      = new Ciphertext[numOfrows];
                var decisionsArr = new Ciphertext[numOfrows];
                var coefArr      = new Plaintext [numOfrows];

                for (int i = 0; i < numOfrows; i++)
                {
                    kernels[i]      = new Ciphertext();
                    decisionsArr[i] = new Ciphertext();
                    coefArr[i]      = new Plaintext();
                }

                // Level 1
                for (int i = 0; i < numOfrows; i++)
                {
                    var ciphertexts = new List <Ciphertext>();

                    //inner product
                    for (int j = 0; j < numOfcolumns; j++)
                    {
                        evaluator.MultiplyPlain(featuresCiphertexts[j], svPlaintexts[i, j], sums[j]);

                        if (useRelinearizeInplace)
                        {
                            evaluator.RelinearizeInplace(sums[j], relinKeys);
                        }

                        if (useReScale)
                        {
                            evaluator.RescaleToNextInplace(sums[j]);
                        }

                        SvcUtilities.PrintScale(sums[j], "tSum" + j);
                    }

                    evaluator.AddMany(sums, kernels[i]);

                    evaluator.NegateInplace(kernels[i]);

                    SvcUtilities.PrintScale(kernels[i], "kernel" + i);

                    SvcUtilities.PrintCyprherText(decryptor, kernels[i], encoder, "kernel" + i);
                }

                // Encode coefficients : ParmsId! , scale!
                double scale2 = Math.Pow(2.0, power);

                if (useReScale)
                {
                    scale2 = kernels[0].Scale;
                }

                for (int i = 0; i < numOfrows; i++)
                {
                    encoder.Encode(_coefficients[0][i], scale2, coefArr[i]);
                    SvcUtilities.PrintScale(coefArr[i], "coefPlainText+i");
                }



                if (useReScale)
                {
                    for (int i = 0; i < numOfrows; i++)
                    {
                        ParmsId lastParmsId = kernels[i].ParmsId;
                        evaluator.ModSwitchToInplace(coefArr[i], lastParmsId);
                    }
                }
                // Level 2
                // Calculate decisionArr
                for (int i = 0; i < numOfrows; i++)
                {
                    evaluator.MultiplyPlain(kernels[i], coefArr[i], decisionsArr[i]);
                    if (useRelinearizeInplace)
                    {
                        evaluator.RelinearizeInplace(decisionsArr[i], relinKeys);
                    }

                    if (useReScale)
                    {
                        evaluator.RescaleToNextInplace(decisionsArr[i]);
                    }
                    SvcUtilities.PrintScale(decisionsArr[i], "decision" + i);
                    SvcUtilities.PrintCyprherText(decryptor, decisionsArr[i], encoder, "decision" + i);
                }



                // Calculate decisionTotal
                Ciphertext decisionTotal = new Ciphertext();

                //=================================================================
                evaluator.AddMany(decisionsArr, decisionTotal);
                //=================================================================

                SvcUtilities.PrintScale(decisionTotal, "decisionTotal");
                SvcUtilities.PrintCyprherText(decryptor, decisionTotal, encoder, "decision total");


                // Encode intercepts : ParmsId! , scale!
                Plaintext interceptsPlainText = new Plaintext();

                double scale3 = Math.Pow(2.0, power * 3);

                if (useReScale)
                {
                    scale3 = decisionTotal.Scale;
                }
                encoder.Encode(_intercepts[0], scale3, interceptsPlainText);
                if (useReScale)
                {
                    ParmsId lastParmsId = decisionTotal.ParmsId;
                    evaluator.ModSwitchToInplace(interceptsPlainText, lastParmsId);
                }

                SvcUtilities.PrintScale(interceptsPlainText, "interceptsPlainText");
                SvcUtilities.PrintScale(decisionTotal, "decisionTotal");


                //// Calculate finalTotal
                Ciphertext finalTotal = new Ciphertext();

                //=================================================================
                evaluator.AddPlainInplace(decisionTotal, interceptsPlainText);
                //=================================================================
                timePredictSum.Stop();
                SvcUtilities.PrintScale(decisionTotal, "decisionTotal");  //Level 3
                List <double> result = SvcUtilities.PrintCyprherText(decryptor, decisionTotal, encoder, "finalTotal");

                using (System.IO.StreamWriter file =
                           new System.IO.StreamWriter(
                               $@"{OutputDir}IrisLinear_IrisSecureSVC_total_{power}_{useRelinearizeInplace}_{useReScale}.txt", !_firstTime)
                       )
                {
                    _firstTime = false;
                    file.WriteLine($"{result[0]}");
                }

                if (result[0] > 0)
                {
                    return(0);
                }

                return(1);
            }
        public void EncryptZeroTest()
        {
            {
                SEALContext  context   = GlobalContext.BFVContext;
                KeyGenerator keyGen    = new KeyGenerator(context);
                PublicKey    publicKey = keyGen.PublicKey;
                SecretKey    secretKey = keyGen.SecretKey;
                Encryptor    encryptor = new Encryptor(context, publicKey, secretKey);
                Decryptor    decryptor = new Decryptor(context, secretKey);

                Assert.IsNotNull(encryptor);
                Assert.IsNotNull(decryptor);

                Ciphertext cipher    = new Ciphertext();
                Plaintext  plain     = new Plaintext();
                ParmsId    nextParms = context.FirstContextData.NextContextData.ParmsId;

                {
                    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.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.EncryptZeroSymmetricSave(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.EncryptZeroSymmetricSave(nextParms, 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;
                Encryptor    encryptor = new Encryptor(context, publicKey, secretKey);
                Decryptor    decryptor = new Decryptor(context, secretKey);
                CKKSEncoder  encoder   = new CKKSEncoder(context);

                Assert.IsNotNull(encryptor);
                Assert.IsNotNull(decryptor);

                Ciphertext     cipher    = new Ciphertext();
                Plaintext      plain     = new Plaintext();
                ParmsId        nextParms = context.FirstContextData.NextContextData.ParmsId;
                List <Complex> res       = new List <Complex>();

                {
                    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.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.EncryptZeroSymmetricSave(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.EncryptZeroSymmetricSave(nextParms, 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);
                    }
                }
            }
        }
示例#15
0
            public int Predict(double[] features, int power, bool useRelinearizeInplace, bool useReScale, Stopwatch timePredictSum)
            {
                EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

                if (power < 60)
                {
                    ulong polyModulusDegree = 8192;
                    parms.PolyModulusDegree = polyModulusDegree;
                    parms.CoeffModulus      = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 40, 40, 60 });
                }
                else
                {
                    ulong polyModulusDegree = 16384;
                    parms.PolyModulusDegree = polyModulusDegree;
                    parms.CoeffModulus      = CoeffModulus.Create(polyModulusDegree, new int[] { 60, 60, 60, 60, 60, 60 });
                }
                //

                double scale = Math.Pow(2.0, power);

                SEALContext context = new SEALContext(parms);

                Console.WriteLine();

                KeyGenerator keygen    = new KeyGenerator(context);
                PublicKey    publicKey = keygen.PublicKey;
                SecretKey    secretKey = keygen.SecretKey;
                RelinKeys    relinKeys = keygen.RelinKeys();
                Encryptor    encryptor = new Encryptor(context, publicKey);
                Evaluator    evaluator = new Evaluator(context);
                Decryptor    decryptor = new Decryptor(context, secretKey);

                CKKSEncoder encoder = new CKKSEncoder(context);

                ulong slotCount = encoder.SlotCount;

                Console.WriteLine($"Number of slots: {slotCount}");

                timePredictSum.Start();
                Plaintext fPlaintext0 = new Plaintext();
                Plaintext fPlaintext1 = new Plaintext();
                Plaintext fPlaintext2 = new Plaintext();
                Plaintext fPlaintext3 = new Plaintext();


                encoder.Encode(features[0], scale, fPlaintext0);
                encoder.Encode(features[1], scale, fPlaintext1);
                encoder.Encode(features[2], scale, fPlaintext2);
                encoder.Encode(features[3], scale, fPlaintext3);


                SvcUtilities.PrintScale(fPlaintext0, "fPlaintext0");
                SvcUtilities.PrintScale(fPlaintext1, "fPlaintext1");
                SvcUtilities.PrintScale(fPlaintext2, "fPlaintext2");

                Ciphertext f0Encrypted = new Ciphertext();
                Ciphertext f1Encrypted = new Ciphertext();
                Ciphertext f2Encrypted = new Ciphertext();
                Ciphertext f3Encrypted = new Ciphertext();

                encryptor.Encrypt(fPlaintext0, f0Encrypted);
                encryptor.Encrypt(fPlaintext1, f1Encrypted);
                encryptor.Encrypt(fPlaintext2, f2Encrypted);
                encryptor.Encrypt(fPlaintext3, f3Encrypted);

                SvcUtilities.PrintScale(f0Encrypted, "f0Encrypted");
                SvcUtilities.PrintScale(f1Encrypted, "f1Encrypted");
                SvcUtilities.PrintScale(f2Encrypted, "f2Encrypted");

                Plaintext v00Plaintext1 = new Plaintext();
                Plaintext v01Plaintext1 = new Plaintext();
                Plaintext v02Plaintext1 = new Plaintext();
                Plaintext v03Plaintext1 = new Plaintext();
                Plaintext v10Plaintext1 = new Plaintext();
                Plaintext v11Plaintext1 = new Plaintext();
                Plaintext v12Plaintext1 = new Plaintext();
                Plaintext v13Plaintext1 = new Plaintext();

                Plaintext v20Plaintext1 = new Plaintext();
                Plaintext v21Plaintext1 = new Plaintext();
                Plaintext v22Plaintext1 = new Plaintext();
                Plaintext v23Plaintext1 = new Plaintext();


                encoder.Encode(_vectors[0][0], scale, v00Plaintext1);
                encoder.Encode(_vectors[0][1], scale, v01Plaintext1);
                encoder.Encode(_vectors[0][2], scale, v02Plaintext1);
                encoder.Encode(_vectors[0][3], scale, v03Plaintext1);
                encoder.Encode(_vectors[1][0], scale, v10Plaintext1);
                encoder.Encode(_vectors[1][1], scale, v11Plaintext1);
                encoder.Encode(_vectors[1][2], scale, v12Plaintext1);
                encoder.Encode(_vectors[1][3], scale, v13Plaintext1);
                encoder.Encode(_vectors[2][0], scale, v20Plaintext1);
                encoder.Encode(_vectors[2][1], scale, v21Plaintext1);
                encoder.Encode(_vectors[2][2], scale, v22Plaintext1);
                encoder.Encode(_vectors[2][3], scale, v23Plaintext1);


                SvcUtilities.PrintScale(v00Plaintext1, "v00Plaintext1");
                SvcUtilities.PrintScale(v01Plaintext1, "v01Plaintext1");
                SvcUtilities.PrintScale(v02Plaintext1, "v02Plaintext1");
                SvcUtilities.PrintScale(v03Plaintext1, "v03Plaintext1");

                SvcUtilities.PrintScale(v10Plaintext1, "v10Plaintext1");
                SvcUtilities.PrintScale(v11Plaintext1, "v11Plaintext1");
                SvcUtilities.PrintScale(v12Plaintext1, "v12Plaintext1");
                SvcUtilities.PrintScale(v13Plaintext1, "v13Plaintext1");

                SvcUtilities.PrintScale(v20Plaintext1, "v20Plaintext1");
                SvcUtilities.PrintScale(v21Plaintext1, "v21Plaintext1");
                SvcUtilities.PrintScale(v22Plaintext1, "v22Plaintext1");
                SvcUtilities.PrintScale(v23Plaintext1, "v23Plaintext1");

                Plaintext coef00PlainText = new Plaintext();
                Plaintext coef01PlainText = new Plaintext();
                Plaintext coef02PlainText = new Plaintext();


                Ciphertext tSum1   = new Ciphertext();
                Ciphertext tSum2   = new Ciphertext();
                Ciphertext tSum3   = new Ciphertext();
                Ciphertext tSum4   = new Ciphertext();
                Ciphertext kernel0 = new Ciphertext();

                //Level 1->2
                //=================================================================
                evaluator.MultiplyPlain(f0Encrypted, v00Plaintext1, tSum1);
                evaluator.MultiplyPlain(f1Encrypted, v01Plaintext1, tSum2);
                evaluator.MultiplyPlain(f2Encrypted, v02Plaintext1, tSum3);
                evaluator.MultiplyPlain(f3Encrypted, v03Plaintext1, tSum4);
                //=================================================================

                if (useRelinearizeInplace)
                {
                    Console.WriteLine("RelinearizeInplace sums 1");
                    evaluator.RelinearizeInplace(tSum1, relinKeys);
                    evaluator.RelinearizeInplace(tSum2, relinKeys);
                    evaluator.RelinearizeInplace(tSum3, relinKeys);
                    evaluator.RelinearizeInplace(tSum4, relinKeys);
                }

                if (useReScale)
                {
                    Console.WriteLine("useReScale sums 1");
                    evaluator.RescaleToNextInplace(tSum1);
                    evaluator.RescaleToNextInplace(tSum2);
                    evaluator.RescaleToNextInplace(tSum3);
                    evaluator.RescaleToNextInplace(tSum4);
                }


                SvcUtilities.PrintScale(tSum1, "tSum1"); //Level 2
                SvcUtilities.PrintScale(tSum2, "tSum2"); //Level 2
                SvcUtilities.PrintScale(tSum3, "tSum3"); //Level 2
                SvcUtilities.PrintScale(tSum4, "tSum4"); //Level 2

                var ciphertexts1 = new List <Ciphertext>();

                ciphertexts1.Add(tSum1);
                ciphertexts1.Add(tSum2);
                ciphertexts1.Add(tSum3);
                ciphertexts1.Add(tSum4);

                //=================================================================
                evaluator.AddMany(ciphertexts1, kernel0);    //Level 2
                //=================================================================
                SvcUtilities.PrintScale(kernel0, "kernel0"); //Level 2

                SvcUtilities.PrintCyprherText(decryptor, kernel0, encoder, "kernel0");

                Ciphertext kernel1 = new Ciphertext();

                //Level 1-> 2
                //=================================================================
                evaluator.MultiplyPlain(f0Encrypted, v10Plaintext1, tSum1);
                evaluator.MultiplyPlain(f1Encrypted, v11Plaintext1, tSum2);
                evaluator.MultiplyPlain(f2Encrypted, v12Plaintext1, tSum3);
                evaluator.MultiplyPlain(f3Encrypted, v13Plaintext1, tSum4);
                //=================================================================
                if (useRelinearizeInplace)
                {
                    Console.WriteLine("RelinearizeInplace sums 2");
                    evaluator.RelinearizeInplace(tSum1, relinKeys);
                    evaluator.RelinearizeInplace(tSum2, relinKeys);
                    evaluator.RelinearizeInplace(tSum3, relinKeys);
                    evaluator.RelinearizeInplace(tSum4, relinKeys);
                }

                if (useReScale)
                {
                    Console.WriteLine("useReScale sums 2");
                    evaluator.RescaleToNextInplace(tSum1);
                    evaluator.RescaleToNextInplace(tSum2);
                    evaluator.RescaleToNextInplace(tSum3);
                    evaluator.RescaleToNextInplace(tSum4);
                }

                ciphertexts1.Add(tSum1);
                ciphertexts1.Add(tSum2);
                ciphertexts1.Add(tSum3);
                ciphertexts1.Add(tSum4);



                Console.WriteLine("Second time : ");
                SvcUtilities.PrintScale(tSum1, "tSum1"); //Level 2
                SvcUtilities.PrintScale(tSum2, "tSum2"); //Level 2
                SvcUtilities.PrintScale(tSum3, "tSum3"); //Level 2
                SvcUtilities.PrintScale(tSum4, "tSum4"); //Level 2

                var ciphertexts2 = new List <Ciphertext>();

                ciphertexts2.Add(tSum1);
                ciphertexts2.Add(tSum2);
                ciphertexts2.Add(tSum3);
                ciphertexts2.Add(tSum4);


                //=================================================================
                evaluator.AddMany(ciphertexts2, kernel1); // Level 2
                //=================================================================
                SvcUtilities.PrintScale(kernel1, "kernel1");
                SvcUtilities.PrintCyprherText(decryptor, kernel1, encoder, "kernel1");

                Ciphertext kernel2 = new Ciphertext();

                //Level 1->2
                //=================================================================
                evaluator.MultiplyPlain(f0Encrypted, v20Plaintext1, tSum1);
                evaluator.MultiplyPlain(f1Encrypted, v21Plaintext1, tSum2);
                evaluator.MultiplyPlain(f2Encrypted, v22Plaintext1, tSum3);
                evaluator.MultiplyPlain(f3Encrypted, v23Plaintext1, tSum4);
                //=================================================================

                if (useRelinearizeInplace)
                {
                    Console.WriteLine("RelinearizeInplace sums 3");
                    evaluator.RelinearizeInplace(tSum1, relinKeys);
                    evaluator.RelinearizeInplace(tSum2, relinKeys);
                    evaluator.RelinearizeInplace(tSum3, relinKeys);
                    evaluator.RelinearizeInplace(tSum4, relinKeys);
                }



                if (useReScale)
                {
                    Console.WriteLine("useReScale sums 3");
                    evaluator.RescaleToNextInplace(tSum1);
                    evaluator.RescaleToNextInplace(tSum2);
                    evaluator.RescaleToNextInplace(tSum3);
                    evaluator.RescaleToNextInplace(tSum4);
                }

                var ciphertexts3 = new List <Ciphertext>();

                ciphertexts3.Add(tSum1);
                ciphertexts3.Add(tSum2);
                ciphertexts3.Add(tSum3);
                ciphertexts3.Add(tSum4);

                Console.WriteLine("Third time : ");
                SvcUtilities.PrintScale(tSum1, "tSum1"); //Level 2
                SvcUtilities.PrintScale(tSum2, "tSum2"); //Level 2
                SvcUtilities.PrintScale(tSum3, "tSum3"); //Level 2
                SvcUtilities.PrintScale(tSum4, "tSum4"); //Level 2

                //=================================================================
                evaluator.AddMany(ciphertexts3, kernel2);
                //=================================================================
                SvcUtilities.PrintScale(kernel2, "kernel2"); //Level 2

                SvcUtilities.PrintCyprherText(decryptor, kernel2, encoder, "kernel2");

                Ciphertext decision1 = new Ciphertext();
                Ciphertext decision2 = new Ciphertext();
                Ciphertext decision3 = new Ciphertext();

                SvcUtilities.PrintScale(decision1, "decision1"); //Level 0
                SvcUtilities.PrintScale(decision2, "decision2"); //Level 0
                SvcUtilities.PrintScale(decision3, "decision3"); //Level 0


                Ciphertext nKernel0 = new Ciphertext();
                Ciphertext nKernel1 = new Ciphertext();
                Ciphertext nKernel2 = new Ciphertext();

                //=================================================================
                evaluator.Negate(kernel0, nKernel0);
                evaluator.Negate(kernel1, nKernel1); //Level 2
                evaluator.Negate(kernel2, nKernel2); //Level 2
                //=================================================================



                //nKernel0.Scale = scale;
                //nKernel1.Scale = scale;
                //nKernel2.Scale = scale;
                double scale2 = Math.Pow(2.0, power);

                if (useReScale)
                {
                    scale2 = nKernel0.Scale;
                }

                encoder.Encode(_coefficients[0][0], scale2, coef00PlainText);
                encoder.Encode(_coefficients[0][1], scale2, coef01PlainText);
                encoder.Encode(_coefficients[0][2], scale2, coef02PlainText);

                SvcUtilities.PrintScale(coef00PlainText, "coef00PlainText");
                SvcUtilities.PrintScale(coef01PlainText, "coef01PlainText");
                SvcUtilities.PrintScale(coef02PlainText, "coef02PlainText");



                if (useReScale)
                {
                    ParmsId lastParmsId = nKernel0.ParmsId;
                    evaluator.ModSwitchToInplace(coef00PlainText, lastParmsId);


                    lastParmsId = nKernel1.ParmsId;
                    evaluator.ModSwitchToInplace(coef01PlainText, lastParmsId);

                    lastParmsId = nKernel2.ParmsId;
                    evaluator.ModSwitchToInplace(coef02PlainText, lastParmsId);
                }

                SvcUtilities.PrintScale(nKernel0, "nKernel0");   //Level 2
                SvcUtilities.PrintScale(nKernel1, "nKernel1");   //Level 2
                SvcUtilities.PrintScale(nKernel2, "nKernel2");   //Level 2

                //Level 2->3
                //=================================================================
                evaluator.MultiplyPlain(nKernel0, coef00PlainText, decision1);
                evaluator.MultiplyPlain(nKernel1, coef01PlainText, decision2);
                evaluator.MultiplyPlain(nKernel2, coef02PlainText, decision3);
                //=================================================================



                if (useRelinearizeInplace)
                {
                    Console.WriteLine("RelinearizeInplace decisions");

                    evaluator.RelinearizeInplace(decision1, relinKeys);
                    evaluator.RelinearizeInplace(decision2, relinKeys);
                    evaluator.RelinearizeInplace(decision3, relinKeys);
                }


                if (useReScale)
                {
                    Console.WriteLine("Rescale decisions");

                    evaluator.RescaleToNextInplace(decision1);
                    evaluator.RescaleToNextInplace(decision2);
                    evaluator.RescaleToNextInplace(decision3);
                }


                SvcUtilities.PrintScale(decision1, "decision1"); //Level 3
                SvcUtilities.PrintScale(decision2, "decision2"); //Level 3
                SvcUtilities.PrintScale(decision3, "decision3"); //Level 3
                SvcUtilities.PrintCyprherText(decryptor, decision1, encoder, "decision1");
                SvcUtilities.PrintCyprherText(decryptor, decision2, encoder, "decision2");
                SvcUtilities.PrintCyprherText(decryptor, decision3, encoder, "decision3");

                //=================================================================
                //evaluator.RelinearizeInplace(decision1,keygen.RelinKeys());
                //evaluator.RelinearizeInplace(decision2, keygen.RelinKeys());
                //evaluator.RelinearizeInplace(decision3, keygen.RelinKeys());
                //=================================================================


                //PrintScale(decision1, "decision1");

                var decisions = new List <Ciphertext>();

                decisions.Add(decision1);
                decisions.Add(decision2);
                decisions.Add(decision3);

                Ciphertext decisionTotal = new Ciphertext();

                //=================================================================
                evaluator.AddMany(decisions, decisionTotal);
                //=================================================================
                SvcUtilities.PrintScale(decisionTotal, "decisionTotal");
                SvcUtilities.PrintCyprherText(decryptor, decisionTotal, encoder, "decision total");


                Ciphertext finalTotal = new Ciphertext();

                Plaintext interceptsPlainText = new Plaintext();

                double scale3 = Math.Pow(2.0, power * 3);

                if (useReScale)
                {
                    scale3 = decisionTotal.Scale;
                }
                encoder.Encode(_intercepts[0], scale3, interceptsPlainText);
                if (useReScale)
                {
                    ParmsId lastParmsId = decisionTotal.ParmsId;
                    evaluator.ModSwitchToInplace(interceptsPlainText, lastParmsId);
                }

                SvcUtilities.PrintScale(interceptsPlainText, "interceptsPlainText");
                SvcUtilities.PrintScale(decisionTotal, "decisionTotal");

                //=================================================================
                evaluator.AddPlainInplace(decisionTotal, interceptsPlainText);
                //=================================================================
                timePredictSum.Stop();
                SvcUtilities.PrintScale(decisionTotal, "decisionTotal");  //Level 3
                List <double> result = SvcUtilities.PrintCyprherText(decryptor, decisionTotal, encoder, "finalTotal");

                using (System.IO.StreamWriter file =
                           new System.IO.StreamWriter(
                               $@"{OutputDir}IrisSimple_IrisSecureSVC_total_{power}_{useRelinearizeInplace}_{useReScale}.txt", !_firstTime)
                       )
                {
                    _firstTime = false;
                    file.WriteLine($"{result[0]}");
                }

                if (result[0] > 0)
                {
                    return(0);
                }

                return(1);
            }
示例#16
0
			public int Predict(double[] features, bool useRelinearizeInplace,bool useReScale,out double finalResult)
			{

			   
				Console.WriteLine();

				ulong slotCount = _encoder.SlotCount;
				
				//Console.WriteLine($"Number of slots: {slotCount}");

				var featuresLength = features.Length;



				var plaintexts  = new Plaintext();
				var featuresCiphertexts = new Ciphertext();
				
				Stopwatch clientStopwatch = new Stopwatch();
				clientStopwatch.Start();
                //Encode and encrypt features
                double scale = Math.Pow(2.0, _power);
				_encoder.Encode(features, scale, plaintexts);
				_encryptor.Encrypt(plaintexts, featuresCiphertexts);
				SvcUtilities.PrintScale(plaintexts, "featurePlaintext");
				SvcUtilities.PrintScale(featuresCiphertexts, "featurefEncrypted");
				clientStopwatch.Stop();


				Stopwatch serverInitStopwatch = new Stopwatch();
				serverInitStopwatch.Start();
                // Handle SV
                var numOfrowsCount    = _vectors.Length;
				var numOfcolumnsCount = _vectors[0].Length;
		   
				var svPlaintexts = new Plaintext[numOfrowsCount];



                //Encode SV
                var sums = new Ciphertext[numOfrowsCount];
                for (int i = 0; i < numOfrowsCount; i++)
				{
						svPlaintexts[i] = new Plaintext();
						_encoder.Encode(_vectors[i], scale, svPlaintexts[i]);
						SvcUtilities.PrintScale(svPlaintexts[i], "supportVectorsPlaintext"+i);
						sums[i] = new Ciphertext();
                }

				var kernels      = new Ciphertext[numOfrowsCount];
				var decisionsArr = new Ciphertext[numOfrowsCount];
				var coefArr      = new Plaintext [numOfrowsCount];

				for (int i = 0; i < numOfrowsCount; i++)
				{
					kernels[i]       = new Ciphertext();
					decisionsArr[i]  = new Ciphertext();
					coefArr[i]       = new Plaintext();
				}
				Plaintext  gamaPlaintext= new Plaintext();
				_encoder.Encode(_gamma, scale, gamaPlaintext);

				Ciphertext tempCt = new Ciphertext();
				serverInitStopwatch.Stop();

				Stopwatch innerProductStopwatch = new Stopwatch();
                Stopwatch negateStopwatch = new Stopwatch();
                Stopwatch degreeStopwatch = new Stopwatch();
                // Level 1
                for (int i = 0; i < numOfrowsCount; i++)
				{
                    //Console.WriteLine(i);

                    //inner product
                  

                    innerProductStopwatch.Start();

                    _evaluator.MultiplyPlain(featuresCiphertexts, svPlaintexts[i],sums[i]);
                    int numOfRotations = (int)Math.Ceiling(Math.Log2(numOfcolumnsCount));

                    for (int k = 1,m=1; m <= numOfRotations/*(int)encoder.SlotCount/2*/; k <<= 1,m++)
                    {

                        _evaluator.RotateVector(sums[i], k, _galoisKeys, tempCt);
                        _evaluator.AddInplace(sums[i], tempCt);

                    }
                    innerProductStopwatch.Stop();
                    kernels[i] = sums[i];

                    SvcUtilities.PrintCyprherText(_decryptor, kernels[i], _encoder, $"inner product TotalValue {i}" );
                    SvcUtilities.PrintScale(kernels[i], "0. kernels" + i);
                    if (useRelinearizeInplace)
                    {
                        _evaluator.RelinearizeInplace(kernels[i], _relinKeys);
                    }

                    if (useReScale)
                    {
                        _evaluator.RescaleToNextInplace(kernels[i]);
                    }

                    SvcUtilities.PrintScale(kernels[i], "1. kernels" + i);
                    kernels[i].Scale = scale;


					if(_kernel == Kernel.Poly)
					{

						if (useReScale)
						{
							ParmsId lastParmsId = kernels[i].ParmsId;
							_evaluator.ModSwitchToInplace(gamaPlaintext, lastParmsId);
						}
						_evaluator.MultiplyPlainInplace(kernels[i], gamaPlaintext);
						SvcUtilities.PrintScale(kernels[i], "2. kernels" + i);
						if (useRelinearizeInplace)
						{
							_evaluator.RelinearizeInplace(kernels[i], _relinKeys);
						}

						if (useReScale)
						{
							_evaluator.RescaleToNextInplace(kernels[i]);
						}
						SvcUtilities.PrintScale(kernels[i], "3.  kernels" + i);

						if (Math.Abs(_coef0) > 0)
						{
							Plaintext coef0Plaintext = new Plaintext();
							_encoder.Encode(_coef0, kernels[i].Scale, coef0Plaintext);
							if (useReScale)
							{
								ParmsId lastParmsId = kernels[i].ParmsId;
								_evaluator.ModSwitchToInplace(coef0Plaintext, lastParmsId);
							}

							//kernels[i].Scale = coef0Plaintext.Scale;

							_evaluator.AddPlainInplace(kernels[i], coef0Plaintext);
                        }

                        SvcUtilities.PrintScale(kernels[i], "4.  kernels" + i);

                       

                        degreeStopwatch.Start();

                        var kernel = new Ciphertext(kernels[i]);
                        for (int d = 0; d < (int)_degree-1; d++)
						{

							kernel.Scale = kernels[i].Scale;
							if (useReScale)
							{
								ParmsId lastParmsId = kernels[i].ParmsId;
								_evaluator.ModSwitchToInplace(kernel, lastParmsId);
							}
                            _evaluator.MultiplyInplace(kernels[i], kernel);
							SvcUtilities.PrintScale(kernels[i], d + "  5. kernels" + i);
							if (useRelinearizeInplace)
							{
								_evaluator.RelinearizeInplace(kernels[i], _relinKeys);
							}

							if (useReScale)
							{
								_evaluator.RescaleToNextInplace(kernels[i]);
							}
							SvcUtilities.PrintScale(kernels[i], d + " rescale  6. kernels" + i);
						}
						SvcUtilities.PrintScale(kernels[i], "7. kernels" + i);

						degreeStopwatch.Stop();
                    }


					

					negateStopwatch.Start();

                    _evaluator.NegateInplace(kernels[i]);
                    negateStopwatch.Stop();

                    SvcUtilities.PrintScale(kernels[i], "8. kernel"+i); 

					SvcUtilities.PrintCyprherText(_decryptor, kernels[i], _encoder, "kernel"+i);

				}


                Stopwatch serverDecisionStopWatch = new Stopwatch();

                serverDecisionStopWatch.Start();

                // Encode coefficients : ParmsId! , scale!
                double scale2 = Math.Pow(2.0, _power);
				if (useReScale)
				{
					scale2 = kernels[0].Scale;
				}

				for (int i = 0; i < numOfrowsCount; i++)
				{
					_encoder.Encode(_coefficients[0][i], scale2, coefArr[i]);
					SvcUtilities.PrintScale(coefArr[i], "coefPlainText"+i);
				}



				if (useReScale)
				{
					for (int i = 0; i < numOfrowsCount; i++)
					{
						ParmsId lastParmsId = kernels[i].ParmsId;
						_evaluator.ModSwitchToInplace(coefArr[i], lastParmsId);
					}
				}
				// Level 2
				// Calculate decisionArr
                for (int i = 0; i < numOfrowsCount; i++)
				{
					_evaluator.MultiplyPlain(kernels[i], coefArr[i], decisionsArr[i]);
					if (useRelinearizeInplace)
					{
						_evaluator.RelinearizeInplace(decisionsArr[i], _relinKeys);
					}

					if (useReScale)
					{
						_evaluator.RescaleToNextInplace(decisionsArr[i]);
					}
					SvcUtilities.PrintScale(decisionsArr[i], "decision"+i);
					SvcUtilities.PrintCyprherText(_decryptor, decisionsArr[i], _encoder, "decision" + i);
				}



				// Calculate decisionTotal
				Ciphertext decisionTotal = new Ciphertext();
				//=================================================================
				_evaluator.AddMany(decisionsArr, decisionTotal);
				//=================================================================
			  
				SvcUtilities.PrintScale(decisionTotal, "decisionTotal"); 
				SvcUtilities.PrintCyprherText(_decryptor, decisionTotal, _encoder, "decision total");


				// Encode intercepts : ParmsId! , scale!
				Plaintext interceptsPlainText = new Plaintext();
				
				double scale3 = Math.Pow(2.0, _power*3);
				if (useReScale)
				{
					scale3 = decisionTotal.Scale;
				}
				_encoder.Encode(_intercepts[0], scale3, interceptsPlainText);
				if (useReScale)
				{
					ParmsId lastParmsId = decisionTotal.ParmsId;
					_evaluator.ModSwitchToInplace(interceptsPlainText, lastParmsId);
				}

				SvcUtilities.PrintScale(interceptsPlainText, "interceptsPlainText");
				SvcUtilities.PrintScale(decisionTotal, "decisionTotal");


				//// Calculate finalTotal
				Ciphertext finalTotal = new Ciphertext();

				//=================================================================
				_evaluator.AddPlainInplace(decisionTotal, interceptsPlainText);
				//=================================================================

				SvcUtilities.PrintScale(decisionTotal, "decisionTotal");  //Level 3
				List<double> result = SvcUtilities.PrintCyprherText(_decryptor, decisionTotal, _encoder, "finalTotal",true);

                serverDecisionStopWatch.Stop();

                Console.WriteLine($"client Init elapsed {clientStopwatch.ElapsedMilliseconds} ms");
                Console.WriteLine($"server Init elapsed {serverInitStopwatch.ElapsedMilliseconds} ms");
                Console.WriteLine($"server innerProductStopwatch elapsed {innerProductStopwatch.ElapsedMilliseconds} ms");
                Console.WriteLine($"server negateStopwatch elapsed {negateStopwatch.ElapsedMilliseconds} ms");
                Console.WriteLine($"server degreeStopwatch elapsed {degreeStopwatch.ElapsedMilliseconds} ms");
                Console.WriteLine($"server Decision elapsed {serverDecisionStopWatch.ElapsedMilliseconds} ms");


                finalResult = result[0];

                if (result[0] > 0)
				{
					return 0;
				}

				return 1;

			}