public List <byte[]> AddVotes(List <PublicVote> publicVotes)
        {
            if (!publicVotes.Any())
            {
                return(new List <byte[]>());
            }

            var firstCandidateVotes = publicVotes[0].CandidateVotes;


            List <Ciphertext> aggregates = new List <Ciphertext>();

            for (int i = 0; i < firstCandidateVotes.Count; i++)
            {
                aggregates.Add(homomorphicKeyManager.DeserializeCiphertext(firstCandidateVotes[i]));
            }

            for (int i = 1; i < publicVotes.Count; i++)
            {
                var vote = publicVotes[i];
                for (int j = 0; j < vote.CandidateVotes.Count; j++)
                {
                    var cipher = homomorphicKeyManager.DeserializeCiphertext(vote.CandidateVotes[j]);
                    evaluator.AddInplace(aggregates[j], cipher);
                }
            }

            return(aggregates.Select(a => homomorphicKeyManager.SerializeCiphertext(a)).ToList());
        }
Example #2
0
        static void Main(string[] args)
        {
            int   votersCount = 10000;
            ulong keysize     = 2048;

            int[] votes = createSampleVotes(votersCount, 1);
#if (TEST)
            Console.WriteLine("votes=[{0}]", string.Join(", ", votes));
#endif
            Console.WriteLine("Sum of all votes = {0}", votes.Sum());

            SEALContext    context = createContext(keysize);
            IntegerEncoder encoder = new IntegerEncoder(context);
            KeyGenerator   keygen  = new KeyGenerator(context);

            PublicKey publicKey = keygen.PublicKey;
            SecretKey secretKey = keygen.SecretKey;

            Encryptor encryptor = new Encryptor(context, publicKey);
            Evaluator evaluator = new Evaluator(context);
            Decryptor decryptor = new Decryptor(context, secretKey);

            Ciphertext encryptedTotal = new Ciphertext();
            encryptor.Encrypt(encoder.Encode(0), encryptedTotal);

            Ciphertext encrypted = new Ciphertext();
            Console.WriteLine("-----------------------------------");
            Console.WriteLine("Encoding the vote values ... ");



            Stopwatch sw = new Stopwatch();

            sw.Start();
            for (int i = 0; i < votes.Length; i++)
            {
                Plaintext plain = encoder.Encode(votes[i]);
                encryptor.Encrypt(plain, encrypted);
#if (TEST)
                Console.WriteLine($"Noise budget in encrypted: {decryptor.InvariantNoiseBudget(encrypted)} bits");

                Console.WriteLine($"Encoded {votes[i]} as polynomial {plain.ToString()}");
#endif
                evaluator.AddInplace(encryptedTotal, encrypted);
            }
            sw.Stop();
            Console.WriteLine("Elapsed={0}", sw.Elapsed);
            Console.WriteLine("Done");

            Console.WriteLine("-----------------------------------");
            Plaintext plainResult = new Plaintext();
            decryptor.Decrypt(encryptedTotal, plainResult);
            Console.Write($"Decrypting the result polynomial {plainResult.ToString()} ... ");
            Console.WriteLine("Done");

            Console.WriteLine("-----------------------------------");
            Console.WriteLine($"Decoded result: {encoder.DecodeInt32(plainResult)}");
            Console.ReadLine();
        }
Example #3
0
        //Function for calculating secured batched inner product
        private Ciphertext InnerProduct(Ciphertext featuresCiphertexts, Plaintext[] svPlaintexts, int i, Ciphertext[] sums, int numOfcolumnsCount, Ciphertext tempCt)
        {
            _evaluator.MultiplyPlain(featuresCiphertexts, svPlaintexts[i], sums[i]);
            int numOfRotations = (int)Math.Ceiling(Math.Log(numOfcolumnsCount, 2));

            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);
            }

            var sum = sums[i];

            return(sum);
        }
Example #4
0
        /*
         * In `1_BFV_Basics.cs' we showed how to perform a very simple computation using the
         * BFV scheme. The computation was performed modulo the PlainModulus parameter, and
         * utilized only one coefficient from a BFV plaintext polynomial. This approach has
         * two notable problems:
         *
         *  (1) Practical applications typically use integer or real number arithmetic,
         *      not modular arithmetic;
         *  (2) We used only one coefficient of the plaintext polynomial. This is really
         *      wasteful, as the plaintext polynomial is large and will in any case be
         *      encrypted in its entirety.
         *
         * For (1), one may ask why not just increase the PlainModulus parameter until no
         * overflow occurs, and the computations behave as in integer arithmetic. The problem
         * is that increasing PlainModulus increases noise budget consumption, and decreases
         * the initial noise budget too.
         *
         * In these examples we will discuss other ways of laying out data into plaintext
         * elements (encoding) that allow more computations without data type overflow, and
         * can allow the full plaintext polynomial to be utilized.
         */
        private static void ExampleIntegerEncoder()
        {
            Utilities.PrintExampleBanner("Example: Encoders / Integer Encoder");

            /*
             * [IntegerEncoder] (For BFV scheme only)
             *
             * The IntegerEncoder encodes integers to BFV plaintext polynomials as follows.
             * First, a binary expansion of the integer is computed. Next, a polynomial is
             * created with the bits as coefficients. For example, the integer
             *
             *  26 = 2^4 + 2^3 + 2^1
             *
             * is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. Conversely, plaintext
             * polynomials are decoded by evaluating them at x=2. For negative numbers the
             * IntegerEncoder simply stores all coefficients as either 0 or -1, where -1 is
             * represented by the unsigned integer PlainModulus - 1 in memory.
             *
             * Since encrypted computations operate on the polynomials rather than on the
             * encoded integers themselves, the polynomial coefficients will grow in the
             * course of such computations. For example, computing the sum of the encrypted
             * encoded integer 26 with itself will result in an encrypted polynomial with
             * larger coefficients: 2x^4 + 2x^3 + 2x^1. Squaring the encrypted encoded
             * integer 26 results also in increased coefficients due to cross-terms, namely,
             *
             *  (1x^4 + 1x^3 + 1x^1)^2 = 1x^8 + 2x^7 + 1x^6 + 2x^5 + 2x^4 + 1x^2;
             *
             * further computations will quickly increase the coefficients much more.
             * Decoding will still work correctly in this case (evaluating the polynomial
             * at x=2), but since the coefficients of plaintext polynomials are really
             * integers modulo plain_modulus, implicit reduction modulo plain_modulus may
             * yield unexpected results. For example, adding 1x^4 + 1x^3 + 1x^1 to itself
             * plain_modulus many times will result in the constant polynomial 0, which is
             * clearly not equal to 26 * plain_modulus. It can be difficult to predict when
             * such overflow will take place especially when computing several sequential
             * multiplications.
             *
             * The IntegerEncoder is easy to understand and use for simple computations,
             * and can be a good tool to experiment with for users new to Microsoft SEAL.
             * However, advanced users will probably prefer more efficient approaches,
             * such as the BatchEncoder or the CKKSEncoder.
             */
            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
            ulong polyModulusDegree    = 4096;

            parms.PolyModulusDegree = polyModulusDegree;
            parms.CoeffModulus      = CoeffModulus.BFVDefault(polyModulusDegree);

            /*
             * There is no hidden logic behind our choice of the plain_modulus. The only
             * thing that matters is that the plaintext polynomial coefficients will not
             * exceed this value at any point during our computation; otherwise the result
             * will be incorrect.
             */
            parms.PlainModulus = new SmallModulus(512);
            SEALContext context = new SEALContext(parms);

            Utilities.PrintParameters(context);
            Console.WriteLine();

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

            /*
             * We create an IntegerEncoder.
             */
            IntegerEncoder encoder = new IntegerEncoder(context);

            /*
             * First, we encode two integers as plaintext polynomials. Note that encoding
             * is not encryption: at this point nothing is encrypted.
             */
            int       value1 = 5;
            Plaintext plain1 = encoder.Encode(value1);

            Utilities.PrintLine();
            Console.WriteLine($"Encode {value1} as polynomial {plain1} (plain1),");

            int       value2 = -7;
            Plaintext plain2 = encoder.Encode(value2);

            Console.WriteLine(new string(' ', 13)
                              + $"Encode {value2} as polynomial {plain2} (plain2),");

            /*
             * Now we can encrypt the plaintext polynomials.
             */
            Ciphertext encrypted1 = new Ciphertext();
            Ciphertext encrypted2 = new Ciphertext();

            Utilities.PrintLine();
            Console.WriteLine("Encrypt plain1 to encrypted1 and plain2 to encrypted2.");
            encryptor.Encrypt(plain1, encrypted1);
            encryptor.Encrypt(plain2, encrypted2);
            Console.WriteLine("    + Noise budget in encrypted1: {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted1));
            Console.WriteLine("    + Noise budget in encrypted2: {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted2));

            /*
             * As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2.
             */
            encryptor.Encrypt(plain2, encrypted2);
            Ciphertext encryptedResult = new Ciphertext();

            Utilities.PrintLine();
            Console.WriteLine("Compute encrypted_result = (-encrypted1 + encrypted2) * encrypted2.");
            evaluator.Negate(encrypted1, encryptedResult);
            evaluator.AddInplace(encryptedResult, encrypted2);
            evaluator.MultiplyInplace(encryptedResult, encrypted2);
            Console.WriteLine("    + Noise budget in encryptedResult: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedResult));

            Plaintext plainResult = new Plaintext();

            Utilities.PrintLine();
            Console.WriteLine("Decrypt encrypted_result to plain_result.");
            decryptor.Decrypt(encryptedResult, plainResult);

            /*
             * Print the result plaintext polynomial. The coefficients are not even close
             * to exceeding our plainModulus, 512.
             */
            Console.WriteLine($"    + Plaintext polynomial: {plainResult}");

            /*
             * Decode to obtain an integer result.
             */
            Utilities.PrintLine();
            Console.WriteLine("Decode plain_result.");
            Console.WriteLine("    + Decoded integer: {0} ...... Correct.",
                              encoder.DecodeInt32(plainResult));
        }
Example #5
0
        private static void CKKSPerformanceTest(SEALContext context)
        {
            Stopwatch timer;

            Utilities.PrintParameters(context);
            Console.WriteLine();

            bool hasZLIB = Serialization.IsSupportedComprMode(ComprModeType.ZLIB);
            bool hasZSTD = Serialization.IsSupportedComprMode(ComprModeType.ZSTD);

            using EncryptionParameters parms = context.FirstContextData.Parms;
            ulong polyModulusDegree = parms.PolyModulusDegree;

            Console.Write("Generating secret/public keys: ");
            using KeyGenerator keygen = new KeyGenerator(context);
            Console.WriteLine("Done");

            using SecretKey secretKey = keygen.SecretKey;
            keygen.CreatePublicKey(out PublicKey publicKey);

            Func <RelinKeys> GetRelinKeys = () => {
                if (context.UsingKeyswitching)
                {
                    /*
                     * Generate relinearization keys.
                     */
                    Console.Write("Generating relinearization keys: ");
                    timer = Stopwatch.StartNew();
                    keygen.CreateRelinKeys(out RelinKeys relinKeys);
                    int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
                    Console.WriteLine($"Done [{micros} microseconds]");
                    return(relinKeys);
                }
                else
                {
                    return(null);
                }
            };

            Func <GaloisKeys> GetGaloisKeys = () => {
                if (context.UsingKeyswitching)
                {
                    if (!context.KeyContextData.Qualifiers.UsingBatching)
                    {
                        Console.WriteLine("Given encryption parameters do not support batching.");
                        return(null);
                    }

                    /*
                     * Generate Galois keys. In larger examples the Galois keys can use a lot of
                     * memory, which can be a problem in constrained systems. The user should
                     * try some of the larger runs of the test and observe their effect on the
                     * memory pool allocation size. The key generation can also take a long time,
                     * as can be observed from the print-out.
                     */
                    Console.Write($"Generating Galois keys: ");
                    timer = Stopwatch.StartNew();
                    keygen.CreateGaloisKeys(out GaloisKeys galoisKeys);
                    int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
                    Console.WriteLine($"Done [{micros} microseconds]");
                    return(galoisKeys);
                }
                else
                {
                    return(null);
                }
            };

            using RelinKeys relinKeys = GetRelinKeys();
            using GaloisKeys galKeys  = GetGaloisKeys();

            using Encryptor encryptor     = new Encryptor(context, publicKey);
            using Decryptor decryptor     = new Decryptor(context, secretKey);
            using Evaluator evaluator     = new Evaluator(context);
            using CKKSEncoder ckksEncoder = new CKKSEncoder(context);

            Stopwatch timeEncodeSum        = new Stopwatch();
            Stopwatch timeDecodeSum        = new Stopwatch();
            Stopwatch timeEncryptSum       = new Stopwatch();
            Stopwatch timeDecryptSum       = new Stopwatch();
            Stopwatch timeAddSum           = new Stopwatch();
            Stopwatch timeMultiplySum      = new Stopwatch();
            Stopwatch timeMultiplyPlainSum = new Stopwatch();
            Stopwatch timeSquareSum        = new Stopwatch();
            Stopwatch timeRelinearizeSum   = new Stopwatch();
            Stopwatch timeRescaleSum       = new Stopwatch();
            Stopwatch timeRotateOneStepSum = new Stopwatch();
            Stopwatch timeRotateRandomSum  = new Stopwatch();
            Stopwatch timeConjugateSum     = new Stopwatch();
            Stopwatch timeSerializeSum     = new Stopwatch();
            Stopwatch timeSerializeZLIBSum = new Stopwatch();
            Stopwatch timeSerializeZSTDSum = new Stopwatch();

            Random rnd = new Random();

            /*
             * How many times to run the test?
             */
            int count = 10;

            /*
             * Populate a vector of floating-point values to batch.
             */
            ulong slotCount = ckksEncoder.SlotCount;

            double[] podValues = new double[slotCount];
            for (ulong i = 0; i < slotCount; i++)
            {
                podValues[i] = 1.001 * i;
            }

            Console.Write("Running tests ");
            for (int i = 0; i < count; i++)
            {
                /*
                 * [Encoding]
                 * For scale we use the square root of the last CoeffModulus prime
                 * from parms.
                 */
                double scale = Math.Sqrt(parms.CoeffModulus.Last().Value);
                using Plaintext plain = new Plaintext(parms.PolyModulusDegree *
                                                      (ulong)parms.CoeffModulus.Count(), 0);
                timeEncodeSum.Start();
                ckksEncoder.Encode(podValues, scale, plain);
                timeEncodeSum.Stop();

                /*
                 * [Decoding]
                 */
                List <double> podList = new List <double>((int)slotCount);
                timeDecodeSum.Start();
                ckksEncoder.Decode(plain, podList);
                timeDecodeSum.Stop();

                /*
                 * [Encryption]
                 */
                using Ciphertext encrypted = new Ciphertext(context);
                timeEncryptSum.Start();
                encryptor.Encrypt(plain, encrypted);
                timeEncryptSum.Stop();

                /*
                 * [Decryption]
                 */
                using Plaintext plain2 = new Plaintext(polyModulusDegree, 0);
                timeDecryptSum.Start();
                decryptor.Decrypt(encrypted, plain2);
                timeDecryptSum.Stop();

                /*
                 * [Add]
                 */
                using Ciphertext encrypted1 = new Ciphertext(context);
                ckksEncoder.Encode(i + 1, plain);
                encryptor.Encrypt(plain, encrypted1);
                using Ciphertext encrypted2 = new Ciphertext(context);
                ckksEncoder.Encode(i + 1, plain2);
                encryptor.Encrypt(plain2, encrypted2);
                timeAddSum.Start();
                evaluator.AddInplace(encrypted1, encrypted2);
                evaluator.AddInplace(encrypted2, encrypted2);
                evaluator.AddInplace(encrypted1, encrypted2);
                timeAddSum.Stop();

                /*
                 * [Multiply]
                 */
                encrypted1.Reserve(3);
                timeMultiplySum.Start();
                evaluator.MultiplyInplace(encrypted1, encrypted2);
                timeMultiplySum.Stop();

                /*
                 * [Multiply Plain]
                 */
                timeMultiplyPlainSum.Start();
                evaluator.MultiplyPlainInplace(encrypted2, plain);
                timeMultiplyPlainSum.Stop();

                /*
                 * [Square]
                 */
                timeSquareSum.Start();
                evaluator.SquareInplace(encrypted2);
                timeSquareSum.Stop();

                if (context.UsingKeyswitching)
                {
                    /*
                     * [Relinearize]
                     */
                    timeRelinearizeSum.Start();
                    evaluator.RelinearizeInplace(encrypted1, relinKeys);
                    timeRelinearizeSum.Stop();

                    /*
                     * [Rescale]
                     */
                    timeRescaleSum.Start();
                    evaluator.RescaleToNextInplace(encrypted1);
                    timeRescaleSum.Stop();

                    /*
                     * [Rotate Vector]
                     */
                    timeRotateOneStepSum.Start();
                    evaluator.RotateVectorInplace(encrypted, 1, galKeys);
                    evaluator.RotateVectorInplace(encrypted, -1, galKeys);
                    timeRotateOneStepSum.Stop();

                    /*
                     * [Rotate Vector Random]
                     */
                    // ckksEncoder.SlotCount is always a power of 2.
                    int randomRotation = rnd.Next() & ((int)ckksEncoder.SlotCount - 1);
                    timeRotateRandomSum.Start();
                    evaluator.RotateVectorInplace(encrypted, randomRotation, galKeys);
                    timeRotateRandomSum.Stop();

                    /*
                     * [Complex Conjugate]
                     */
                    timeConjugateSum.Start();
                    evaluator.ComplexConjugateInplace(encrypted, galKeys);
                    timeConjugateSum.Stop();
                }

                /*
                 * [Serialize Ciphertext]
                 */
                using MemoryStream stream = new MemoryStream();
                timeSerializeSum.Start();
                encrypted.Save(stream, ComprModeType.None);
                timeSerializeSum.Stop();

                if (hasZLIB)
                {
                    /*
                     * [Serialize Ciphertext (ZLIB)]
                     */
                    timeSerializeZLIBSum.Start();
                    encrypted.Save(stream, ComprModeType.ZLIB);
                    timeSerializeZLIBSum.Stop();
                }

                if (hasZSTD)
                {
                    /*
                     * [Serialize Ciphertext (Zstandard)]
                     */
                    timeSerializeZSTDSum.Start();
                    encrypted.Save(stream, ComprModeType.ZSTD);
                    timeSerializeZSTDSum.Stop();
                }

                /*
                 * Print a dot to indicate progress.
                 */
                Console.Write(".");
                Console.Out.Flush();
            }

            Console.WriteLine(" Done");
            Console.WriteLine();
            Console.Out.Flush();

            int avgEncode           = (int)(timeEncodeSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgDecode           = (int)(timeDecodeSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgEncrypt          = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgDecrypt          = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgAdd              = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count));
            int avgMultiply         = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgMultiplyPlain    = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSquare           = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgRelinearize      = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgRescale          = (int)(timeRescaleSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgRotateOneStep    = (int)(timeRotateOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count));
            int avgRotateRandom     = (int)(timeRotateRandomSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgConjugate        = (int)(timeConjugateSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSerializeSum     = (int)(timeSerializeSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSerializeZLIBSum = (int)(timeSerializeZLIBSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSerializeZSTDSum = (int)(timeSerializeZSTDSum.Elapsed.TotalMilliseconds * 1000 / count);

            Console.WriteLine($"Average encode: {avgEncode} microseconds");
            Console.WriteLine($"Average decode: {avgDecode} microseconds");
            Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds");
            Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds");
            Console.WriteLine($"Average add: {avgAdd} microseconds");
            Console.WriteLine($"Average multiply: {avgMultiply} microseconds");
            Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds");
            Console.WriteLine($"Average square: {avgSquare} microseconds");
            if (context.UsingKeyswitching)
            {
                Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds");
                Console.WriteLine($"Average rescale: {avgRescale} microseconds");
                Console.WriteLine($"Average rotate vector one step: {avgRotateOneStep} microseconds");
                Console.WriteLine($"Average rotate vector random: {avgRotateRandom} microseconds");
                Console.WriteLine($"Average complex conjugate: {avgConjugate} microseconds");
            }
            Console.WriteLine($"Average serialize ciphertext: {avgSerializeSum} microseconds");
            if (hasZLIB)
            {
                Console.WriteLine(
                    $"Average compressed (ZLIB) serialize ciphertext: {avgSerializeZLIBSum} microseconds");
            }
            if (hasZSTD)
            {
                Console.WriteLine(
                    $"Average compressed (Zstandard) serialize ciphertext: {avgSerializeZSTDSum} microseconds");
            }

            Console.Out.Flush();
        }
Example #6
0
        private static void BFVPerformanceTest(SEALContext context)
        {
            Stopwatch timer;

            Utilities.PrintParameters(context);
            Console.WriteLine();

            bool hasZLIB = Serialization.IsSupportedComprMode(ComprModeType.ZLIB);
            bool hasZSTD = Serialization.IsSupportedComprMode(ComprModeType.ZSTD);

            using EncryptionParameters parms = context.FirstContextData.Parms;
            using Modulus plainModulus       = parms.PlainModulus;
            ulong polyModulusDegree = parms.PolyModulusDegree;

            Console.Write("Generating secret/public keys: ");
            using KeyGenerator keygen = new KeyGenerator(context);
            Console.WriteLine("Done");

            using SecretKey secretKey = keygen.SecretKey;
            keygen.CreatePublicKey(out PublicKey publicKey);

            Func <RelinKeys> GetRelinKeys = () => {
                if (context.UsingKeyswitching)
                {
                    /*
                     * Generate relinearization keys.
                     */
                    Console.Write("Generating relinearization keys: ");
                    timer = Stopwatch.StartNew();
                    keygen.CreateRelinKeys(out RelinKeys relinKeys);
                    int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
                    Console.WriteLine($"Done [{micros} microseconds]");
                    return(relinKeys);
                }
                else
                {
                    return(null);
                }
            };

            Func <GaloisKeys> GetGaloisKeys = () => {
                if (context.UsingKeyswitching)
                {
                    if (!context.KeyContextData.Qualifiers.UsingBatching)
                    {
                        Console.WriteLine("Given encryption parameters do not support batching.");
                        return(null);
                    }

                    /*
                     * Generate Galois keys. In larger examples the Galois keys can use a lot of
                     * memory, which can be a problem in constrained systems. The user should
                     * try some of the larger runs of the test and observe their effect on the
                     * memory pool allocation size. The key generation can also take a long time,
                     * as can be observed from the print-out.
                     */
                    Console.Write($"Generating Galois keys: ");
                    timer = Stopwatch.StartNew();
                    keygen.CreateGaloisKeys(out GaloisKeys galoisKeys);
                    int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
                    Console.WriteLine($"Done [{micros} microseconds]");
                    return(galoisKeys);
                }
                else
                {
                    return(null);
                }
            };

            using RelinKeys relinKeys = GetRelinKeys();
            using GaloisKeys galKeys  = GetGaloisKeys();

            using Encryptor encryptor       = new Encryptor(context, publicKey);
            using Decryptor decryptor       = new Decryptor(context, secretKey);
            using Evaluator evaluator       = new Evaluator(context);
            using BatchEncoder batchEncoder = new BatchEncoder(context);

            /*
             * These will hold the total times used by each operation.
             */
            Stopwatch timeBatchSum             = new Stopwatch();
            Stopwatch timeUnbatchSum           = new Stopwatch();
            Stopwatch timeEncryptSum           = new Stopwatch();
            Stopwatch timeDecryptSum           = new Stopwatch();
            Stopwatch timeAddSum               = new Stopwatch();
            Stopwatch timeMultiplySum          = new Stopwatch();
            Stopwatch timeMultiplyPlainSum     = new Stopwatch();
            Stopwatch timeSquareSum            = new Stopwatch();
            Stopwatch timeRelinearizeSum       = new Stopwatch();
            Stopwatch timeRotateRowsOneStepSum = new Stopwatch();
            Stopwatch timeRotateRowsRandomSum  = new Stopwatch();
            Stopwatch timeRotateColumnsSum     = new Stopwatch();
            Stopwatch timeSerializeSum         = new Stopwatch();
            Stopwatch timeSerializeZLIBSum     = new Stopwatch();
            Stopwatch timeSerializeZSTDSum     = new Stopwatch();

            /*
             * How many times to run the test?
             */
            int count = 10;

            /*
             * Populate a vector of values to batch.
             */
            ulong slotCount = batchEncoder.SlotCount;

            ulong[] podValues = new ulong[slotCount];
            Random  rnd       = new Random();

            for (ulong i = 0; i < batchEncoder.SlotCount; i++)
            {
                podValues[i] = plainModulus.Reduce((ulong)rnd.Next());
            }

            Console.Write("Running tests ");
            for (int i = 0; i < count; i++)
            {
                /*
                 * [Batching]
                 * There is nothing unusual here. We batch our random plaintext matrix
                 * into the polynomial. Note how the plaintext we create is of the exactly
                 * right size so unnecessary reallocations are avoided.
                 */
                using Plaintext plain = new Plaintext(parms.PolyModulusDegree, 0);
                timeBatchSum.Start();
                batchEncoder.Encode(podValues, plain);
                timeBatchSum.Stop();

                /*
                 * [Unbatching]
                 * We unbatch what we just batched.
                 */
                List <ulong> podList = new List <ulong>((int)slotCount);
                timeUnbatchSum.Start();
                batchEncoder.Decode(plain, podList);
                timeUnbatchSum.Stop();
                if (!podList.SequenceEqual(podValues))
                {
                    throw new InvalidOperationException("Batch/unbatch failed. Something is wrong.");
                }

                /*
                 * [Encryption]
                 * We make sure our ciphertext is already allocated and large enough
                 * to hold the encryption with these encryption parameters. We encrypt
                 * our random batched matrix here.
                 */
                using Ciphertext encrypted = new Ciphertext(context);
                timeEncryptSum.Start();
                encryptor.Encrypt(plain, encrypted);
                timeEncryptSum.Stop();

                /*
                 * [Decryption]
                 * We decrypt what we just encrypted.
                 */
                using Plaintext plain2 = new Plaintext(polyModulusDegree, 0);
                timeDecryptSum.Start();
                decryptor.Decrypt(encrypted, plain2);
                timeDecryptSum.Stop();
                if (!plain2.Equals(plain))
                {
                    throw new InvalidOperationException("Encrypt/decrypt failed. Something is wrong.");
                }

                /*
                 * [Add]
                 * We create two ciphertexts and perform a few additions with them.
                 */
                using Plaintext plain1 = new Plaintext(parms.PolyModulusDegree, 0);
                for (ulong j = 0; j < batchEncoder.SlotCount; j++)
                {
                    podValues[j] = j;
                }
                batchEncoder.Encode(podValues, plain1);
                for (ulong j = 0; j < batchEncoder.SlotCount; j++)
                {
                    podValues[j] = j + 1;
                }
                batchEncoder.Encode(podValues, plain2);
                using Ciphertext encrypted1 = new Ciphertext(context);
                encryptor.Encrypt(plain1, encrypted1);
                using Ciphertext encrypted2 = new Ciphertext(context);
                encryptor.Encrypt(plain2, encrypted2);

                timeAddSum.Start();
                evaluator.AddInplace(encrypted1, encrypted1);
                evaluator.AddInplace(encrypted2, encrypted2);
                evaluator.AddInplace(encrypted1, encrypted2);
                timeAddSum.Stop();

                /*
                 * [Multiply]
                 * We multiply two ciphertexts. Since the size of the result will be 3,
                 * and will overwrite the first argument, we reserve first enough memory
                 * to avoid reallocating during multiplication.
                 */
                encrypted1.Reserve(3);
                timeMultiplySum.Start();
                evaluator.MultiplyInplace(encrypted1, encrypted2);
                timeMultiplySum.Stop();

                /*
                 * [Multiply Plain]
                 * We multiply a ciphertext with a random plaintext. Recall that
                 * MultiplyPlain does not change the size of the ciphertext so we use
                 * encrypted2 here.
                 */
                timeMultiplyPlainSum.Start();
                evaluator.MultiplyPlainInplace(encrypted2, plain);
                timeMultiplyPlainSum.Stop();

                /*
                 * [Square]
                 * We continue to use encrypted2. Now we square it; this should be
                 * faster than generic homomorphic multiplication.
                 */
                timeSquareSum.Start();
                evaluator.SquareInplace(encrypted2);
                timeSquareSum.Stop();

                if (context.UsingKeyswitching)
                {
                    /*
                     * [Relinearize]
                     * Time to get back to encrypted1. We now relinearize it back
                     * to size 2. Since the allocation is currently big enough to
                     * contain a ciphertext of size 3, no costly reallocations are
                     * needed in the process.
                     */
                    timeRelinearizeSum.Start();
                    evaluator.RelinearizeInplace(encrypted1, relinKeys);
                    timeRelinearizeSum.Stop();

                    /*
                     * [Rotate Rows One Step]
                     * We rotate matrix rows by one step left and measure the time.
                     */
                    timeRotateRowsOneStepSum.Start();
                    evaluator.RotateRowsInplace(encrypted, 1, galKeys);
                    evaluator.RotateRowsInplace(encrypted, -1, galKeys);
                    timeRotateRowsOneStepSum.Stop();

                    /*
                     * [Rotate Rows Random]
                     * We rotate matrix rows by a random number of steps. This is much more
                     * expensive than rotating by just one step.
                     */
                    int rowSize = (int)batchEncoder.SlotCount / 2;
                    // rowSize is always a power of 2.
                    int randomRotation = rnd.Next() & (rowSize - 1);
                    timeRotateRowsRandomSum.Start();
                    evaluator.RotateRowsInplace(encrypted, randomRotation, galKeys);
                    timeRotateRowsRandomSum.Stop();

                    /*
                     * [Rotate Columns]
                     * Nothing surprising here.
                     */
                    timeRotateColumnsSum.Start();
                    evaluator.RotateColumnsInplace(encrypted, galKeys);
                    timeRotateColumnsSum.Stop();
                }

                /*
                 * [Serialize Ciphertext]
                 */
                using MemoryStream stream = new MemoryStream();
                timeSerializeSum.Start();
                encrypted.Save(stream, ComprModeType.None);
                timeSerializeSum.Stop();

                if (hasZLIB)
                {
                    /*
                     * [Serialize Ciphertext (ZLIB)]
                     */
                    timeSerializeZLIBSum.Start();
                    encrypted.Save(stream, ComprModeType.ZLIB);
                    timeSerializeZLIBSum.Stop();
                }

                if (hasZSTD)
                {
                    /*
                     * [Serialize Ciphertext (Zstandard)]
                     */
                    timeSerializeZSTDSum.Start();
                    encrypted.Save(stream, ComprModeType.ZSTD);
                    timeSerializeZSTDSum.Stop();
                }

                /*
                 * Print a dot to indicate progress.
                 */
                Console.Write(".");
                Console.Out.Flush();
            }

            Console.WriteLine(" Done");
            Console.WriteLine();
            Console.Out.Flush();

            int avgBatch             = (int)(timeBatchSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgUnbatch           = (int)(timeUnbatchSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgEncrypt           = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgDecrypt           = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgAdd               = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count));
            int avgMultiply          = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgMultiplyPlain     = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSquare            = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgRelinearize       = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgRotateRowsOneStep = (int)(timeRotateRowsOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count));
            int avgRotateRowsRandom  = (int)(timeRotateRowsRandomSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgRotateColumns     = (int)(timeRotateColumnsSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSerializeSum      = (int)(timeSerializeSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSerializeZLIBSum  = (int)(timeSerializeZLIBSum.Elapsed.TotalMilliseconds * 1000 / count);
            int avgSerializeZSTDSum  = (int)(timeSerializeZSTDSum.Elapsed.TotalMilliseconds * 1000 / count);

            Console.WriteLine($"Average batch: {avgBatch} microseconds");
            Console.WriteLine($"Average unbatch: {avgUnbatch} microseconds");
            Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds");
            Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds");
            Console.WriteLine($"Average add: {avgAdd} microseconds");
            Console.WriteLine($"Average multiply: {avgMultiply} microseconds");
            Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds");
            Console.WriteLine($"Average square: {avgSquare} microseconds");
            if (context.UsingKeyswitching)
            {
                Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds");
                Console.WriteLine($"Average rotate rows one step: {avgRotateRowsOneStep} microseconds");
                Console.WriteLine($"Average rotate rows random: {avgRotateRowsRandom} microseconds");
                Console.WriteLine($"Average rotate columns: {avgRotateColumns} microseconds");
            }
            Console.WriteLine($"Average serialize ciphertext: {avgSerializeSum} microseconds");
            if (hasZLIB)
            {
                Console.WriteLine(
                    $"Average compressed (ZLIB) serialize ciphertext: {avgSerializeZLIBSum} microseconds");
            }
            if (hasZSTD)
            {
                Console.WriteLine(
                    $"Average compressed (Zstandard) serialize ciphertext: {avgSerializeZSTDSum} microseconds");
            }

            Console.Out.Flush();
        }
Example #7
0
        private static void HomoExample()
        {
            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);

            parms.PolyModulusDegree = 2048;
            parms.CoeffModulus      = DefaultParams.CoeffModulus128(polyModulusDegree: 2048);
            parms.PlainModulus      = new SmallModulus(1 << 8);
            SEALContext    context = SEALContext.Create(parms);
            IntegerEncoder encoder = new IntegerEncoder(context);

            KeyGenerator keygen = new KeyGenerator(context);

            Microsoft.Research.SEAL.PublicKey publicKey = keygen.PublicKey;
            SecretKey secretKey = keygen.SecretKey;

            Encryptor encryptor = new Encryptor(context, publicKey);
            Evaluator evaluator = new Evaluator(context);

            Decryptor decryptor = new Decryptor(context, secretKey);

            int       value1 = 5;
            Plaintext plain1 = encoder.Encode(value1);

            Console.WriteLine($"Encoded {value1} as polynomial {plain1.ToString()} (plain1)");

            int       value2 = -7;
            Plaintext plain2 = encoder.Encode(value2);

            Console.WriteLine($"Encoded {value2} as polynomial {plain2.ToString()} (plain2)");

            Ciphertext encrypted1 = new Ciphertext();
            Ciphertext encrypted2 = new Ciphertext();

            Console.Write("Encrypting plain1: ");

            encryptor.Encrypt(plain1, encrypted1);
            Console.WriteLine("Done (encrypted1)");

            Plaintext plainResult = new Plaintext();

            decryptor.Decrypt(encrypted1, plainResult);
            Console.WriteLine(encoder.DecodeInt32(plainResult));


            Console.Write("Encrypting plain2: ");
            encryptor.Encrypt(plain2, encrypted2);
            Console.WriteLine("Done (encrypted2)");



            Console.WriteLine($"Noise budget in encrypted1: {decryptor.InvariantNoiseBudget(encrypted1)} bits");
            Console.WriteLine($"Noise budget in encrypted2: {decryptor.InvariantNoiseBudget(encrypted2)} bits");

            evaluator.NegateInplace(encrypted1);
            Console.WriteLine($"Noise budget in -encrypted1: {decryptor.InvariantNoiseBudget(encrypted1)} bits");

            evaluator.AddInplace(encrypted1, encrypted2);

            Console.WriteLine($"Noise budget in -encrypted1 + encrypted2: {decryptor.InvariantNoiseBudget(encrypted1)} bits");

            evaluator.MultiplyInplace(encrypted1, encrypted2);

            Console.WriteLine($"Noise budget in (-encrypted1 + encrypted2) * encrypted2: {decryptor.InvariantNoiseBudget(encrypted1)} bits");

            plainResult = new Plaintext();
            Console.Write("Decrypting result: ");
            decryptor.Decrypt(encrypted1, plainResult);
            Console.WriteLine("Done");

            Console.WriteLine($"Plaintext polynomial: {plainResult.ToString()}");

            Console.WriteLine($"Decoded integer: {encoder.DecodeInt32(plainResult)}");
        }
        public void TestLinearRegression_Encryption()
        {
            // these are the feature sets we will be encrypting and getting
            // the ML model results on. The plaintext versions of these values
            // should (in the encryped scheme) not be known by the evaluator

            double[][] testX = new double[6][];
            testX[0] = new double[] { 43.45089541, 53.15091973, 53.07708932, 93.65456934, 65.23330105, 69.34856259, 62.91649012, 35.28814156, 108.1002775, 100.1735266 };
            testX[1] = new double[] { 51.59952075, 99.48561775, 95.75948428, 126.6533636, 142.5235433, 90.97955769, 43.66586306, 85.31957886, 62.57644682, 66.12458533 };
            testX[2] = new double[] { 94.77026243, 71.51229208, 85.33271407, 69.58347566, 107.8693045, 101.6701889, 89.88200921, 54.93440139, 105.5448532, 72.07947083 };
            testX[3] = new double[] { 89.53820766, 100.199631, 86.19911875, 85.88717675, 33.92249944, 80.47113937, 65.34411148, 89.70004394, 75.00778202, 122.3514331 };
            testX[4] = new double[] { 96.86101454, 97.54597612, 122.9960987, 86.1281547, 115.5539807, 107.888993, 65.51660154, 74.17007885, 48.04727402, 93.56952259 };
            testX[5] = new double[] { 91.75121904, 121.2115065, 62.92763365, 99.4343452, 70.420912, 88.0580948, 71.82993308, 80.49171244, 87.11321454, 100.1459868 };

            // setup the encryptor and other various components
            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

            parms.PolyModulusDegree = 8192;
            parms.CoeffModulus      = DefaultParams.CoeffModulus128(polyModulusDegree: 8192);
            SEALContext  context   = SEALContext.Create(parms);
            CKKSEncoder  encoder   = new CKKSEncoder(context);
            KeyGenerator keygen    = new KeyGenerator(context);
            PublicKey    publicKey = keygen.PublicKey;
            SecretKey    secretKey = keygen.SecretKey;
            RelinKeys    relinKeys = keygen.RelinKeys(decompositionBitCount: DefaultParams.DBCmax);
            Encryptor    encryptor = new Encryptor(context, publicKey);
            Evaluator    evaluator = new Evaluator(context);
            Decryptor    decryptor = new Decryptor(context, secretKey);
            double       scale     = Math.Pow(2.0, 30);
            List <List <Ciphertext> > featureCiphers = new List <List <Ciphertext> >();

            for (int i = 0; i < testX.Length; i++)
            {
                List <Ciphertext> curFeatureCiphers = new List <Ciphertext>();
                foreach (var featureVal in testX[i])
                {
                    List <double> featureVector = new double[] { featureVal }.ToList();
                    Plaintext     plain = new Plaintext();
                    encoder.Encode(featureVal, scale, plain);
                    Ciphertext encrypted = new Ciphertext();
                    encryptor.Encrypt(plain, encrypted);
                    curFeatureCiphers.Add(encrypted);
                }
                featureCiphers.Add(curFeatureCiphers);
            }

            // This is the 'evaluator' section
            // this is not a part of the client and would, in a cloud based solution, be run on the server
            // the server should not know the values of the input features, but it will do math on them
            // likewise, the client would not know the various weights and parameters, but will receive a result
            double[] weights_model =
            { 0.0921533,
              0.14545279,
              0.11066622,
              0.06119513,
              0.10041948,
              0.19091597,
              0.07359407,
              0.04503237,
              0.10848583,
              0.10092494 };
            double intercept_model = -2.484390163425502;

            double[] weights_groundTruth =
            { 0.1, 0.15, 0.1, 0.05, 0.1, 0.2, 0.05, 0.05, 0.1, 0.1 };

            // we need to encode the weights/parameters/intercepts/etc. used by the model using the same public key as the client
            List <Ciphertext> weightsCTs = new List <Ciphertext>();
            List <Ciphertext> scoreCTs   = new List <Ciphertext>();

            foreach (var weight in weights_model)
            {
                List <double> weightVector = new double[] { weight }.ToList();
                List <double> scoreVector = new double[] { 0.0 }.ToList();
                Plaintext     weightPT = new Plaintext();
                encoder.Encode(weight, scale, weightPT);
                Ciphertext weightCT = new Ciphertext();
                encryptor.Encrypt(weightPT, weightCT);
                weightsCTs.Add(weightCT);
            }

            // next, we run the actual model's computation
            // linear regression is a basic dot product
            for (int i = 0; i < featureCiphers.Count(); i++)
            {
                List <Ciphertext> multResultCTs = new List <Ciphertext>();
                for (var j = 0; j < weightsCTs.Count; j++)
                {
                    Ciphertext multResultCT = new Ciphertext();
                    evaluator.Multiply(weightsCTs[j], featureCiphers[i][j], multResultCT);
                    multResultCTs.Add(multResultCT);
                }
                Ciphertext dotProductResult = new Ciphertext();
                evaluator.AddMany(multResultCTs, dotProductResult);

                Plaintext scorePT = new Plaintext();
                encoder.Encode(intercept_model, dotProductResult.Scale, scorePT);
                Ciphertext scoreCT = new Ciphertext();
                encryptor.Encrypt(scorePT, scoreCT);
                evaluator.AddInplace(scoreCT, dotProductResult);
                scoreCTs.Add(scoreCT);
                //evaluator.AddInplace(scoreCTs[i], interceptCT);
            }

            // we now have the encrypted version of the ML model. The below section is the client's again
            // in it, we decrypt the results given by the server using the private key generated previously
            List <List <double> > predictions = new List <List <double> >();

            for (int i = 0; i < scoreCTs.Count; i++)
            {
                Plaintext plainResult     = new Plaintext();
                var       encryptedResult = scoreCTs[i];
                decryptor.Decrypt(encryptedResult, plainResult);
                List <double> result = new List <double>();
                encoder.Decode(plainResult, result);
                predictions.Add(result);
            }

            // this is the output section. In practice, we would not have access to these values (as they represent the ground truth)
            // We are using them here merely to demonstrate that we can properly recover the proper ML model output
            double[]     yGroundTruth = { 68.43881952, 87.75905253, 88.34053641, 83.87264322, 95.20322583, 89.61704108 };
            double[]     yTest        = { 68.702934, 87.28860458, 88.40827187, 83.24001674, 94.53137951, 89.00229455 };
            const double EPSILON      = 1e-4;

            for (int i = 0; i < predictions.Count; i++)
            {
                var avgDecryption = predictions[i].Average();
                var absDelta      = Math.Abs(avgDecryption - yTest[i]);
                Assert.IsTrue(absDelta < EPSILON);
            }
        }
Example #9
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();
                var          galoisKeys = keygen.GaloisKeys();
                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();
                var featuresCiphertexts = new Ciphertext();

                //Encode and encrypt features

                encoder.Encode(features, scale, plaintexts);
                encryptor.Encrypt(plaintexts, featuresCiphertexts);
                SvcUtilities.PrintScale(plaintexts, "featurePlaintext");
                SvcUtilities.PrintScale(featuresCiphertexts, "featurefEncrypted");



                // Handle SV
                var numOfrows    = _vectors.Length;
                var numOfcolumns = _vectors[0].Length;

                int numOfRotations = (int)Math.Ceiling(Math.Log2(numOfcolumns));
                //Console.WriteLine("**********************************    : "+ numOfRotations);
                var svPlaintexts = new Plaintext[numOfrows];

                //Encode SV
                for (int i = 0; i < numOfrows; i++)
                {
                    //for (int j = 0; j < numOfcolumns; j++)
                    //{
                    svPlaintexts[i] = new Plaintext();
                    encoder.Encode(_vectors[i], scale, svPlaintexts[i]);
                    SvcUtilities.PrintScale(svPlaintexts[i], "supportVectorsPlaintext" + i);
                    //}
                }
                // 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>();

                    evaluator.MultiplyPlain(featuresCiphertexts, svPlaintexts[i], sums[i]);

                    for (int k = 1; k <= numOfRotations + 1 /*(int)encoder.SlotCount*/ / 2; k <<= 1)
                    {
                        Ciphertext tempCt = new Ciphertext();
                        evaluator.RotateVector(sums[i], k, galoisKeys, tempCt);
                        evaluator.AddInplace(sums[i], tempCt);
                    }


                    kernels[i] = sums[i];


                    evaluator.NegateInplace(kernels[i]);

                    if (useRelinearizeInplace)
                    {
                        evaluator.RelinearizeInplace(kernels[i], relinKeys);
                    }

                    if (useReScale)
                    {
                        evaluator.RescaleToNextInplace(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}IrisLinearBatch_IrisSecureSVC_total_{power}_{useRelinearizeInplace}_{useReScale}.txt", !_firstTime)
                       )
                {
                    _firstTime = false;
                    file.WriteLine($"{result[0]}");
                }

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

                return(1);
            }
Example #10
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;

			}