Example #1
0
        public void BalancedEncodeDecodeInt64NET()
        {
            var modulus = new SmallModulus(0x10000);
            var encoder = new BalancedEncoder(modulus, 3, MemoryPoolHandle.New());

            var poly = encoder.Encode(0L);

            Assert.AreEqual(0, poly.SignificantCoeffCount());
            Assert.IsTrue(poly.IsZero);
            Assert.AreEqual(0L, encoder.DecodeInt64(poly));

            var poly1 = encoder.Encode(1L);

            Assert.AreEqual(1, poly1.SignificantCoeffCount());
            Assert.AreEqual("1", poly1.ToString());
            Assert.AreEqual(1L, encoder.DecodeInt64(poly1));

            var poly2 = encoder.Encode(2L);

            Assert.AreEqual(2, poly2.SignificantCoeffCount());
            Assert.AreEqual("1x^1 + FFFF", poly2.ToString());
            Assert.AreEqual(2L, encoder.DecodeInt64(poly2));

            var poly3 = encoder.Encode(3L);

            Assert.AreEqual(2, poly3.SignificantCoeffCount());
            Assert.AreEqual("1x^1", poly3.ToString());
            Assert.AreEqual(3L, encoder.DecodeInt64(poly3));

            var poly4 = encoder.Encode(-1L);

            Assert.AreEqual(1, poly4.SignificantCoeffCount());
            Assert.AreEqual("FFFF", poly4.ToString());
            Assert.AreEqual(-1L, encoder.DecodeInt64(poly4));

            var poly5 = encoder.Encode(-2L);

            Assert.AreEqual(2, poly5.SignificantCoeffCount());
            Assert.AreEqual("FFFFx^1 + 1", poly5.ToString());
            Assert.AreEqual(-2L, encoder.DecodeInt64(poly5));

            var poly6 = encoder.Encode(-3L);

            Assert.AreEqual(2, poly6.SignificantCoeffCount());
            Assert.AreEqual("FFFFx^1", poly6.ToString());
            Assert.AreEqual(-3L, encoder.DecodeInt64(poly6));

            var poly7 = encoder.Encode(-0x2671L);

            Assert.AreEqual(9, poly7.SignificantCoeffCount());
            for (int i = 0; i < 9; ++i)
            {
                Assert.AreEqual(0xFFFFUL, poly7[i]);
            }
            Assert.AreEqual(-0x2671L, encoder.DecodeInt64(poly7));

            var poly8 = encoder.Encode(-4374L);

            Assert.AreEqual(9, poly8.SignificantCoeffCount());
            Assert.AreEqual(0xFFFFUL, poly8[8]);
            Assert.AreEqual(1UL, poly8[7]);
            for (int i = 0; i < 7; ++i)
            {
                Assert.IsTrue(poly8[i] == 0);
            }
            Assert.AreEqual(-4374L, encoder.DecodeInt64(poly8));

            var poly9 = encoder.Encode(-0xD4EBL);

            Assert.AreEqual(11, poly9.SignificantCoeffCount());
            for (int i = 0; i < 11; ++i)
            {
                if (i % 3 == 1)
                {
                    Assert.AreEqual(0xFFFFUL, poly9[i]);
                }
                else if (i % 3 == 0)
                {
                    Assert.IsTrue(poly9[i] == 0);
                }
                else
                {
                    Assert.AreEqual(1UL, poly9[i]);
                }
            }
            Assert.AreEqual(-0xD4EBL, encoder.DecodeInt64(poly9));

            var poly10 = encoder.Encode(-30724L);

            Assert.AreEqual(11, poly10.SignificantCoeffCount());
            Assert.AreEqual(0xFFFFUL, poly10[10]);
            Assert.AreEqual(1UL, poly10[9]);
            Assert.AreEqual(1UL, poly10[8]);
            Assert.AreEqual(1UL, poly10[7]);
            Assert.IsTrue(poly10[6] == 0);
            Assert.IsTrue(poly10[5] == 0);
            Assert.AreEqual(0xFFFFUL, poly10[4]);
            Assert.AreEqual(0xFFFFUL, poly10[3]);
            Assert.IsTrue(poly10[2] == 0);
            Assert.AreEqual(1UL, poly10[1]);
            Assert.AreEqual(0xFFFFUL, poly10[0]);
            Assert.AreEqual(-30724L, encoder.DecodeInt64(poly10));

            var encoder2 = new BalancedEncoder(modulus, 13, MemoryPoolHandle.New());
            var poly11   = encoder2.Encode(-126375543984L);

            Assert.AreEqual(11, poly11.SignificantCoeffCount());
            Assert.AreEqual(0xFFFFUL, poly11[10]);
            Assert.AreEqual(1UL, poly11[9]);
            Assert.AreEqual(1UL, poly11[8]);
            Assert.AreEqual(1UL, poly11[7]);
            Assert.IsTrue(poly11[6] == 0);
            Assert.IsTrue(poly11[5] == 0);
            Assert.AreEqual(0xFFFFUL, poly11[4]);
            Assert.AreEqual(0xFFFFUL, poly11[3]);
            Assert.IsTrue(poly11[2] == 0);
            Assert.AreEqual(1UL, poly11[1]);
            Assert.AreEqual(0xFFFFUL, poly11[0]);
            Assert.AreEqual(-126375543984L, encoder2.DecodeInt64(poly11));

            modulus.Set(0xFFFF);
            var encoder3 = new BalancedEncoder(modulus, 7, MemoryPoolHandle.New());
            var poly12   = new Plaintext(6);

            poly12[0] = 1;
            poly12[1] = 0xFFFE; // -1
            poly12[2] = 0xFFFD; // -2
            poly12[3] = 0x8000; // -32767
            poly12[4] = 0x7FFF; // 32767
            poly12[5] = 0x7FFE; // 32766
            Assert.AreEqual(1L + -1 * 7 + -2 * 49 + -32767 * 343 + 32767 * 2401 + 32766 * 16807, encoder3.DecodeInt64(poly12));

            var encoder4 = new BalancedEncoder(modulus, 6, MemoryPoolHandle.New());

            poly8    = new Plaintext(4);
            poly8[0] = 5;
            poly8[1] = 4;
            poly8[2] = 3;
            poly8[3] = (modulus.Value - 2);
            Int64 value = 5 + 4 * 6 + 3 * 36 - 2 * 216;

            Assert.AreEqual(value, encoder4.DecodeInt64(poly8));

            var encoder5 = new BalancedEncoder(modulus, 10, MemoryPoolHandle.New());

            poly9    = new Plaintext(4);
            poly9[0] = 1;
            poly9[1] = 2;
            poly9[2] = 3;
            poly9[3] = 4;
            value    = 4321;
            Assert.AreEqual(value, encoder5.DecodeInt64(poly9));

            value = -1234;
            poly10.Set(encoder3.Encode(value));
            Assert.AreEqual(5, poly10.SignificantCoeffCount());
            Assert.IsTrue(value.Equals(encoder3.DecodeInt64(poly10)));

            value = -1234;
            poly11.Set(encoder4.Encode(value));
            Assert.AreEqual(5, poly11.SignificantCoeffCount());
            Assert.IsTrue(value.Equals(encoder4.DecodeInt64(poly11)));

            value = -1234;
            poly12.Set(encoder5.Encode(value));
            Assert.AreEqual(4, poly12.SignificantCoeffCount());
            Assert.IsTrue(value.Equals(encoder5.DecodeInt64(poly12)));
        }
        public void BalancedEncodeDecodeInt64NET()
        {
            var modulus = new BigUInt("10000");
            var encoder = new BalancedEncoder(modulus, 3);

            var poly = encoder.Encode(0L);

            Assert.AreEqual(0, poly.GetSignificantCoeffCount());
            Assert.IsTrue(poly.IsZero);
            Assert.AreEqual(0L, encoder.DecodeInt64(poly));

            var poly1 = encoder.Encode(1L);

            Assert.AreEqual(1, poly1.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly1.CoeffBitCount);
            Assert.AreEqual("1", poly1.ToString());
            Assert.AreEqual(1L, encoder.DecodeInt64(poly1));

            var poly2 = encoder.Encode(2L);

            Assert.AreEqual(2, poly2.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly2.CoeffBitCount);
            Assert.AreEqual("1x^1 + FFFF", poly2.ToString());
            Assert.AreEqual(2L, encoder.DecodeInt64(poly2));

            var poly3 = encoder.Encode(3L);

            Assert.AreEqual(2, poly3.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly3.CoeffBitCount);
            Assert.AreEqual("1x^1", poly3.ToString());
            Assert.AreEqual(3L, encoder.DecodeInt64(poly3));

            var poly4 = encoder.Encode(-1L);

            Assert.AreEqual(1, poly4.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly4.CoeffBitCount);
            Assert.AreEqual("FFFF", poly4.ToString());
            Assert.AreEqual(-1L, encoder.DecodeInt64(poly4));

            var poly5 = encoder.Encode(-2L);

            Assert.AreEqual(2, poly5.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly5.CoeffBitCount);
            Assert.AreEqual("FFFFx^1 + 1", poly5.ToString());
            Assert.AreEqual(-2L, encoder.DecodeInt64(poly5));

            var poly6 = encoder.Encode(-3L);

            Assert.AreEqual(2, poly6.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly6.CoeffBitCount);
            Assert.AreEqual("FFFFx^1", poly6.ToString());
            Assert.AreEqual(-3L, encoder.DecodeInt64(poly6));

            var poly7 = encoder.Encode(-0x2671L);

            Assert.AreEqual(9, poly7.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly7.CoeffBitCount);
            for (int i = 0; i < 9; ++i)
            {
                Assert.AreEqual("FFFF", poly7[i].ToString());
            }
            Assert.AreEqual(-0x2671L, encoder.DecodeInt64(poly7));

            var poly8 = encoder.Encode(-4374L);

            Assert.AreEqual(9, poly8.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly8.CoeffBitCount);
            Assert.AreEqual("FFFF", poly8[8].ToString());
            Assert.AreEqual("1", poly8[7].ToString());
            for (int i = 0; i < 7; ++i)
            {
                Assert.IsTrue(poly8[i].IsZero);
            }
            Assert.AreEqual(-4374L, encoder.DecodeInt64(poly8));

            var poly9 = encoder.Encode(-0xD4EBL);

            Assert.AreEqual(11, poly9.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly9.CoeffBitCount);
            for (int i = 0; i < 11; ++i)
            {
                if (i % 3 == 1)
                {
                    Assert.AreEqual("FFFF", poly9[i].ToString());
                }
                else if (i % 3 == 0)
                {
                    Assert.IsTrue(poly9[i].IsZero);
                }
                else
                {
                    Assert.AreEqual("1", poly9[i].ToString());
                }
            }
            Assert.AreEqual(-0xD4EBL, encoder.DecodeInt64(poly9));

            var poly10 = encoder.Encode(-30724L);

            Assert.AreEqual(11, poly10.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly10.CoeffBitCount);
            Assert.AreEqual("FFFF", poly10[10].ToString());
            Assert.AreEqual("1", poly10[9].ToString());
            Assert.AreEqual("1", poly10[8].ToString());
            Assert.AreEqual("1", poly10[7].ToString());
            Assert.IsTrue(poly10[6].IsZero);
            Assert.IsTrue(poly10[5].IsZero);
            Assert.AreEqual("FFFF", poly10[4].ToString());
            Assert.AreEqual("FFFF", poly10[3].ToString());
            Assert.IsTrue(poly10[2].IsZero);
            Assert.AreEqual("1", poly10[1].ToString());
            Assert.AreEqual("FFFF", poly10[0].ToString());
            Assert.AreEqual(-30724L, encoder.DecodeInt64(poly10));

            var encoder2 = new BalancedEncoder(modulus, 13);
            var poly11   = encoder2.Encode(-126375543984L);

            Assert.AreEqual(11, poly11.GetSignificantCoeffCount());
            Assert.AreEqual(modulus.BitCount, poly11.CoeffBitCount);
            Assert.AreEqual("FFFF", poly11[10].ToString());
            Assert.AreEqual("1", poly11[9].ToString());
            Assert.AreEqual("1", poly11[8].ToString());
            Assert.AreEqual("1", poly11[7].ToString());
            Assert.IsTrue(poly11[6].IsZero);
            Assert.IsTrue(poly11[5].IsZero);
            Assert.AreEqual("FFFF", poly11[4].ToString());
            Assert.AreEqual("FFFF", poly11[3].ToString());
            Assert.IsTrue(poly11[2].IsZero);
            Assert.AreEqual("1", poly11[1].ToString());
            Assert.AreEqual("FFFF", poly11[0].ToString());
            Assert.AreEqual(-126375543984L, encoder2.DecodeInt64(poly11));

            modulus.Set("FFFF");
            var encoder3 = new BalancedEncoder(modulus, 7);
            var poly12   = new BigPoly(6, 16);

            poly12[0].Set(1);
            poly12[1].Set("FFFE"); // -1
            poly12[2].Set("FFFD"); // -2
            poly12[3].Set("8000"); // -32767
            poly12[4].Set("7FFF"); // 32767
            poly12[5].Set("7FFE"); // 32766
            Assert.AreEqual(1L + -1 * 7 + -2 * 49 + -32767 * 343 + 32767 * 2401 + 32766 * 16807, encoder3.DecodeInt64(poly12));
        }
Example #3
0
        public static void ExampleParameterSelection()
        {
            PrintExampleBanner("Example: Automatic Parameter Selection");

            /*
             * Here we demonstrate the automatic parameter selection tool. Suppose we want to find parameters
             * that are optimized in a way that allows us to evaluate the polynomial 42x^3-27x+1. We need to know
             * the size of the input data, so let's assume that x is an integer with base-3 representation of length
             * at most 10.
             */
            Console.Write("Finding optimized parameters for computing 42x^3-27x+1 ... ");

            var chooserEncoder   = new ChooserEncoder();
            var chooserEvaluator = new ChooserEvaluator();

            /*
             * First create a ChooserPoly representing the input data. You can think of this modeling a freshly
             * encrypted cipheretext of a plaintext polynomial with length at most 10 coefficients, where the
             * coefficients have absolute value at most 1.
             */
            var cinput = new ChooserPoly(10, 1);

            // Compute the first term
            var ccubedInput = chooserEvaluator.Exponentiate(cinput, 3);
            var cterm1      = chooserEvaluator.MultiplyPlain(ccubedInput, chooserEncoder.Encode(42));

            // Compute the second term
            var cterm2 = chooserEvaluator.MultiplyPlain(cinput, chooserEncoder.Encode(27));

            // Subtract the first two terms
            var csum12 = chooserEvaluator.Sub(cterm1, cterm2);

            // Add the constant term 1
            var cresult = chooserEvaluator.AddPlain(csum12, chooserEncoder.Encode(1));

            // To find an optimized set of parameters, we use ChooserEvaluator::select_parameters(...).
            var optimalParms = new EncryptionParameters();

            chooserEvaluator.SelectParameters(cresult, optimalParms);

            Console.WriteLine("done.");

            // Let's print these to see what was recommended
            Console.WriteLine("Selected parameters:");
            Console.WriteLine("{{ poly_modulus: {0}", optimalParms.PolyModulus);
            Console.WriteLine("{{ coeff_modulus: {0}", optimalParms.CoeffModulus);
            Console.WriteLine("{{ plain_modulus: {0}", optimalParms.PlainModulus.ToDecimalString());
            Console.WriteLine("{{ decomposition_bit_count: {0}", optimalParms.DecompositionBitCount);
            Console.WriteLine("{{ noise_standard_deviation: {0}", optimalParms.NoiseStandardDeviation);
            Console.WriteLine("{{ noise_max_deviation: {0}", optimalParms.NoiseMaxDeviation);

            // Let's try to actually perform the homomorphic computation using the recommended parameters.
            // Generate keys.
            Console.WriteLine("Generating keys...");
            var generator = new KeyGenerator(optimalParms);

            generator.Generate();
            Console.WriteLine("... key generation completed");
            var publicKey = generator.PublicKey;
            var secretKey = generator.SecretKey;

            // Create the encoding/encryption tools
            var encoder   = new BalancedEncoder(optimalParms.PlainModulus);
            var encryptor = new Encryptor(optimalParms, publicKey);
            var evaluator = new Evaluator(optimalParms);
            var decryptor = new Decryptor(optimalParms, secretKey);

            // Now perform the computations on real encrypted data.
            const int inputValue = 12345;
            var       plainInput = encoder.Encode(inputValue);

            Console.WriteLine("Encoded {0} as polynomial {1}", inputValue, plainInput);

            Console.Write("Encrypting ... ");
            var input = encryptor.Encrypt(plainInput);

            Console.WriteLine("done.");

            // Compute the first term
            Console.Write("Computing first term ... ");
            var cubedInput = evaluator.Exponentiate(input, 3);
            var term1      = evaluator.MultiplyPlain(cubedInput, encoder.Encode(42));

            Console.WriteLine("done.");

            // Compute the second term
            Console.Write("Computing second term ... ");
            var term2 = evaluator.MultiplyPlain(input, encoder.Encode(27));

            Console.WriteLine("done.");

            // Subtract the first two terms
            Console.Write("Subtracting first two terms ... ");
            var sum12 = evaluator.Sub(term1, term2);

            Console.WriteLine("done.");

            // Add the constant term 1
            Console.Write("Adding one ... ");
            var result = evaluator.AddPlain(sum12, encoder.Encode(1));

            Console.WriteLine("done.");

            // Decrypt and decode
            Console.Write("Decrypting ... ");
            var plainResult = decryptor.Decrypt(result);

            Console.WriteLine("done.");

            // Finally print the result
            Console.WriteLine("Polynomial 42x^3-27x+1 evaluated at x=12345: {0}", encoder.DecodeInt64(plainResult));

            // How much noise did we end up with?
            Console.WriteLine("Noise in the result: {0}/{1} bits", Utilities.InherentNoise(result, optimalParms, secretKey).GetSignificantBitCount(),
                              Utilities.InherentNoiseMax(optimalParms).GetSignificantBitCount());
        }