Exemple #1
0
        public void ExceptionsTest()
        {
            SEALContext  context = GlobalContext.BFVContext;
            KeyGenerator keygen  = new KeyGenerator(context);
            SecretKey    secret  = new SecretKey();
            List <uint>  elts    = new List <uint> {
                16385
            };
            List <uint> elts_null = null;
            List <int>  steps     = new List <int> {
                4096
            };
            List <int> steps_null = null;

            Utilities.AssertThrows <ArgumentNullException>(() => keygen = new KeyGenerator(null));

            Utilities.AssertThrows <ArgumentNullException>(() => keygen = new KeyGenerator(context, null));
            Utilities.AssertThrows <ArgumentNullException>(() => keygen = new KeyGenerator(null, keygen.SecretKey));
            Utilities.AssertThrows <ArgumentException>(() => keygen     = new KeyGenerator(context, secret));

            Utilities.AssertThrows <ArgumentNullException>(() => keygen.GaloisKeys(elts_null));
            Utilities.AssertThrows <ArgumentException>(() => keygen.GaloisKeys(elts));
            Utilities.AssertThrows <ArgumentNullException>(() => keygen.GaloisKeys(steps_null));
            Utilities.AssertThrows <ArgumentException>(() => keygen.GaloisKeys(steps));

            EncryptionParameters smallParms = new EncryptionParameters(SchemeType.CKKS);

            smallParms.PolyModulusDegree = 128;
            smallParms.CoeffModulus      = CoeffModulus.Create(smallParms.PolyModulusDegree, new int[] { 60 });
            context = new SEALContext(smallParms, true, SecLevelType.None);
            keygen  = new KeyGenerator(context);
            Utilities.AssertThrows <InvalidOperationException>(() => keygen.RelinKeys());
            Utilities.AssertThrows <InvalidOperationException>(() => keygen.GaloisKeys());
        }
Exemple #2
0
        public void KeyStepTest()
        {
            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
            {
                PolyModulusDegree = 64,
                CoeffModulus      = new List <SmallModulus>()
                {
                    DefaultParams.SmallMods60Bit(0)
                }
            };
            SEALContext  context = SEALContext.Create(parms);
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys(decompositionBitCount: 15, steps: new int[] { 1, 2, 3 });

            Assert.IsNotNull(keys);

            Assert.AreEqual(15, keys.DecompositionBitCount);
            Assert.AreEqual(3ul, keys.Size);

            Assert.IsFalse(keys.HasKey(1));
            Assert.IsTrue(keys.HasKey(3));
            Assert.IsFalse(keys.HasKey(5));
            Assert.IsFalse(keys.HasKey(7));
            Assert.IsTrue(keys.HasKey(9));
            Assert.IsFalse(keys.HasKey(11));
            Assert.IsFalse(keys.HasKey(13));
            Assert.IsFalse(keys.HasKey(15));
            Assert.IsFalse(keys.HasKey(17));
            Assert.IsFalse(keys.HasKey(19));
            Assert.IsFalse(keys.HasKey(21));
            Assert.IsFalse(keys.HasKey(23));
            Assert.IsFalse(keys.HasKey(25));
            Assert.IsTrue(keys.HasKey(27));
        }
        /// <summary>
        /// Constructor for MainWindow
        /// </summary>
        public MainWindow()
        {
            // Initialize in background thread
            Task.Run(() =>
            {
                KeyGenerator keygen = new KeyGenerator(GlobalProperties.Context);

                encryptor_ = new Encryptor(GlobalProperties.Context, keygen.PublicKey);
                decryptor_ = new Decryptor(GlobalProperties.Context, keygen.SecretKey);
                encoder_   = new BatchEncoder(GlobalProperties.Context);

                rlk_ = keygen.RelinKeys(decompositionBitCount: GlobalProperties.RelinKeysDBC);

                List <int> rotCounts = new List <int>();
                for (int i = (int)encoder_.SlotCount / GlobalProperties.MatrixSizeMax; i < (int)encoder_.SlotCount / 2; i *= 2)
                {
                    rotCounts.Add(i);
                }
                rotCounts.Add(0);
                galk_ = keygen.GaloisKeys(decompositionBitCount: GlobalProperties.GaloisKeysDBC, steps: rotCounts);

                // Choose the Session ID
                RandomizeSID();
            });

            InitializeComponent();
        }
Exemple #4
0
        public void KeyTest()
        {
            SEALContext  context = GlobalContext.BFVContext;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys       keys   = keygen.GaloisKeys();
            MemoryPoolHandle handle = keys.Pool;

            Assert.IsNotNull(keys);
            Assert.AreEqual(24ul, keys.Size);

            Assert.IsFalse(keys.HasKey(galoisElt: 1));
            Assert.IsTrue(keys.HasKey(galoisElt: 3));
            Assert.IsFalse(keys.HasKey(galoisElt: 5));
            Assert.IsFalse(keys.HasKey(galoisElt: 7));
            Assert.IsTrue(keys.HasKey(galoisElt: 9));
            Assert.IsFalse(keys.HasKey(galoisElt: 11));

            IEnumerable <PublicKey> key = keys.Key(3);

            Assert.AreEqual(4, key.Count());

            IEnumerable <PublicKey> key2 = keys.Key(9);

            Assert.AreEqual(4, key2.Count());

            Assert.IsTrue(handle.AllocByteCount > 0ul);
        }
Exemple #5
0
        public void KeyStepTest()
        {
            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
            {
                PolyModulusDegree = 64,
                CoeffModulus      = CoeffModulus.Create(64, new int[] { 60, 60 })
            };
            SEALContext context = new SEALContext(parms,
                                                  expandModChain: false,
                                                  secLevel: SecLevelType.None);
            KeyGenerator keygen = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys(steps: new int[] { 1, 2, 3 });

            Assert.IsNotNull(keys);

            Assert.AreEqual(3ul, keys.Size);

            Assert.IsFalse(keys.HasKey(1));
            Assert.IsTrue(keys.HasKey(3));
            Assert.IsFalse(keys.HasKey(5));
            Assert.IsFalse(keys.HasKey(7));
            Assert.IsTrue(keys.HasKey(9));
            Assert.IsFalse(keys.HasKey(11));
            Assert.IsFalse(keys.HasKey(13));
            Assert.IsFalse(keys.HasKey(15));
            Assert.IsFalse(keys.HasKey(17));
            Assert.IsFalse(keys.HasKey(19));
            Assert.IsFalse(keys.HasKey(21));
            Assert.IsFalse(keys.HasKey(23));
            Assert.IsFalse(keys.HasKey(25));
            Assert.IsTrue(keys.HasKey(27));
        }
Exemple #6
0
        public void KeyTest()
        {
            SEALContext  context = GlobalContext.Context;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys       keys   = keygen.GaloisKeys(decompositionBitCount: 30);
            MemoryPoolHandle handle = keys.Pool;

            Assert.IsNotNull(keys);
            Assert.AreEqual(30, keys.DecompositionBitCount);
            Assert.AreEqual(22ul, keys.Size);

            Assert.IsFalse(keys.HasKey(galoisElt: 1));
            Assert.IsTrue(keys.HasKey(galoisElt: 3));
            Assert.IsFalse(keys.HasKey(galoisElt: 5));
            Assert.IsFalse(keys.HasKey(galoisElt: 7));
            Assert.IsTrue(keys.HasKey(galoisElt: 9));
            Assert.IsFalse(keys.HasKey(galoisElt: 11));

            IEnumerable <Ciphertext> key = keys.Key(3);

            Assert.AreEqual(2, key.Count());

            IEnumerable <Ciphertext> key2 = keys.Key(9);

            Assert.AreEqual(2, key2.Count());

            Assert.IsTrue(handle.AllocByteCount > 0ul);
        }
        public void ScaleTest()
        {
            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
            {
                PolyModulusDegree = 8,
                CoeffModulus      = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 })
            };
            SEALContext context = new SEALContext(parms,
                                                  expandModChain: true,
                                                  secLevel: SecLevelType.None);
            KeyGenerator keygen     = new KeyGenerator(context);
            GaloisKeys   galoisKeys = keygen.GaloisKeys();
            Encryptor    encryptor  = new Encryptor(context, keygen.PublicKey);
            Evaluator    evaluator  = new Evaluator(context);
            CKKSEncoder  encoder    = new CKKSEncoder(context);

            MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceNew);

            Assert.AreEqual(0ul, pool.AllocByteCount);

            Ciphertext encrypted = new Ciphertext(pool);
            Plaintext  plain     = new Plaintext();

            MemoryPoolHandle cipherPool = encrypted.Pool;

            Assert.IsNotNull(cipherPool);
            Assert.AreEqual(0ul, cipherPool.AllocByteCount);

            List <Complex> input = new List <Complex>()
            {
                new Complex(1, 1),
                new Complex(2, 2),
                new Complex(3, 3),
                new Complex(4, 4)
            };
            double delta = Math.Pow(2, 70);

            encoder.Encode(input, context.FirstParmsId, delta, plain);
            encryptor.Encrypt(plain, encrypted);

            Assert.AreEqual(delta, encrypted.Scale, delta: Math.Pow(2, 60));

            Ciphertext encrypted2 = new Ciphertext();

            encrypted2.Set(encrypted);
            Assert.AreEqual(delta, encrypted2.Scale, delta: Math.Pow(2, 60));

            evaluator.RescaleToNextInplace(encrypted);

            Assert.AreEqual(Math.Pow(2, 30), encrypted.Scale, delta: 10000);
            Assert.AreNotEqual(0ul, cipherPool.AllocByteCount);

            double newScale = Math.Pow(2, 10);

            encrypted.Scale = newScale;
            Assert.AreEqual(newScale, encrypted.Scale, delta: 100);
        }
Exemple #8
0
 /// <summary>
 /// Convert a GaloisKeys object to a Base64 string
 /// </summary>
 /// <param name="galk">GaloisKeys to convert</param>
 /// <returns>Base64 string representing the GaloisKeys</returns>
 public static string GaloisKeysToBase64(KeyGenerator keygen, List <int> rotations)
 {
     using (MemoryStream ms = new MemoryStream())
     {
         // Saving directly to stream; this compresses the size in half
         keygen.GaloisKeys(rotations).Save(ms);
         byte[] bytes = ms.ToArray();
         return(Convert.ToBase64String(bytes));
     }
 }
Exemple #9
0
        public void SaveLoadTest()
        {
            SEALContext  context = GlobalContext.Context;
            KeyGenerator keyGen  = new KeyGenerator(context);

            GaloisKeys keys  = keyGen.GaloisKeys(decompositionBitCount: 30);
            GaloisKeys other = new GaloisKeys();

            Assert.IsNotNull(keys);
            Assert.AreEqual(30, keys.DecompositionBitCount);
            Assert.AreEqual(22ul, keys.Size);

            using (MemoryStream ms = new MemoryStream())
            {
                keys.Save(ms);

                ms.Seek(offset: 0, loc: SeekOrigin.Begin);

                other.Load(context, ms);
            }

            Assert.AreEqual(30, other.DecompositionBitCount);
            Assert.AreEqual(22ul, other.Size);
            Assert.IsTrue(other.IsMetadataValidFor(context));

            List <IEnumerable <Ciphertext> > keysData  = new List <IEnumerable <Ciphertext> >(keys.Data);
            List <IEnumerable <Ciphertext> > otherData = new List <IEnumerable <Ciphertext> >(other.Data);

            Assert.AreEqual(keysData.Count, otherData.Count);
            for (int i = 0; i < keysData.Count; i++)
            {
                List <Ciphertext> keysCiphers  = new List <Ciphertext>(keysData[i]);
                List <Ciphertext> otherCiphers = new List <Ciphertext>(otherData[i]);

                Assert.AreEqual(keysCiphers.Count, otherCiphers.Count);

                for (int j = 0; j < keysCiphers.Count; j++)
                {
                    Ciphertext keysCipher  = keysCiphers[j];
                    Ciphertext otherCipher = otherCiphers[j];

                    Assert.AreEqual(keysCipher.Size, otherCipher.Size);
                    Assert.AreEqual(keysCipher.PolyModulusDegree, otherCipher.PolyModulusDegree);
                    Assert.AreEqual(keysCipher.CoeffModCount, otherCipher.CoeffModCount);

                    ulong coeffCount = keysCipher.Size * keysCipher.PolyModulusDegree * keysCipher.CoeffModCount;
                    for (ulong k = 0; k < coeffCount; k++)
                    {
                        Assert.AreEqual(keysCipher[k], otherCipher[k]);
                    }
                }
            }
        }
Exemple #10
0
        public void SaveLoadTest()
        {
            SEALContext  context = GlobalContext.BFVContext;
            KeyGenerator keyGen  = new KeyGenerator(context);

            GaloisKeys keys  = keyGen.GaloisKeys();
            GaloisKeys other = new GaloisKeys();

            Assert.IsNotNull(keys);
            Assert.AreEqual(24ul, keys.Size);

            using (MemoryStream ms = new MemoryStream())
            {
                keys.Save(ms);

                ms.Seek(offset: 0, loc: SeekOrigin.Begin);

                other.Load(context, ms);
            }

            Assert.AreEqual(24ul, other.Size);
            Assert.IsTrue(ValCheck.IsValidFor(other, context));

            List <IEnumerable <PublicKey> > keysData  = new List <IEnumerable <PublicKey> >(keys.Data);
            List <IEnumerable <PublicKey> > otherData = new List <IEnumerable <PublicKey> >(other.Data);

            Assert.AreEqual(keysData.Count, otherData.Count);
            for (int i = 0; i < keysData.Count; i++)
            {
                List <PublicKey> keysCiphers  = new List <PublicKey>(keysData[i]);
                List <PublicKey> otherCiphers = new List <PublicKey>(otherData[i]);

                Assert.AreEqual(keysCiphers.Count, otherCiphers.Count);

                for (int j = 0; j < keysCiphers.Count; j++)
                {
                    PublicKey keysCipher  = keysCiphers[j];
                    PublicKey otherCipher = otherCiphers[j];

                    Assert.AreEqual(keysCipher.Data.Size, otherCipher.Data.Size);
                    Assert.AreEqual(keysCipher.Data.PolyModulusDegree, otherCipher.Data.PolyModulusDegree);
                    Assert.AreEqual(keysCipher.Data.CoeffModCount, otherCipher.Data.CoeffModCount);

                    ulong coeffCount = keysCipher.Data.Size * keysCipher.Data.PolyModulusDegree * keysCipher.Data.CoeffModCount;
                    for (ulong k = 0; k < coeffCount; k++)
                    {
                        Assert.AreEqual(keysCipher.Data[k], otherCipher.Data[k]);
                    }
                }
            }
        }
Exemple #11
0
			//private static bool _firstTime = true;

            //private static Decryptor _decryptor;

            public SecureSvc(int nRows, double[][] vectors, double[][] coefficients, double[] intercepts,
				 String kernel, double gamma, double coef0, ulong degree , int power)
			{


				//this._nRows			= nRows;

				this._vectors		= vectors;
				this._coefficients	= coefficients;
				this._intercepts		= intercepts;

				this._kernel			= Enum.Parse<Kernel>(kernel, true);
				this._gamma			= gamma;
				this._coef0			= coef0;
				this._degree			= degree;
				this._power			= power;
				EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

				ulong polyModulusDegree = 16384;
				
				if (power >= 20 && power < 40 )
				{
					parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree,
						new int[] { 60, 20, 21, 22, 23, 24, 25, 26, 27, 60 });
				}
				else if (power >= 40 && power < 60)
				{
					parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree,
						new int[] { 60, 40, 40, 40, 40, 40, 40, 40 , 60 });
				}
				else if (power == 60)
				{
					polyModulusDegree = 32768;
                    parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree,
						new int[] { 60, 60, 60, 60, 60, 60, 60, 60, 60 });
				}
				parms.PolyModulusDegree = polyModulusDegree;
                _context = new SEALContext(parms);

				KeyGenerator keygen = new KeyGenerator(_context);
				_publicKey = keygen.PublicKey;
				_secretKey = keygen.SecretKey;
				_relinKeys = keygen.RelinKeys();
				_galoisKeys = keygen.GaloisKeys();

				_encryptor = new Encryptor(_context, _publicKey);
				_evaluator = new Evaluator(_context);
				_decryptor = new Decryptor(_context, _secretKey);
				_encoder = new CKKSEncoder(_context);
			}
Exemple #12
0
        public void CreateNonEmptyTest()
        {
            SEALContext  context = GlobalContext.BFVContext;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys();

            Assert.IsNotNull(keys);
            Assert.AreEqual(24ul, keys.Size);

            GaloisKeys copy = new GaloisKeys(keys);

            Assert.IsNotNull(copy);
            Assert.AreEqual(24ul, copy.Size);
        }
Exemple #13
0
        public void KeyEltTest()
        {
            SEALContext  context = GlobalContext.BFVContext;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys(galoisElts: new ulong[] { 1, 3 });

            Assert.IsNotNull(keys);

            Assert.AreEqual(2ul, keys.Size);

            Assert.IsTrue(keys.HasKey(1));
            Assert.IsTrue(keys.HasKey(3));
            Assert.IsFalse(keys.HasKey(5));
        }
Exemple #14
0
        public void CreateNonEmptyTest()
        {
            SEALContext  context = GlobalContext.Context;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys(decompositionBitCount: 30);

            Assert.IsNotNull(keys);
            Assert.AreEqual(30, keys.DecompositionBitCount);
            Assert.AreEqual(22ul, keys.Size);

            GaloisKeys copy = new GaloisKeys(keys);

            Assert.IsNotNull(copy);
            Assert.AreEqual(30, copy.DecompositionBitCount);
            Assert.AreEqual(22ul, copy.Size);
        }
Exemple #15
0
        public void SetTest()
        {
            SEALContext  context = GlobalContext.BFVContext;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys();

            Assert.IsNotNull(keys);
            Assert.AreEqual(24ul, keys.Size);

            GaloisKeys keys2 = new GaloisKeys();

            Assert.IsNotNull(keys2);
            Assert.AreEqual(0ul, keys2.Size);

            keys2.Set(keys);

            Assert.AreNotSame(keys, keys2);
            Assert.AreEqual(24ul, keys2.Size);
        }
Exemple #16
0
        public void SetTest()
        {
            SEALContext  context = GlobalContext.Context;
            KeyGenerator keygen  = new KeyGenerator(context);

            GaloisKeys keys = keygen.GaloisKeys(decompositionBitCount: 30);

            Assert.IsNotNull(keys);
            Assert.AreEqual(30, keys.DecompositionBitCount);
            Assert.AreEqual(22ul, keys.Size);

            GaloisKeys keys2 = new GaloisKeys();

            Assert.IsNotNull(keys2);
            Assert.AreEqual(0, keys2.DecompositionBitCount);
            Assert.AreEqual(0ul, keys2.Size);

            keys2.Set(keys);

            Assert.AreNotSame(keys, keys2);
            Assert.AreEqual(30, keys2.DecompositionBitCount);
            Assert.AreEqual(22ul, keys2.Size);
        }
Exemple #17
0
        private static void ExampleRotationCKKS()
        {
            Utilities.PrintExampleBanner("Example: Rotation / Rotation in CKKS");

            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

            ulong polyModulusDegree = 8192;

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

            SEALContext context = new SEALContext(parms);

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

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

            CKKSEncoder ckksEncoder = new CKKSEncoder(context);

            ulong slotCount = ckksEncoder.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);

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

            Utilities.PrintLine();
            Console.WriteLine("Encode and encrypt.");
            Plaintext plain = new Plaintext();

            ckksEncoder.Encode(input, scale, plain);
            Ciphertext encrypted = new Ciphertext();

            encryptor.Encrypt(plain, encrypted);

            Ciphertext rotated = new Ciphertext();

            Utilities.PrintLine();
            Console.WriteLine("Rotate 2 steps left.");
            evaluator.RotateVector(encrypted, 2, galKeys, rotated);
            Console.WriteLine("    + Decrypt and decode ...... Correct.");
            decryptor.Decrypt(encrypted, plain);
            List <double> result = new List <double>();

            ckksEncoder.Decode(plain, result);
            Utilities.PrintVector(result, 3, 7);

            /*
             * With the CKKS scheme it is also possible to evaluate a complex conjugation on
             * a vector of encrypted complex numbers, using Evaluator.ComplexConjugate. This
             * is in fact a kind of rotation, and requires also Galois keys.
             */
        }
        private static void BFVPerformanceTest(SEALContext context)
        {
            Stopwatch timer;

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

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

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

            Console.WriteLine("Done");

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

            RelinKeys  relinKeys = null;
            GaloisKeys galKeys   = null;

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

                if (!context.KeyContextData.Qualifiers.UsingBatching)
                {
                    Console.WriteLine("Given encryption parameters do not support batching.");
                    return;
                }

                /*
                 * 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();
                galKeys = keygen.GaloisKeys();
                micros  = (int)(timer.Elapsed.TotalMilliseconds * 1000);
                Console.WriteLine($"Done [{micros} microseconds]");
            }

            Encryptor      encryptor    = new Encryptor(context, publicKey);
            Decryptor      decryptor    = new Decryptor(context, secretKey);
            Evaluator      evaluator    = new Evaluator(context);
            BatchEncoder   batchEncoder = new BatchEncoder(context);
            IntegerEncoder encoder      = new IntegerEncoder(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();

            /*
             * 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] = (ulong)rnd.Next() % plainModulus.Value;
            }

            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.
                 */
                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.
                 */
                Ciphertext encrypted = new Ciphertext(context);
                timeEncryptSum.Start();
                encryptor.Encrypt(plain, encrypted);
                timeEncryptSum.Stop();

                /*
                 * [Decryption]
                 * We decrypt what we just encrypted.
                 */
                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.
                 */
                Ciphertext encrypted1 = new Ciphertext(context);
                encryptor.Encrypt(encoder.Encode(i), encrypted1);
                Ciphertext encrypted2 = new Ciphertext(context);
                encryptor.Encrypt(encoder.Encode(i + 1), 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;
                    int randomRotation = rnd.Next() % rowSize;
                    timeRotateRowsRandomSum.Start();
                    evaluator.RotateRowsInplace(encrypted, randomRotation, galKeys);
                    timeRotateRowsRandomSum.Stop();

                    /*
                     * [Rotate Columns]
                     * Nothing surprising here.
                     */
                    timeRotateColumnsSum.Start();
                    evaluator.RotateColumnsInplace(encrypted, galKeys);
                    timeRotateColumnsSum.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);

            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.Out.Flush();
        }
        private static void CKKSPerformanceTest(SEALContext context)
        {
            Stopwatch timer;

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

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

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

            Console.WriteLine("Done");

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

            RelinKeys  relinKeys = null;
            GaloisKeys galKeys   = null;

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

                if (!context.KeyContextData.Qualifiers.UsingBatching)
                {
                    Console.WriteLine("Given encryption parameters do not support batching.");
                    return;
                }

                /*
                 * 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();
                galKeys = keygen.GaloisKeys();
                micros  = (int)(timer.Elapsed.TotalMilliseconds * 1000);
                Console.WriteLine($"Done [{micros} microseconds]");
            }

            Encryptor   encryptor   = new Encryptor(context, publicKey);
            Decryptor   decryptor   = new Decryptor(context, secretKey);
            Evaluator   evaluator   = new Evaluator(context);
            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();

            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);
                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]
                 */
                Ciphertext encrypted = new Ciphertext(context);
                timeEncryptSum.Start();
                encryptor.Encrypt(plain, encrypted);
                timeEncryptSum.Stop();

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

                /*
                 * [Add]
                 */
                Ciphertext encrypted1 = new Ciphertext(context);
                ckksEncoder.Encode(i + 1, plain);
                encryptor.Encrypt(plain, encrypted1);
                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]
                     */
                    int randomRotation = rnd.Next() % (int)ckksEncoder.SlotCount;
                    timeRotateRandomSum.Start();
                    evaluator.RotateVectorInplace(encrypted, randomRotation, galKeys);
                    timeRotateRandomSum.Stop();

                    /*
                     * [Complex Conjugate]
                     */
                    timeConjugateSum.Start();
                    evaluator.ComplexConjugateInplace(encrypted, galKeys);
                    timeConjugateSum.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);

            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.Out.Flush();
        }
Exemple #20
0
        private static void ExampleLevels()
        {
            Utilities.PrintExampleBanner("Example: Levels");

            /*
             * In this examples we describe the concept of `levels' in BFV and CKKS and the
             * related objects that represent them in Microsoft SEAL.
             *
             * In Microsoft SEAL a set of encryption parameters (excluding the random number
             * generator) is identified uniquely by a SHA-3 hash of the parameters. This
             * hash is called the `ParmsId' and can be easily accessed and printed at any
             * time. The hash will change as soon as any of the parameters is changed.
             *
             * When a SEALContext is created from a given EncryptionParameters instance,
             * Microsoft SEAL automatically creates a so-called `modulus switching chain',
             * which is a chain of other encryption parameters derived from the original set.
             * The parameters in the modulus switching chain are the same as the original
             * parameters with the exception that size of the coefficient modulus is
             * decreasing going down the chain. More precisely, each parameter set in the
             * chain attempts to remove the last coefficient modulus prime from the
             * previous set; this continues until the parameter set is no longer valid
             * (e.g., PlainModulus is larger than the remaining CoeffModulus). It is easy
             * to walk through the chain and access all the parameter sets. Additionally,
             * each parameter set in the chain has a `chain index' that indicates its
             * position in the chain so that the last set has index 0. We say that a set
             * of encryption parameters, or an object carrying those encryption parameters,
             * is at a higher level in the chain than another set of parameters if its the
             * chain index is bigger, i.e., it is earlier in the chain.
             *
             * Each set of parameters in the chain involves unique pre-computations performed
             * when the SEALContext is created, and stored in a SEALContext.ContextData
             * object. The chain is basically a linked list of SEALContext.ContextData
             * objects, and can easily be accessed through the SEALContext at any time. Each
             * node can be identified by the ParmsId of its specific encryption parameters
             * (PolyModulusDegree remains the same but CoeffModulus varies).
             */
            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
            ulong polyModulusDegree    = 8192;

            parms.PolyModulusDegree = polyModulusDegree;

            /*
             * In this example we use a custom CoeffModulus, consisting of 5 primes of
             * sizes 50, 30, 30, 50, and 50 bits. Note that this is still OK according to
             * the explanation in `1_BFV_Basics.cs'. Indeed,
             *
             *  CoeffModulus.MaxBitCount(polyModulusDegree)
             *
             * returns 218 (less than 50+30+30+50+50=210).
             *
             * Due to the modulus switching chain, the order of the 5 primes is significant.
             * The last prime has a special meaning and we call it the `special prime'. Thus,
             * the first parameter set in the modulus switching chain is the only one that
             * involves the special prime. All key objects, such as SecretKey, are created
             * at this highest level. All data objects, such as Ciphertext, can be only at
             * lower levels. The special modulus should be as large as the largest of the
             * other primes in the CoeffModulus, although this is not a strict requirement.
             *
             *       special prime +---------+
             |
             |                               v
             | CoeffModulus: { 50, 30, 30, 50, 50 }  +---+  Level 4 (all keys; `key level')
             |
             |
             |  CoeffModulus: { 50, 30, 30, 50 }  +---+  Level 3 (highest `data level')
             |
             |
             |      CoeffModulus: { 50, 30, 30 }  +---+  Level 2
             |
             |
             |          CoeffModulus: { 50, 30 }  +---+  Level 1
             |
             |
             |              CoeffModulus: { 50 }  +---+  Level 0 (lowest level)
             */
            parms.CoeffModulus = CoeffModulus.Create(
                polyModulusDegree, new int[] { 50, 30, 30, 50, 50 });

            /*
             * In this example the PlainModulus does not play much of a role; we choose
             * some reasonable value.
             */
            parms.PlainModulus = new SmallModulus(1 << 20);

            SEALContext context = new SEALContext(parms);

            Utilities.PrintParameters(context);

            /*
             * There are convenience method for accessing the SEALContext.ContextData for
             * some of the most important levels:
             *
             *  SEALContext.KeyContextData: access to key level ContextData
             *  SEALContext.FirstContextData: access to highest data level ContextData
             *  SEALContext.LastContextData: access to lowest level ContextData
             *
             * We iterate over the chain and print the ParmsId for each set of parameters.
             */
            Console.WriteLine();
            Utilities.PrintLine();
            Console.WriteLine("Print the modulus switching chain.");

            /*
             * First print the key level parameter information.
             */
            SEALContext.ContextData contextData = context.KeyContextData;
            Console.WriteLine("----> Level (chain index): {0} ...... KeyContextData",
                              contextData.ChainIndex);
            Console.WriteLine($"      ParmsId: {contextData.ParmsId}");
            Console.Write("      CoeffModulus primes: ");
            foreach (SmallModulus prime in contextData.Parms.CoeffModulus)
            {
                Console.Write($"{Utilities.ULongToString(prime.Value)} ");
            }
            Console.WriteLine();
            Console.WriteLine("\\");
            Console.Write(" \\--> ");

            /*
             * Next iterate over the remaining (data) levels.
             */
            contextData = context.FirstContextData;
            while (null != contextData)
            {
                Console.Write($"Level (chain index): {contextData.ChainIndex}");
                if (contextData.ParmsId.Equals(context.FirstParmsId))
                {
                    Console.WriteLine(" ...... FirstContextData");
                }
                else if (contextData.ParmsId.Equals(context.LastParmsId))
                {
                    Console.WriteLine(" ...... LastContextData");
                }
                else
                {
                    Console.WriteLine();
                }
                Console.WriteLine($"      ParmsId: {contextData.ParmsId}");
                Console.Write("      CoeffModulus primes: ");
                foreach (SmallModulus prime in contextData.Parms.CoeffModulus)
                {
                    Console.Write($"{Utilities.ULongToString(prime.Value)} ");
                }
                Console.WriteLine();
                Console.WriteLine("\\");
                Console.Write(" \\--> ");

                /*
                 * Step forward in the chain.
                 */
                contextData = contextData.NextContextData;
            }
            Console.WriteLine("End of chain reached");
            Console.WriteLine();

            /*
             * We create some keys and check that indeed they appear at the highest level.
             */
            KeyGenerator keygen     = new KeyGenerator(context);
            PublicKey    publicKey  = keygen.PublicKey;
            SecretKey    secretKey  = keygen.SecretKey;
            RelinKeys    relinKeys  = keygen.RelinKeys();
            GaloisKeys   galoisKeys = keygen.GaloisKeys();

            Utilities.PrintLine();
            Console.WriteLine("Print the parameter IDs of generated elements.");
            Console.WriteLine($"    + publicKey:  {publicKey.ParmsId}");
            Console.WriteLine($"    + secretKey:  {secretKey.ParmsId}");
            Console.WriteLine($"    + relinKeys:  {relinKeys.ParmsId}");
            Console.WriteLine($"    + galoisKeys: {galoisKeys.ParmsId}");

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

            /*
             * In the BFV scheme plaintexts do not carry a ParmsId, but ciphertexts do. Note
             * how the freshly encrypted ciphertext is at the highest data level.
             */
            Plaintext  plain     = new Plaintext("1x^3 + 2x^2 + 3x^1 + 4");
            Ciphertext encrypted = new Ciphertext();

            encryptor.Encrypt(plain, encrypted);
            Console.WriteLine($"    + plain:      {plain.ParmsId} (not set in BFV)");
            Console.WriteLine($"    + encrypted:  {encrypted.ParmsId}");
            Console.WriteLine();

            /*
             * `Modulus switching' is a technique of changing the ciphertext parameters down
             * in the chain. The function Evaluator.ModSwitchToNext always switches to the
             * next level down the chain, whereas Evaluator.ModSwitchTo switches to a parameter
             * set down the chain corresponding to a given ParmsId. However, it is impossible
             * to switch up in the chain.
             */
            Utilities.PrintLine();
            Console.WriteLine("Perform modulus switching on encrypted and print.");
            contextData = context.FirstContextData;
            Console.Write("----> ");
            while (null != contextData.NextContextData)
            {
                Console.WriteLine($"Level (chain index): {contextData.ChainIndex}");
                Console.WriteLine($"      ParmsId of encrypted: {contextData.ParmsId}");
                Console.WriteLine("      Noise budget at this level: {0} bits",
                                  decryptor.InvariantNoiseBudget(encrypted));
                Console.WriteLine("\\");
                Console.Write(" \\--> ");
                evaluator.ModSwitchToNextInplace(encrypted);
                contextData = contextData.NextContextData;
            }
            Console.WriteLine($"Level (chain index): {contextData.ChainIndex}");
            Console.WriteLine($"      ParmsId of encrypted: {contextData.ParmsId}");
            Console.WriteLine("      Noise budget at this level: {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted));
            Console.WriteLine("\\");
            Console.Write(" \\--> ");
            Console.WriteLine("End of chain reached");
            Console.WriteLine();

            /*
             * At this point it is hard to see any benefit in doing this: we lost a huge
             * amount of noise budget (i.e., computational power) at each switch and seemed
             * to get nothing in return. Decryption still works.
             */
            Utilities.PrintLine();
            Console.WriteLine("Decrypt still works after modulus switching.");
            decryptor.Decrypt(encrypted, plain);
            Console.WriteLine($"    + Decryption of encrypted: {plain} ...... Correct.");
            Console.WriteLine();

            /*
             * However, there is a hidden benefit: the size of the ciphertext depends
             * linearly on the number of primes in the coefficient modulus. Thus, if there
             * is no need or intention to perform any further computations on a given
             * ciphertext, we might as well switch it down to the smallest (last) set of
             * parameters in the chain before sending it back to the secret key holder for
             * decryption.
             *
             * Also the lost noise budget is actually not as issue at all, if we do things
             * right, as we will see below.
             *
             * First we recreate the original ciphertext and perform some computations.
             */
            Console.WriteLine("Computation is more efficient with modulus switching.");
            Utilities.PrintLine();
            Console.WriteLine("Compute the fourth power.");
            encryptor.Encrypt(plain, encrypted);
            Console.WriteLine("    + Noise budget before squaring:         {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted));
            evaluator.SquareInplace(encrypted);
            evaluator.RelinearizeInplace(encrypted, relinKeys);
            Console.WriteLine("    + Noise budget after squaring:          {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted));

            /*
             * From the print-out we see that the noise budget after these computations is
             * just slightly below the level we would have in a fresh ciphertext after one
             * modulus switch (135 bits). Surprisingly, in this case modulus switching has
             * no effect at all on the noise budget.
             */
            evaluator.ModSwitchToNextInplace(encrypted);
            Console.WriteLine("    + Noise budget after modulus switching: {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted));


            /*
             * This means that there is no harm at all in dropping some of the coefficient
             * modulus after doing enough computations. In some cases one might want to
             * switch to a lower level slightly earlier, actually sacrificing some of the
             * noise budget in the process, to gain computational performance from having
             * smaller parameters. We see from the print-out that the next modulus switch
             * should be done ideally when the noise budget is down to around 81 bits.
             */
            evaluator.SquareInplace(encrypted);
            evaluator.RelinearizeInplace(encrypted, relinKeys);
            Console.WriteLine("    + Noise budget after squaring:          {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted));
            evaluator.ModSwitchToNextInplace(encrypted);
            Console.WriteLine("    + Noise budget after modulus switching: {0} bits",
                              decryptor.InvariantNoiseBudget(encrypted));

            /*
             * At this point the ciphertext still decrypts correctly, has very small size,
             * and the computation was as efficient as possible. Note that the decryptor
             * can be used to decrypt a ciphertext at any level in the modulus switching
             * chain.
             */
            decryptor.Decrypt(encrypted, plain);
            Console.WriteLine("    + Decryption of fourth power (hexadecimal) ...... Correct.");
            Console.WriteLine($"    {plain}");
            Console.WriteLine();

            /*
             * In BFV modulus switching is not necessary and in some cases the user might
             * not want to create the modulus switching chain, except for the highest two
             * levels. This can be done by passing a bool `false' to SEALContext constructor.
             */
            context = new SEALContext(parms, expandModChain: false);

            /*
             * We can check that indeed the modulus switching chain has been created only
             * for the highest two levels (key level and highest data level). The following
             * loop should execute only once.
             */
            Console.WriteLine("Optionally disable modulus switching chain expansion.");
            Utilities.PrintLine();
            Console.WriteLine("Print the modulus switching chain.");
            Console.Write("----> ");
            for (contextData = context.KeyContextData; null != contextData;
                 contextData = contextData.NextContextData)
            {
                Console.WriteLine($"Level (chain index): {contextData.ChainIndex}");
                Console.WriteLine($"      ParmsId of encrypted: {contextData.ParmsId}");
                Console.Write("      CoeffModulus primes: ");
                foreach (SmallModulus prime in contextData.Parms.CoeffModulus)
                {
                    Console.Write($"{Utilities.ULongToString(prime.Value)} ");
                }
                Console.WriteLine();
                Console.WriteLine("\\");
                Console.Write(" \\--> ");
            }
            Console.WriteLine("End of chain reached");
            Console.WriteLine();

            /*
             * It is very important to understand how this example works since in the CKKS
             * scheme modulus switching has a much more fundamental purpose and the next
             * examples will be difficult to understand unless these basic properties are
             * totally clear.
             */
        }
        public void SeededKeyTest()
        {
            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
            {
                PolyModulusDegree = 8,
                PlainModulus      = new Modulus(257),
                CoeffModulus      = CoeffModulus.Create(8, new int[] { 40, 40 })
            };
            SEALContext context = new SEALContext(parms,
                                                  expandModChain: false,
                                                  secLevel: SecLevelType.None);
            KeyGenerator keygen    = new KeyGenerator(context);
            Encryptor    encryptor = new Encryptor(context, keygen.PublicKey);
            Decryptor    decryptor = new Decryptor(context, keygen.SecretKey);
            Evaluator    evaluator = new Evaluator(context);
            BatchEncoder encoder   = new BatchEncoder(context);

            GaloisKeys galoisKeys = new GaloisKeys();

            using (MemoryStream stream = new MemoryStream())
            {
                keygen.GaloisKeys().Save(stream);
                stream.Seek(0, SeekOrigin.Begin);
                galoisKeys.Load(context, stream);
            }

            Plaintext    plain = new Plaintext();
            List <ulong> vec   = new List <ulong>
            {
                1, 2, 3, 4,
                5, 6, 7, 8
            };

            encoder.Encode(vec, plain);

            Ciphertext encrypted = new Ciphertext();
            Ciphertext encdest   = new Ciphertext();
            Plaintext  plaindest = new Plaintext();

            encryptor.Encrypt(plain, encrypted);
            evaluator.RotateColumns(encrypted, galoisKeys, encdest);
            decryptor.Decrypt(encdest, plaindest);
            encoder.Decode(plaindest, vec);

            Assert.IsTrue(AreCollectionsEqual(vec, new List <ulong>
            {
                5, 6, 7, 8,
                1, 2, 3, 4
            }));

            evaluator.RotateRows(encdest, -1, galoisKeys, encrypted);
            decryptor.Decrypt(encrypted, plaindest);
            encoder.Decode(plaindest, vec);

            Assert.IsTrue(AreCollectionsEqual(vec, new List <ulong>
            {
                8, 5, 6, 7,
                4, 1, 2, 3
            }));

            evaluator.RotateRowsInplace(encrypted, 2, galoisKeys);
            decryptor.Decrypt(encrypted, plaindest);
            encoder.Decode(plaindest, vec);

            Assert.IsTrue(AreCollectionsEqual(vec, new List <ulong>
            {
                6, 7, 8, 5,
                2, 3, 4, 1
            }));

            evaluator.RotateColumnsInplace(encrypted, galoisKeys);
            decryptor.Decrypt(encrypted, plaindest);
            encoder.Decode(plaindest, vec);

            Assert.IsTrue(AreCollectionsEqual(vec, new List <ulong>
            {
                2, 3, 4, 1,
                6, 7, 8, 5
            }));
        }
Exemple #22
0
        static async Task Main(string[] args)
        {
            Console.WriteLine("Secure Iris");

            // Get Input from resource file or as args
            double[][] features;
            int        numberOfFeatures = 4;
            int        numOfRows        = 0;

            // Option to load from args and not the whole dataset that is stored in resources
            if (args.Length >= numberOfFeatures)
            {
                numOfRows = args.Length / numberOfFeatures;
                // Features:
                features = new double[numOfRows][];
                for (int i = 0; i < numOfRows; i++)
                {
                    features[i] = new double[numberOfFeatures];
                }
                for (int i = 0, l = args.Length; i < l; i++)
                {
                    features[i / numberOfFeatures][i % numberOfFeatures] = Double.Parse(args[i]);
                }
            }

            else  // load the whole dataset from resources
            {
                List <double[]> rows = new List <double[]>();

                var bytes = Properties.Resources.iris;
                numOfRows = 0;
                features  = SVCUtilities.SvcUtilities.LoadFeatures(bytes, numberOfFeatures, ref numOfRows);
            }
            Stopwatch clientStopwatch = new Stopwatch();

            clientStopwatch.Start();

            //svm algorithm parametrs calculated in python : training result
            double[][] vectors = new double[3][];
            vectors[0] = new[] { 4.5, 2.3, 1.3, 0.3 };
            vectors[1] = new[] { 5.1, 3.3, 1.7, 0.5 };
            vectors[2] = new[] { 5.1, 2.5, 3.0, 1.1 };

            double[][] coefficients = new double[1][];
            coefficients[0] = new double[] { -0.07724840262003278, -0.6705185831514366, 0.7477669857714694 };
            double[] intercepts = { 1.453766563649063 };


            // SEAL parameters client side
            Console.WriteLine("SecureSVC : ");

            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

            ulong polyModulusDegree = 16384;
            int   power             = 40;

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

            if (power >= 20 && power < 40)
            {
                parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree,
                                                         new int[] { 60, 20, 21, 22, 23, 24, 25, 26, 27, 60 });
            }
            else if (power >= 40 && power < 60)
            {
                parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree,
                                                         new int[] { 60, 40, 40, 40, 40, 40, 40, 40, 60 });
            }
            else if (power == 60)
            {
                polyModulusDegree  = 32768;
                parms.CoeffModulus = CoeffModulus.Create(polyModulusDegree,
                                                         new int[] { 60, 60, 60, 60, 60, 60, 60, 60, 60 });
            }
            parms.PolyModulusDegree = polyModulusDegree;



            var context = new SEALContext(parms);
            // Key generation
            KeyGenerator keygen    = new KeyGenerator(context);
            var          publicKey = keygen.PublicKey;
            var          secretKey = keygen.SecretKey;
            var          relinKeys = keygen.RelinKeys();

            var galoisKeys = keygen.GaloisKeys();
            var encryptor  = new Encryptor(context, publicKey);

            var decryptor = new Decryptor(context, secretKey);
            var encoder   = new CKKSEncoder(context);

            clientStopwatch.Stop();


            using (System.IO.StreamWriter file =
                       new System.IO.StreamWriter(
                           $@"{OutputDir}IrisLinearSecured_{IsParallel}_{DateTime.Now.Day}_{DateTime.Now.ToShortTimeString().ToString().Replace(":", "_")}.txt")
                   )
            {
                // Only CONCEPT demonstation how to parrallel all the computation on all machine cpu's
                // Though the parallel here is done on the client side , in "real life" this parallel mechanism
                // Should on the server side
                if (IsParallel)
                {
                    int processorCount = Environment.ProcessorCount;
                    Console.WriteLine("Number Of Logical Processors: {0}", processorCount);

                    Svc[] machines = new Svc[processorCount];

                    Stopwatch[] innerProductStopwatchArr   = new Stopwatch[processorCount];
                    Stopwatch[] negateStopwatchArr         = new Stopwatch[processorCount];
                    Stopwatch[] degreeStopwatchArr         = new Stopwatch[processorCount];
                    Stopwatch[] serverDecisionStopWatchArr = new Stopwatch[processorCount];
                    Result[]    results = new Result[numOfRows];

                    Task[] tasks = new Task[processorCount];
                    for (int i = 0; i < processorCount; i++)
                    {
                        machines[i] = new Svc(vectors, coefficients, intercepts, "Linear", 0.25, 0.0, 3, 40, publicKey /*, secretKey*/, relinKeys, galoisKeys, 1, 4);
                        innerProductStopwatchArr[i]   = new Stopwatch();
                        negateStopwatchArr[i]         = new Stopwatch();
                        degreeStopwatchArr[i]         = new Stopwatch();
                        serverDecisionStopWatchArr[i] = new Stopwatch();
                    }
                    Stopwatch totalTime = new Stopwatch();
                    totalTime.Start();
                    for (int i = 0; i < numOfRows;)
                    {
                        for (int j = 0; j < processorCount && i < numOfRows; j++)
                        {
                            var secureSvc = machines[i % processorCount];
                            var feature   = features[i];
                            //Console.WriteLine($"\n\n $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
                            List <object> l = new List <object>();
                            l.Add(secureSvc);                  //0
                            l.Add(feature);                    //1
                            l.Add(i);                          //2
                            l.Add(encoder);                    //3
                            l.Add(encryptor);                  //4
                            l.Add(decryptor);                  //5
                            l.Add(innerProductStopwatchArr[i % processorCount]);
                            l.Add(degreeStopwatchArr[i % processorCount]);
                            l.Add(negateStopwatchArr[i % processorCount]);
                            l.Add(serverDecisionStopWatchArr[i % processorCount]);

                            l.Add(results);
                            tasks[j] = new TaskFactory().StartNew(new Action <object>((test) =>
                            {
                                List <object> l2 = (List <object>)test;

                                SinglePredict((Svc)l2[0], (double[])l2[1], (int)l2[2], (CKKSEncoder)l2[3], (Encryptor)l2[4], (Decryptor)l2[5], (Stopwatch)l2[6], (Stopwatch)l2[7], (Stopwatch)l2[8], (Stopwatch)l2[9], scale, (Result[])l2[10]);
                            }), l);
                            i++;
                        }

                        await Task.WhenAll(tasks);
                    }

                    totalTime.Stop();

                    for (int i = 0; i < numOfRows; i++)
                    {
                        var result = results[i];
                        file.WriteLine($"{i} , {result.Estimation} , {result.TotalValue} ");
                    }

                    double innerProductTime = 0;
                    double degreeTime       = 0;
                    double negateTime       = 0;
                    double serverTime       = 0;

                    for (int i = 0; i < processorCount; i++)
                    {
                        innerProductTime = innerProductStopwatchArr[i].ElapsedMilliseconds;
                        degreeTime       = degreeStopwatchArr[i].ElapsedMilliseconds;
                        negateTime       = negateStopwatchArr[i].ElapsedMilliseconds;
                        serverTime       = serverDecisionStopWatchArr[i].ElapsedMilliseconds;
                    }
                    file.WriteLine($" Client time :  {clientStopwatch.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Total time for {numOfRows} samples :  {totalTime.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Avg time  :  {totalTime.ElapsedMilliseconds * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Inner Product time for  {numOfRows} samples :  {innerProductTime} ms  ");
                    file.WriteLine($" Inner Product Avg time  :  {innerProductTime * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Degree time for  {numOfRows} samples :  {degreeTime} ms  ");
                    file.WriteLine($" Degree Avg time  :  {degreeTime * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Negate time for  {numOfRows} samples :  {negateTime} ms  ");
                    file.WriteLine($" Negate Avg time  :  {negateTime * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Decision time for  {numOfRows} samples :  {serverTime} ms  ");
                    file.WriteLine($" Decision Avg time  :  {serverTime * 1000 / numOfRows} microSec ");
                }
                else
                {
                    //Initiate Stopwatch for performance measure
                    Stopwatch innerProductStopwatch   = new Stopwatch();
                    Stopwatch negateStopwatch         = new Stopwatch();
                    Stopwatch degreeStopwatch         = new Stopwatch();
                    Stopwatch serverDecisionStopWatch = new Stopwatch();

                    int featureSizeWithSpace = numberOfFeatures;

                    int batchSize = 200;
                    if (batchSize > 1)
                    {
                        featureSizeWithSpace = numberOfFeatures * 2;
                    }

                    Svc       clf       = new Svc(vectors, coefficients, intercepts, "Linear", 0.25, 0.0, 3, 40, publicKey /*, secretKey*/, relinKeys, galoisKeys, batchSize, featureSizeWithSpace);
                    Stopwatch totalTime = new Stopwatch();
                    totalTime.Start();
                    int start = 0;
                    //double[] batchFeatures = new double[batchSize * featureSizeWithSpace];
                    for (int i = 0; i < numOfRows;)
                    {
                        start = i;
                        double     finalResult = -10000;
                        double[][] batchRows   = new double[batchSize][];
                        for (int j = 0; j < batchSize && i < numOfRows; j++)
                        {
                            batchRows[j] = features[i];
                            i++;
                        }
                        double[] batchFeatures = GetBatchFeatures(batchRows, batchSize, numberOfFeatures, featureSizeWithSpace);


                        var plaintexts          = new Plaintext();
                        var featuresCiphertexts = new Ciphertext();
                        encoder.Encode(batchFeatures, scale, plaintexts);
                        encryptor.Encrypt(plaintexts, featuresCiphertexts);

                        //Server side start
                        var cypherResult = clf.Predict(featuresCiphertexts, true, true, innerProductStopwatch, degreeStopwatch, negateStopwatch, serverDecisionStopWatch);
                        // Server side end
                        Plaintext plainResult = new Plaintext();
                        decryptor.Decrypt(cypherResult, plainResult);
                        List <double> result = new List <double>();
                        encoder.Decode(plainResult, result);

                        for (int j = 0; j < batchSize && start < numOfRows; j++)
                        {
                            finalResult = result[j * featureSizeWithSpace];
                            int estimation = finalResult > 0 ? 0 : 1;
                            Console.WriteLine($"\n ************************************************");
                            Console.WriteLine($"SVC estimation{i} is : {estimation} , result : {finalResult}");
                            file.WriteLine($"{start} , {estimation} , {finalResult} ");
                            Console.WriteLine($"************************************************ \n");
                            start++;
                        }
                    }
                    totalTime.Stop();
                    file.WriteLine($" Client time :  {clientStopwatch.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Total time for {numOfRows} samples :  {totalTime.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Avg time  :  {totalTime.ElapsedMilliseconds * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Inner Product time for  {numOfRows} samples :  {innerProductStopwatch.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Inner Product Avg time  :  {innerProductStopwatch.ElapsedMilliseconds * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Degree time for  {numOfRows} samples :  {degreeStopwatch.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Degree Avg time  :  {degreeStopwatch.ElapsedMilliseconds * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Negate time for  {numOfRows} samples :  {negateStopwatch.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Negate Avg time  :  {negateStopwatch.ElapsedMilliseconds * 1000 / numOfRows} microSec ");
                    file.WriteLine($" Decision time for  {numOfRows} samples :  {serverDecisionStopWatch.ElapsedMilliseconds} ms  ");
                    file.WriteLine($" Decision Avg time  :  {serverDecisionStopWatch.ElapsedMilliseconds * 1000 / numOfRows} microSec ");
                }
            }
        }
Exemple #23
0
        public void ScaleTest()
        {
            List <SmallModulus> coeffModulus = new List <SmallModulus>()
            {
                DefaultParams.SmallMods40Bit(0),
                DefaultParams.SmallMods40Bit(1),
                DefaultParams.SmallMods40Bit(2),
                DefaultParams.SmallMods40Bit(3)
            };
            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
            {
                CoeffModulus      = coeffModulus,
                PolyModulusDegree = 8
            };
            SEALContext  context    = SEALContext.Create(parms);
            KeyGenerator keygen     = new KeyGenerator(context);
            GaloisKeys   galoisKeys = keygen.GaloisKeys(decompositionBitCount: 4);
            Encryptor    encryptor  = new Encryptor(context, keygen.PublicKey);
            Evaluator    evaluator  = new Evaluator(context);
            CKKSEncoder  encoder    = new CKKSEncoder(context);

            MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceNew);

            Assert.AreEqual(0ul, pool.AllocByteCount);

            Ciphertext encrypted = new Ciphertext(pool);
            Plaintext  plain     = new Plaintext();

            MemoryPoolHandle cipherPool = encrypted.Pool;

            Assert.IsNotNull(cipherPool);
            Assert.AreEqual(0ul, cipherPool.AllocByteCount);

            List <Complex> input = new List <Complex>()
            {
                new Complex(1, 1),
                new Complex(2, 2),
                new Complex(3, 3),
                new Complex(4, 4)
            };
            double delta = Math.Pow(2, 70);

            encoder.Encode(input, parms.ParmsId, delta, plain);
            encryptor.Encrypt(plain, encrypted);

            Assert.AreEqual(delta, encrypted.Scale, delta: Math.Pow(2, 60));

            Ciphertext encrypted2 = new Ciphertext();

            encrypted2.Set(encrypted);
            Assert.AreEqual(delta, encrypted2.Scale, delta: Math.Pow(2, 60));

            evaluator.RescaleToNextInplace(encrypted);

            Assert.AreEqual(Math.Pow(2, 30), encrypted.Scale, delta: 10000);
            Assert.AreNotEqual(0ul, cipherPool.AllocByteCount);

            double newScale = Math.Pow(2, 10);

            encrypted.Scale = newScale;
            Assert.AreEqual(newScale, encrypted.Scale, delta: 100);
        }
Exemple #24
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);
            }
Exemple #25
0
        /*
         * Both the BFV scheme (with BatchEncoder) as well as the CKKS scheme support native
         * vectorized computations on encrypted numbers. In addition to computing slot-wise,
         * it is possible to rotate the encrypted vectors cyclically.
         */
        private static void ExampleRotationBFV()
        {
            Utilities.PrintExampleBanner("Example: Rotation / Rotation in BFV");

            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);

            ulong polyModulusDegree = 8192;

            parms.PolyModulusDegree = polyModulusDegree;
            parms.CoeffModulus      = CoeffModulus.BFVDefault(polyModulusDegree);
            parms.PlainModulus      = PlainModulus.Batching(polyModulusDegree, 20);

            SEALContext context = new SEALContext(parms);

            Utilities.PrintParameters(context);
            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);

            BatchEncoder batchEncoder = new BatchEncoder(context);
            ulong        slotCount    = batchEncoder.SlotCount;
            ulong        rowSize      = slotCount / 2;

            Console.WriteLine($"Plaintext matrix row size: {rowSize}");

            ulong[] podMatrix = new ulong[slotCount];
            podMatrix[0]           = 0;
            podMatrix[1]           = 1;
            podMatrix[2]           = 2;
            podMatrix[3]           = 3;
            podMatrix[rowSize]     = 4;
            podMatrix[rowSize + 1] = 5;
            podMatrix[rowSize + 2] = 6;
            podMatrix[rowSize + 3] = 7;

            Console.WriteLine("Input plaintext matrix:");
            Utilities.PrintMatrix(podMatrix, (int)rowSize);
            Console.WriteLine();

            /*
             * First we use BatchEncoder to encode the matrix into a plaintext. We encrypt
             * the plaintext as usual.
             */
            Utilities.PrintLine();
            Plaintext plainMatrix = new Plaintext();

            Console.WriteLine("Encode and encrypt.");
            batchEncoder.Encode(podMatrix, plainMatrix);
            Ciphertext encryptedMatrix = new Ciphertext();

            encryptor.Encrypt(plainMatrix, encryptedMatrix);
            Console.WriteLine("    + Noise budget in fresh encryption: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedMatrix));
            Console.WriteLine();

            /*
             * Rotations require yet another type of special key called `Galois keys'. These
             * are easily obtained from the KeyGenerator.
             */
            GaloisKeys galKeys = keygen.GaloisKeys();

            /*
             * Now rotate both matrix rows 3 steps to the left, decrypt, decode, and print.
             */
            Utilities.PrintLine();
            Console.WriteLine("Rotate rows 3 steps left.");
            evaluator.RotateRowsInplace(encryptedMatrix, 3, galKeys);
            Plaintext plainResult = new Plaintext();

            Console.WriteLine("    + Noise budget after rotation: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedMatrix));
            Console.WriteLine("    + Decrypt and decode ...... Correct.");
            decryptor.Decrypt(encryptedMatrix, plainResult);
            List <ulong> podResult = new List <ulong>();

            batchEncoder.Decode(plainResult, podResult);
            Utilities.PrintMatrix(podResult, (int)rowSize);

            /*
             * We can also rotate the columns, i.e., swap the rows.
             */
            Utilities.PrintLine();
            Console.WriteLine("Rotate columns.");
            evaluator.RotateColumnsInplace(encryptedMatrix, galKeys);
            Console.WriteLine("    + Noise budget after rotation: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedMatrix));
            Console.WriteLine("    + Decrypt and decode ...... Correct.");
            decryptor.Decrypt(encryptedMatrix, plainResult);
            batchEncoder.Decode(plainResult, podResult);
            Utilities.PrintMatrix(podResult, (int)rowSize);

            /*
             * Finally, we rotate the rows 4 steps to the right, decrypt, decode, and print.
             */
            Utilities.PrintLine();
            Console.WriteLine("Rotate rows 4 steps right.");
            evaluator.RotateRowsInplace(encryptedMatrix, -4, galKeys);
            Console.WriteLine("    + Noise budget after rotation: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedMatrix));
            Console.WriteLine("    + Decrypt and decode ...... Correct.");
            decryptor.Decrypt(encryptedMatrix, plainResult);
            batchEncoder.Decode(plainResult, podResult);
            Utilities.PrintMatrix(podResult, (int)rowSize);

            /*
             * Note that rotations do not consume any noise budget. However, this is only
             * the case when the special prime is at least as large as the other primes. The
             * same holds for relinearization. Microsoft SEAL does not require that the
             * special prime is of any particular size, so ensuring this is the case is left
             * for the user to do.
             */
        }