Exemplo n.º 1
0
        public static void SignRequest(SecretKey secret, HttpRequestMessage request)
        {
            #region Preconditions

            if (secret.Value == null) throw new ArgumentNullException(nameof(secret.Value));

            #endregion

            request.Headers.Date = DateTimeOffset.UtcNow;
            request.Headers.Add("User-Agent", "Carbon/1.0");

            var dateHeader = request.Headers.GetValues("Date").First();
            
            var stringToSign = string.Join("\n",
                "HMAC-SHA256",                       // Algorithm
                dateHeader,                          // Request Date / TODO: Format as ISO
                request.Method.ToString().ToUpper(),
                request.RequestUri.Authority,
                request.RequestUri.AbsolutePath
            );

            var signature = Signature.ComputeHmacSha256(
                key  : secret,
                data : Encoding.UTF8.GetBytes(stringToSign)
            );

            // TODO: Credential

            var headerValue = $"C Algorithm=HMAC-SHA256,Signature={signature.ToHexString()}";

            request.Headers.TryAddWithoutValidation("Authorization", headerValue);
        }
Exemplo n.º 2
0
 private static void AddNewSecretKey(string key, string userId, bool isTestMode)
 {
     var secretKey = new SecretKey
     {
         UserId = userId,
         CreatedDate = DateTime.UtcNow,
         IsTest = isTestMode,
         Value = key
     };
     using (var db = new DBEntities())
     {
         var activeSecret = db.SecretKeys.Where(sk => sk.UserId == userId && !sk.IsRevoked && sk.IsTest == isTestMode).FirstOrDefault();
         if (activeSecret != null)
         {
             activeSecret.IsRevoked = true;
             activeSecret.RevokedDate = DateTime.UtcNow;
         }
         db.SecretKeys.Add(secretKey);
         db.SaveChanges();
     }
 }
Exemplo n.º 3
0
 public GFWPressForwardServerListener(IPAddress listenIPAddress, int listenPort, IPAddress forwardIPAddress, int forwardPort, SecretKey key)
     : base(listenIPAddress, listenPort, forwardIPAddress, forwardPort)
 {
     _key = key;
 }
        public override void Write()
        {
            using (StreamWriter keyFile =
                       new StreamWriter(Environment.CurrentDirectory + Constants.File.Path.SECRET_KEY + FileName))
            {
                keyFile.WriteLine(Constants.START);
                keyFile.WriteLine();

                keyFile.WriteLine(Constants.DESCRIPTION);
                keyFile.WriteLine(Constants.TAB + Constants.DESCRIPTION_SECRET_KEY);
                keyFile.WriteLine();

                keyFile.WriteLine(Constants.METHOD);
                foreach (var m in Methods)
                {
                    keyFile.WriteLine(Constants.TAB + m); // "SHA-1"
                }
                keyFile.WriteLine();

                keyFile.WriteLine(Constants.KEY_LENGTH);
                foreach (var m in KeyLength)
                {
                    keyFile.WriteLine(Constants.TAB + m); // "SHA-1"
                }
                keyFile.WriteLine();

                keyFile.WriteLine(Constants.SECRET_KEY);
                for (int i = 0; i < GetNumberOfLines(SecretKey.Length); i++)
                {
                    if ((SecretKey.Length - i * Constants.ROW__CHARACTER_COUNT) < Constants.ROW__CHARACTER_COUNT)
                    {
                        keyFile.WriteLine(Constants.TAB + SecretKey.Substring(i * Constants.ROW__CHARACTER_COUNT,
                                                                              (SecretKey.Length - i * Constants.ROW__CHARACTER_COUNT)));
                    }
                    else
                    {
                        keyFile.WriteLine(Constants.TAB + SecretKey.Substring(i * Constants.ROW__CHARACTER_COUNT,
                                                                              Constants.ROW__CHARACTER_COUNT));
                    }
                }
                keyFile.WriteLine();


                keyFile.WriteLine(Constants.INIT_VECTOR);
                for (int i = 0; i < GetNumberOfLines(InitializationVector.Length); i++)
                {
                    if ((InitializationVector.Length - i * Constants.ROW__CHARACTER_COUNT) <
                        Constants.ROW__CHARACTER_COUNT)
                    {
                        keyFile.WriteLine(Constants.TAB + InitializationVector.Substring(
                                              i * Constants.ROW__CHARACTER_COUNT,
                                              (InitializationVector.Length - i * Constants.ROW__CHARACTER_COUNT)));
                    }
                    else
                    {
                        keyFile.WriteLine(Constants.TAB +
                                          InitializationVector.Substring(i * Constants.ROW__CHARACTER_COUNT,
                                                                         Constants.ROW__CHARACTER_COUNT));
                    }
                }
                keyFile.WriteLine();

                keyFile.WriteLine(Constants.END);
            }
        }
Exemplo n.º 5
0
        public TransfersConsumer(CryptoNote.Currency currency, INodeOriginal node, Logging.ILogger logger, SecretKey viewSecret)
        {
            this.m_node       = new CryptoNote.INodeOriginal(node);
            this.m_viewSecret = new Crypto.SecretKey(viewSecret);
//C++ TO C# CONVERTER TODO TASK: The following line could not be converted:
            this.m_currency = new CryptoNote.Currency(currency);
            this.m_logger   = new Logging.LoggerRef(logger, "TransfersConsumer");
            updateSyncStart();
        }
Exemplo n.º 6
0
        private static void BFVPerformanceTest(SEALContext context)
        {
            Stopwatch timer;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            Console.Out.Flush();
        }
Exemplo n.º 7
0
 /// <summary>Compute the HMAC hash of the message using the key</summary>
 /// <param name="msg">the message to hash</param>
 /// <param name="key">the key to use</param>
 /// <returns>the computed hash</returns>
 public static byte[] ComputeHash(byte[] msg, SecretKey key)
 {
     return(CreatePassword(msg, key));
 }
Exemplo n.º 8
0
        /// <exception cref="System.IO.IOException"/>
        public static string CreateDigest(byte[] password, string data)
        {
            SecretKey key = JobTokenSecretManager.CreateSecretKey(password);

            return(SecureShuffleUtils.HashFromString(data, key));
        }
Exemplo n.º 9
0
        bool IKeyManagementDriver.LoadKeyBlob(int session, IntPtr pKey, int keyLen, KeyType keyType, KeyAttribute keyAttrib, out int hKey)
        {
            bool bRet = false;

            hKey = -1;

            try
            {
                SessionData             ctx    = ((SessionDriver)this.Hal.Session).GetSessionCtx(session);
                CryptokiObjectMgrDriver objMgr = (CryptokiObjectMgrDriver)Hal.CryptokiObjectMgr;

                byte[] keyData = new byte[keyLen];

                Marshal.Copy(pKey, keyData, 0, keyLen);

                if (keyAttrib == KeyAttribute.Secret)
                {
                    SecretKey key = new SecretKey(keyLen * 8, keyData);

                    hKey = ctx.ObjectCtx.AddObject(CryptokiObjectType.Key, new KeyData(keyData, key));

                    bRet = true;
                }
                else
                {
                    switch (keyType)
                    {
                    case KeyType.RSA:
                        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

                        rsa.ImportCspBlob(keyData);

                        hKey = ctx.ObjectCtx.AddObject(CryptokiObjectType.Key, new KeyData(rsa.ExportCspBlob(0 != (keyAttrib & KeyAttribute.Private)), rsa));

                        bRet = true;
                        break;

                    case KeyType.DSA:
                        DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
                        dsa.ImportCspBlob(keyData);

                        hKey = ctx.ObjectCtx.AddObject(CryptokiObjectType.Key, new KeyData(dsa.ExportCspBlob(0 != (keyAttrib & KeyAttribute.Private)), dsa));

                        bRet = true;
                        break;

                    case KeyType.ECDSA:
                    {
                        CngKeyBlobFormat fmt = (0 == (keyAttrib & KeyAttribute.Private)) ? CngKeyBlobFormat.EccPublicBlob : CngKeyBlobFormat.EccPrivateBlob;

                        CngKey   key = CngKey.Import(keyData, fmt);
                        ECDsaCng ec  = new ECDsaCng(key);

                        hKey = ctx.ObjectCtx.AddObject(CryptokiObjectType.Key, new KeyData(ec.Key.Export(fmt), ec));
                        bRet = true;
                    }
                    break;

                    case KeyType.DH:
                    {
                        CngKeyBlobFormat fmt = (0 == (keyAttrib & KeyAttribute.Private)) ? CngKeyBlobFormat.EccPublicBlob : CngKeyBlobFormat.EccPrivateBlob;
                        CngKey           key = CngKey.Import(keyData, fmt);

                        ECDiffieHellmanCng ecdh = new ECDiffieHellmanCng(key);

                        hKey = ctx.ObjectCtx.AddObject(CryptokiObjectType.Key, new KeyData(ecdh.Key.Export(fmt), ecdh));
                        bRet = true;
                    }
                    break;
                    }
                }
            }
            catch
            {
                return(false);
            }

            return(bRet);
        }
Exemplo n.º 10
0
        bool IKeyManagementDriver.DeriveKey(int session, int alg, IntPtr pParam, int paramLen, int hBaseKey, out int hKey)
        {
            hKey = -1;

            try
            {
                SessionData ctx = ((SessionDriver)this.Hal.Session).GetSessionCtx(session);
                KeyData     kd  = ctx.ObjectCtx.GetObject(hBaseKey).Data as KeyData;

                if (kd == null)
                {
                    return(false);
                }

                switch ((AlgorithmType)alg)
                {
                case AlgorithmType.ECDH1_DERIVE:

                    ECDH_Params ecdh = new ECDH_Params(pParam, paramLen);

                    ECDiffieHellmanCng ec = kd.KeyCsp as ECDiffieHellmanCng;

                    ECDiffieHellmanCng cng = new ECDiffieHellmanCng(ec.Key);

                    byte[] pubData = new byte[ecdh.PublicData.Length + 8];

                    pubData[0] = (byte)'E';
                    pubData[1] = (byte)'C';
                    pubData[2] = (byte)'K';
                    switch (ec.KeySize)
                    {
                    case 521:
                        pubData[3] = (byte)'5';
                        pubData[4] = (byte)((521 + 7) / 8);
                        break;

                    case 384:
                        pubData[3] = (byte)'3';
                        pubData[4] = (byte)((384 + 7) / 8);
                        break;

                    case 256:
                        pubData[3] = (byte)'1';
                        pubData[4] = (byte)((256 + 7) / 8);
                        break;
                    }
                    pubData[5] = 0;
                    pubData[6] = 0;
                    pubData[7] = 0;

                    Array.Copy(ecdh.PublicData, 0, pubData, 8, ecdh.PublicData.Length);

                    //CngKey otherPublicKey = CngKey.Import(pubData, CngKeyBlobFormat.EccPublicBlob);

                    ECDiffieHellmanPublicKey otherPublicKey = ECDiffieHellmanCngPublicKey.FromByteArray(pubData, CngKeyBlobFormat.EccPublicBlob);


                    //byte[] otherKeyData = otherPublicKey.Export(CngKeyBlobFormat.EccPublicBlob);

                    //Debug.Print(otherKeyData[0].ToString());

                    switch (ecdh.kdf)
                    {
                    case AlgorithmType.NULL_KEY_DERIVATION:
                        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                        cng.HashAlgorithm         = CngAlgorithm.Sha1;
                        break;

                    case AlgorithmType.SHA1_KEY_DERIVATION:
                        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                        cng.HashAlgorithm         = CngAlgorithm.Sha1;
                        break;

                    case AlgorithmType.SHA256_KEY_DERIVATION:
                        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                        cng.HashAlgorithm         = CngAlgorithm.Sha256;
                        break;

                    case AlgorithmType.SHA512_KEY_DERIVATION:
                        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                        cng.HashAlgorithm         = CngAlgorithm.Sha512;
                        break;

                    case AlgorithmType.MD5_KEY_DERIVATION:
                        cng.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                        cng.HashAlgorithm         = CngAlgorithm.MD5;
                        break;

                    case AlgorithmType.SHA224_HMAC:
                    case AlgorithmType.TLS_MASTER_KEY_DERIVE_DH:
                    default:
                        return(false);
                    }
                    cng.SecretPrepend = null;
                    cng.SecretAppend  = null;

                    byte[] keyData = cng.DeriveKeyMaterial(otherPublicKey);

                    SecretKey key = new SecretKey(keyData.Length * 8, keyData);

                    hKey = ctx.ObjectCtx.AddObject(CryptokiObjectType.Key, new KeyData(keyData, key));

                    break;

                default:
                    return(false);
                }
            }
            catch
            {
                return(false);
            }

            return(true);
        }
Exemplo n.º 11
0
        static async Task RunAsync()
        {
            // Update port # in the following line.
            client.BaseAddress = new Uri("http://localhost/");
            //client.BaseAddress = new Uri("https://sealserver20200623225403.azurewebsites.net/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/octet-stream"));
            UriBuilder builder = new UriBuilder();

            builder.Port = 50755;
            builder.Path = "sealoperation";
            using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
            ulong polyModulusDegree = 4096;

            parms.PolyModulusDegree   = polyModulusDegree;
            parms.CoeffModulus        = CoeffModulus.BFVDefault(polyModulusDegree);
            parms.PlainModulus        = new Modulus(4096);
            using SEALContext context = new SEALContext(parms);
            using Evaluator evaluator = new Evaluator(context);
            using KeyGenerator keygen = new KeyGenerator(context);
            using PublicKey publicKey = keygen.PublicKey;
            using SecretKey secretKey = keygen.SecretKey;
            using Encryptor encryptor = new Encryptor(context, publicKey);
            using Decryptor decryptor = new Decryptor(context, secretKey);


            //BigInteger bint = BigInteger.Parse("97391909619002370737223511047161666878854921822310726371156754097341907215981");
            BigInteger bint = BigInteger.Parse("998745113");
            //int xVal = 625;
            //int degree = 10;
            //int coeff = 25;
            // These are good starting points for small numbers < 100mil

            /*
             * int tConst = 121;
             * int xVal = 10;
             * int degree = 2;
             * int coeff = 3;
             */
            int tConst = 1210;
            int xVal   = 25;
            int degree = 4;
            int coeff  = 3;


            // Candidate first result from initial polynomial
            List <int> terms;
            BigInteger res = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms);

            // compare res to target BigInteger, if way smaller, then create a new
            // result after increasing any of the polynomial values
            while (BigInteger.Compare(res, bint) < 0) // res is less than bint
            {
                BigInteger halfVal    = BigInteger.Divide(bint, new BigInteger(2));
                BigInteger onePercent = BigInteger.Divide(bint, new BigInteger(100));
                BigInteger tenPercent = BigInteger.Multiply(onePercent, new BigInteger(10));
                //BigInteger quarterVal = BigInteger.Divide(bint, new BigInteger(4));
                if (BigInteger.Compare(halfVal, res) > 0)
                {
                    //coeff += 1;
                    int len  = halfVal.ToString().Length;
                    int len2 = res.ToString().Length;
                    if (len == len2)
                    {
                        coeff *= 2;
                    }
                    else
                    {
                        degree += 2;
                    }
                    res = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms);
                }
                else
                {
                    BigInteger difference = BigInteger.Subtract(bint, res);
                    if (BigInteger.Compare(tenPercent, difference) > 0)
                    {
                        tConst += 1111;
                    }
                    else
                    {
                        coeff += 1;
                    }
                    res = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms);
                }
                //Console.WriteLine(res.ToString());
                Console.WriteLine("...");
            }
            // Res is now equal or greater to bint
            tConst = tConst - (int)BigInteger.Subtract(res, bint);
            // Now check the polynomial
            BigInteger testPoly = createBigIntFromPoly(degree, coeff, xVal, tConst, out terms);

            Console.WriteLine("For Big Integer {0}", bint.ToString());
            foreach (int term in terms)
            {
                Console.WriteLine("Polynomial term is {0}x^{1}", coeff, term);
            }
            Console.WriteLine("Final term is constant {0} with x={1}", tConst, xVal);
            byte[] bytespan = bint.ToByteArray();
            byte[] newspan  = new byte[bytespan.Length];
            newspan[0] = bytespan[0];
            BigInteger binttemp = new BigInteger(bytespan);
            // Pick an 'x' value for the polynomial that is big enough to represent the upper 10 digits of the value
            BigInteger bint2   = BigInteger.Parse("7983012132846067729184195556448685457666384473549591845215215701504271855338012801306119587019479688581971723759499902125851173348207536911525267617909811");
            BigInteger bintres = bint * bint2;

            using Plaintext bPlainB = new Plaintext(bint.ToString());
            int x = 9;

            Console.WriteLine("Plain x value to set");
            Console.WriteLine(x.ToString());
            using Plaintext xPlainX = new Plaintext(Convert.ToString(x, 16));
            Console.WriteLine("Hex value being set");
            Console.WriteLine(xPlainX.ToString());
            using Ciphertext xEncrypted = new Ciphertext();
            Console.WriteLine("Encrypt xPlain to xEncrypted.");
            encryptor.Encrypt(xPlainX, xEncrypted);
            int y = 5;

            Console.WriteLine("Plain y value to set");
            Console.WriteLine(y.ToString());
            using Plaintext xPlainY = new Plaintext(Convert.ToString(y, 16));
            Console.WriteLine("Hex y value being set");
            Console.WriteLine(xPlainY.ToString());
            using Ciphertext yEncrypted = new Ciphertext();
            encryptor.Encrypt(xPlainY, yEncrypted);

            FHEParams fHEParams = new FHEParams();

            fHEParams.param1 = xEncrypted;
            fHEParams.param2 = yEncrypted;
            fHEParams.result = new Ciphertext();
            // DEBUG ONLY
            Ciphertext mAnswer = new Ciphertext();

            evaluator.Multiply(fHEParams.param1, fHEParams.param2, mAnswer);
            evaluator.Add(fHEParams.param1, fHEParams.param2, fHEParams.result);
            string expAnswer = SerializeSEAL(fHEParams.result);

            using Plaintext xDecrypted2 = new Plaintext();
            decryptor.Decrypt(mAnswer, xDecrypted2);
            Console.WriteLine(xDecrypted2.ToString());
            decryptor.Decrypt(fHEParams.result, xDecrypted2);
            string answer = xDecrypted2.ToString();
            int    num    = 0;

            Int32.TryParse(answer, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out num);
            Console.WriteLine("Local answer");
            Console.WriteLine(answer);
            Console.WriteLine(num.ToString());

            // END DEBUG

            //fHEParams.param1.

            fHEParams.operation = "add";

            SEALTransport transport = new SEALTransport();

            transport.ContextParams = SerializeSEAL(parms);

            transport.FHEParam1 = SerializeSEAL(fHEParams.param1);
            // Console.WriteLine(transport.FHEParam1);
            transport.FHEParam2 = SerializeSEAL(fHEParams.param2);
            transport.FHEResult = SerializeSEAL(fHEParams.result);
            transport.Operation = fHEParams.operation;

            try
            {
                // Get the parameters,
                SEALTransport response = await PostFHEResultAsync(builder.Uri.AbsoluteUri, transport);

                Ciphertext result    = new Ciphertext();
                byte[]     fp1       = System.Convert.FromBase64String(response.FHEResult);
                string     recAnswer = response.FHEResult;
                if (expAnswer == recAnswer)
                {
                    Console.WriteLine("Expected answer matches received answer");
                }
                MemoryStream mst = new MemoryStream(fp1);
                result.Load(context, mst);
                Plaintext xDecrypted3 = new Plaintext();
                decryptor.Decrypt(result, xDecrypted3);
                answer = xDecrypted3.ToString();
                Console.WriteLine(answer);
                Console.WriteLine("Remote Decimal answer");
                Int32.TryParse(answer, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out num);
                Console.WriteLine(num.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadLine();
        }
Exemplo n.º 12
0
        public void EncryptZeroTest()
        {
            {
                SEALContext  context   = GlobalContext.BFVContext;
                KeyGenerator keyGen    = new KeyGenerator(context);
                PublicKey    publicKey = keyGen.PublicKey;
                SecretKey    secretKey = keyGen.SecretKey;
                Encryptor    encryptor = new Encryptor(context, publicKey, secretKey);
                Decryptor    decryptor = new Decryptor(context, secretKey);

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

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

                {
                    encryptor.EncryptZero(cipher);
                    Assert.IsFalse(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    decryptor.Decrypt(cipher, plain);
                    Assert.IsTrue(plain.IsZero);

                    encryptor.EncryptZero(nextParms, cipher);
                    Assert.IsFalse(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    Assert.AreEqual(cipher.ParmsId, nextParms);
                    decryptor.Decrypt(cipher, plain);
                    Assert.IsTrue(plain.IsZero);
                }
                {
                    encryptor.EncryptZeroSymmetric(cipher);
                    Assert.IsFalse(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    decryptor.Decrypt(cipher, plain);
                    Assert.IsTrue(plain.IsZero);

                    encryptor.EncryptZeroSymmetric(nextParms, cipher);
                    Assert.IsFalse(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    Assert.AreEqual(cipher.ParmsId, nextParms);
                    decryptor.Decrypt(cipher, plain);
                    Assert.IsTrue(plain.IsZero);
                }
                using (MemoryStream stream = new MemoryStream())
                {
                    encryptor.EncryptZeroSymmetricSave(stream);
                    stream.Seek(0, SeekOrigin.Begin);
                    cipher.Load(context, stream);
                    Assert.IsFalse(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    decryptor.Decrypt(cipher, plain);
                    Assert.IsTrue(plain.IsZero);
                }
                using (MemoryStream stream = new MemoryStream())
                {
                    encryptor.EncryptZeroSymmetricSave(nextParms, stream);
                    stream.Seek(0, SeekOrigin.Begin);
                    cipher.Load(context, stream);
                    Assert.IsFalse(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    Assert.AreEqual(cipher.ParmsId, nextParms);
                    decryptor.Decrypt(cipher, plain);
                    Assert.IsTrue(plain.IsZero);
                }
            }
            {
                SEALContext  context   = GlobalContext.CKKSContext;
                KeyGenerator keyGen    = new KeyGenerator(context);
                PublicKey    publicKey = keyGen.PublicKey;
                SecretKey    secretKey = keyGen.SecretKey;
                Encryptor    encryptor = new Encryptor(context, publicKey, secretKey);
                Decryptor    decryptor = new Decryptor(context, secretKey);
                CKKSEncoder  encoder   = new CKKSEncoder(context);

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

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

                {
                    encryptor.EncryptZero(cipher);
                    Assert.IsTrue(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    cipher.Scale = Math.Pow(2.0, 30);
                    decryptor.Decrypt(cipher, plain);

                    encoder.Decode(plain, res);
                    foreach (Complex val in res)
                    {
                        Assert.AreEqual(val.Real, 0.0, 0.01);
                        Assert.AreEqual(val.Imaginary, 0.0, 0.01);
                    }

                    encryptor.EncryptZero(nextParms, cipher);
                    Assert.IsTrue(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    cipher.Scale = Math.Pow(2.0, 30);
                    Assert.AreEqual(cipher.ParmsId, nextParms);
                    decryptor.Decrypt(cipher, plain);
                    Assert.AreEqual(plain.ParmsId, nextParms);

                    encoder.Decode(plain, res);
                    foreach (Complex val in res)
                    {
                        Assert.AreEqual(val.Real, 0.0, 0.01);
                        Assert.AreEqual(val.Imaginary, 0.0, 0.01);
                    }
                }
                {
                    encryptor.EncryptZeroSymmetric(cipher);
                    Assert.IsTrue(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    cipher.Scale = Math.Pow(2.0, 30);
                    decryptor.Decrypt(cipher, plain);

                    encoder.Decode(plain, res);
                    foreach (Complex val in res)
                    {
                        Assert.AreEqual(val.Real, 0.0, 0.01);
                        Assert.AreEqual(val.Imaginary, 0.0, 0.01);
                    }

                    encryptor.EncryptZeroSymmetric(nextParms, cipher);
                    Assert.IsTrue(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    cipher.Scale = Math.Pow(2.0, 30);
                    Assert.AreEqual(cipher.ParmsId, nextParms);
                    decryptor.Decrypt(cipher, plain);
                    Assert.AreEqual(plain.ParmsId, nextParms);

                    encoder.Decode(plain, res);
                    foreach (Complex val in res)
                    {
                        Assert.AreEqual(val.Real, 0.0, 0.01);
                        Assert.AreEqual(val.Imaginary, 0.0, 0.01);
                    }
                }
                using (MemoryStream stream = new MemoryStream())
                {
                    encryptor.EncryptZeroSymmetricSave(stream);
                    stream.Seek(0, SeekOrigin.Begin);
                    cipher.Load(context, stream);
                    Assert.IsTrue(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    cipher.Scale = Math.Pow(2.0, 30);
                    decryptor.Decrypt(cipher, plain);

                    encoder.Decode(plain, res);
                    foreach (Complex val in res)
                    {
                        Assert.AreEqual(val.Real, 0.0, 0.01);
                        Assert.AreEqual(val.Imaginary, 0.0, 0.01);
                    }
                }
                using (MemoryStream stream = new MemoryStream())
                {
                    encryptor.EncryptZeroSymmetricSave(nextParms, stream);
                    stream.Seek(0, SeekOrigin.Begin);
                    cipher.Load(context, stream);
                    Assert.IsTrue(cipher.IsNTTForm);
                    Assert.IsFalse(cipher.IsTransparent);
                    Assert.AreEqual(cipher.Scale, 1.0, double.Epsilon);
                    cipher.Scale = Math.Pow(2.0, 30);
                    Assert.AreEqual(cipher.ParmsId, nextParms);
                    decryptor.Decrypt(cipher, plain);
                    Assert.AreEqual(plain.ParmsId, nextParms);

                    encoder.Decode(plain, res);
                    foreach (Complex val in res)
                    {
                        Assert.AreEqual(val.Real, 0.0, 0.01);
                        Assert.AreEqual(val.Imaginary, 0.0, 0.01);
                    }
                }
            }
        }
Exemplo n.º 13
0
 /// <summary>
 /// 获取学校的详细信息(用于登录或其他)
 /// </summary>
 /// <param name="school">School Object</param>
 /// <param name="secretKey">SecretKey Object</param>
 /// <returns>SchoolDetails</returns>
 public Task <SchoolDetails> GetSchoolDetailsAsync(School school, SecretKey secretKey)
 {
     return(GetSchoolDetailsAsync(school.Id, secretKey.Chk));
 }
Exemplo n.º 14
0
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual bool getTransactionSecretKey(SecretKey& key) const override
        public override bool GetTransactionSecretKey(SecretKey key)
        {
            return(false);
        }
Exemplo n.º 15
0
        /*
         * In `1_BFV_Basics.cs' we showed how to perform a very simple computation using the
         * BFV scheme. The computation was performed modulo the PlainModulus parameter, and
         * utilized only one coefficient from a BFV plaintext polynomial. This approach has
         * two notable problems:
         *
         *  (1) Practical applications typically use integer or real number arithmetic,
         *      not modular arithmetic;
         *  (2) We used only one coefficient of the plaintext polynomial. This is really
         *      wasteful, as the plaintext polynomial is large and will in any case be
         *      encrypted in its entirety.
         *
         * For (1), one may ask why not just increase the PlainModulus parameter until no
         * overflow occurs, and the computations behave as in integer arithmetic. The problem
         * is that increasing PlainModulus increases noise budget consumption, and decreases
         * the initial noise budget too.
         *
         * In these examples we will discuss other ways of laying out data into plaintext
         * elements (encoding) that allow more computations without data type overflow, and
         * can allow the full plaintext polynomial to be utilized.
         */
        private static void ExampleBatchEncoder()
        {
            Utilities.PrintExampleBanner("Example: Encoders / Batch Encoder");

            /*
             * [BatchEncoder] (For BFV scheme only)
             *
             * Let N denote the PolyModulusDegree and T denote the PlainModulus. Batching
             * allows the BFV plaintext polynomials to be viewed as 2-by-(N/2) matrices, with
             * each element an integer modulo T. In the matrix view, encrypted operations act
             * element-wise on encrypted matrices, allowing the user to obtain speeds-ups of
             * several orders of magnitude in fully vectorizable computations. Thus, in all
             * but the simplest computations, batching should be the preferred method to use
             * with BFV, and when used properly will result in implementations outperforming
             * anything done without batching.
             */
            using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
            ulong polyModulusDegree = 8192;

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

            /*
             * To enable batching, we need to set the plain_modulus to be a prime number
             * congruent to 1 modulo 2*PolyModulusDegree. Microsoft SEAL provides a helper
             * method for finding such a prime. In this example we create a 20-bit prime
             * that supports batching.
             */
            parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20);

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

            /*
             * We can verify that batching is indeed enabled by looking at the encryption
             * parameter qualifiers created by SEALContext.
             */
            using var qualifiers = context.FirstContextData.Qualifiers;
            Console.WriteLine($"Batching enabled: {qualifiers.UsingBatching}");

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

            /*
             * Batching is done through an instance of the BatchEncoder class.
             */
            using BatchEncoder batchEncoder = new BatchEncoder(context);

            /*
             * The total number of batching `slots' equals the PolyModulusDegree, N, and
             * these slots are organized into 2-by-(N/2) matrices that can be encrypted and
             * computed on. Each slot contains an integer modulo PlainModulus.
             */
            ulong slotCount = batchEncoder.SlotCount;
            ulong rowSize   = slotCount / 2;

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

            /*
             * The matrix plaintext is simply given to BatchEncoder as a flattened vector
             * of numbers. The first `rowSize' many numbers form the first row, and the
             * rest form the second row. Here we create the following matrix:
             *
             *  [ 0,  1,  2,  3,  0,  0, ...,  0 ]
             *  [ 4,  5,  6,  7,  0,  0, ...,  0 ]
             */
            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);

            /*
             * First we use BatchEncoder to encode the matrix into a plaintext polynomial.
             */
            using Plaintext plainMatrix = new Plaintext();
            Utilities.PrintLine();
            Console.WriteLine("Encode plaintext matrix:");
            batchEncoder.Encode(podMatrix, plainMatrix);

            /*
             * We can instantly decode to verify correctness of the encoding. Note that no
             * encryption or decryption has yet taken place.
             */
            List <ulong> podResult = new List <ulong>();

            Console.WriteLine("    + Decode plaintext matrix ...... Correct.");
            batchEncoder.Decode(plainMatrix, podResult);
            Utilities.PrintMatrix(podResult, (int)rowSize);

            /*
             * Next we encrypt the encoded plaintext.
             */
            using Ciphertext encryptedMatrix = new Ciphertext();
            Utilities.PrintLine();
            Console.WriteLine("Encrypt plainMatrix to encryptedMatrix.");
            encryptor.Encrypt(plainMatrix, encryptedMatrix);
            Console.WriteLine("    + Noise budget in encryptedMatrix: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedMatrix));

            /*
             * Operating on the ciphertext results in homomorphic operations being performed
             * simultaneously in all 8192 slots (matrix elements). To illustrate this, we
             * form another plaintext matrix
             *
             *  [ 1,  2,  1,  2,  1,  2, ..., 2 ]
             *  [ 1,  2,  1,  2,  1,  2, ..., 2 ]
             *
             * and encode it into a plaintext.
             */
            ulong[] podMatrix2 = new ulong[slotCount];
            for (ulong i = 0; i < slotCount; i++)
            {
                podMatrix2[i] = (i & 1) + 1;
            }
            using Plaintext plainMatrix2 = new Plaintext();
            batchEncoder.Encode(podMatrix2, plainMatrix2);
            Console.WriteLine();
            Console.WriteLine("Second input plaintext matrix:");
            Utilities.PrintMatrix(podMatrix2, (int)rowSize);

            /*
             * We now add the second (plaintext) matrix to the encrypted matrix, and square
             * the sum.
             */
            Utilities.PrintLine();
            Console.WriteLine("Sum, square, and relinearize.");
            evaluator.AddPlainInplace(encryptedMatrix, plainMatrix2);
            evaluator.SquareInplace(encryptedMatrix);
            evaluator.RelinearizeInplace(encryptedMatrix, relinKeys);

            /*
             * How much noise budget do we have left?
             */
            Console.WriteLine("    + Noise budget in result: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedMatrix));

            /*
             * We decrypt and decompose the plaintext to recover the result as a matrix.
             */
            using Plaintext plainResult = new Plaintext();
            Utilities.PrintLine();
            Console.WriteLine("Decrypt and decode result.");
            decryptor.Decrypt(encryptedMatrix, plainResult);
            batchEncoder.Decode(plainResult, podResult);
            Console.WriteLine("    + Result plaintext matrix ...... Correct.");
            Utilities.PrintMatrix(podResult, (int)rowSize);

            /*
             * Batching allows us to efficiently use the full plaintext polynomial when the
             * desired encrypted computation is highly parallelizable. However, it has not
             * solved the other problem mentioned in the beginning of this file: each slot
             * holds only an integer modulo plain_modulus, and unless plain_modulus is very
             * large, we can quickly encounter data type overflow and get unexpected results
             * when integer computations are desired. Note that overflow cannot be detected
             * in encrypted form. The CKKS scheme (and the CKKSEncoder) addresses the data
             * type overflow issue, but at the cost of yielding only approximate results.
             */
        }
Exemplo n.º 16
0
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual bool findOutputsToAccount(const AccountPublicAddress& addr, const SecretKey& viewSecretKey, ClassicVector<uint>& outs, ulong& outputAmount) const override
        public override bool FindOutputsToAccount(AccountPublicAddress addr, SecretKey viewSecretKey, List <uint> outs, ulong outputAmount)
        {
            return(global::CryptoNote.findOutputsToAccount(m_txPrefix, addr, viewSecretKey, outs, outputAmount));
        }
Exemplo n.º 17
0
        bool IKeyManagementDriver.GetPublicKeyData(int session, int hKey, IntPtr data, ref int dataLen)
        {
            try
            {
                SessionData ctx = ((SessionDriver)this.Hal.Session).GetSessionCtx(session);
                KeyData     kd  = ctx.ObjectCtx.GetObject(hKey).Data as KeyData;

                if (kd == null)
                {
                    return(false);
                }

                if (kd.KeyCsp is RSACryptoServiceProvider)
                {
                    RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)kd.KeyCsp;

                    byte [] key = rsa.ExportCspBlob(false);

                    if (dataLen < key.Length)
                    {
                        return(false);
                    }

                    Marshal.Copy(key, 0, data, key.Length);

                    dataLen = key.Length;
                }
                else if (kd.KeyCsp is DSACryptoServiceProvider)
                {
                    DSACryptoServiceProvider dsa = (DSACryptoServiceProvider)kd.KeyCsp;

                    byte[] key = dsa.ExportCspBlob(false);

                    if (dataLen < key.Length)
                    {
                        return(false);
                    }

                    Marshal.Copy(key, 0, data, key.Length);

                    dataLen = key.Length;
                }
                else if (kd.KeyCsp is ECDsaCng)
                {
                    ECDsaCng cng = (ECDsaCng)kd.KeyCsp;

                    byte[] key = cng.Key.Export(CngKeyBlobFormat.EccPublicBlob);

                    if (dataLen < (key.Length - 8))
                    {
                        return(false);
                    }

                    Marshal.Copy(key, 8, data, key.Length - 8);

                    dataLen = key.Length - 8;
                }
                else if (kd.KeyCsp is ECDiffieHellmanCng)
                {
                    ECDiffieHellmanCng cng = (ECDiffieHellmanCng)kd.KeyCsp;

                    byte[] key = cng.Key.Export(CngKeyBlobFormat.EccPublicBlob);

                    if (dataLen < (key.Length - 8))
                    {
                        return(false);
                    }

                    Marshal.Copy(key, 8, data, key.Length - 8);

                    dataLen = key.Length - 8;
                }
                else if (kd.KeyCsp is SecretKey)
                {
                    SecretKey key = (SecretKey)kd.KeyCsp;

                    if (dataLen < key.Data.Length)
                    {
                        return(false);
                    }

                    Marshal.Copy(key.Data, 0, data, key.Data.Length);

                    dataLen = key.Data.Length;
                }
                else if (kd.KeyCsp is AesCryptoServiceProvider)
                {
                    AesCryptoServiceProvider aes = (AesCryptoServiceProvider)kd.KeyCsp;

                    if (dataLen < aes.Key.Length)
                    {
                        return(false);
                    }

                    Marshal.Copy(aes.Key, 0, data, aes.Key.Length);

                    dataLen = aes.Key.Length;
                }
                else
                {
                    return(false);
                }
            }
            catch
            {
                return(false);
            }

            return(true);
        }
Exemplo n.º 18
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.
             */
        }
Exemplo n.º 19
0
        protected override void Execute(CodeActivityContext context)
        {
            try {
                var mUniversalDataHandler = new AwsS3DataHandler(AccessKey.Get(context), SecretKey.Get(context), Region.Get(context));

                mUniversalDataHandler.CreateDir(Generate(SourcePath.Get(context), BucketName.Get(context)));
                Response.Set(context, "Complete");
            }
            catch (Exception e) {
                Error.Set(context, e.Message);
            }
        }
Exemplo n.º 20
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.CreateGaloisKeys(elts_null));
                Utilities.AssertThrows <ArgumentException>(() => keygen.CreateGaloisKeys(elts));
                Utilities.AssertThrows <ArgumentNullException>(() => keygen.CreateGaloisKeys(steps_null));
                Utilities.AssertThrows <ArgumentException>(() => keygen.CreateGaloisKeys(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.CreateRelinKeys());
                Utilities.AssertThrows <InvalidOperationException>(() => keygen.CreateGaloisKeys());
            }
            {
                SEALContext  context = GlobalContext.BGVContext;
                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.CreateGaloisKeys(elts_null));
                Utilities.AssertThrows <ArgumentException>(() => keygen.CreateGaloisKeys(elts));
                Utilities.AssertThrows <ArgumentNullException>(() => keygen.CreateGaloisKeys(steps_null));
                Utilities.AssertThrows <ArgumentException>(() => keygen.CreateGaloisKeys(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.CreateRelinKeys());
                Utilities.AssertThrows <InvalidOperationException>(() => keygen.CreateGaloisKeys());
            }
        }
Exemplo n.º 21
0
 public GFWPressEncryptForwarder(Socket ClientSocket, DestroyDelegate Destroyer, Socket DestinationSocket, SecretKey key) : base(ClientSocket, Destroyer)
 {
     ClientSocket.Blocking  = false;
     this.DestinationSocket = DestinationSocket;
     this._key = key;
 }
Exemplo n.º 22
0
 /// <summary>Default constructor</summary>
 public JobTokenSecretManager()
 {
     this.masterKey        = GenerateSecret();
     this.currentJobTokens = new SortedDictionary <string, SecretKey>();
 }
Exemplo n.º 23
0
            public int Predict(double[] features, int power, bool useRelinearizeInplace, bool useReScale, Stopwatch timePredictSum)
            {
                EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

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

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

                SEALContext context = new SEALContext(parms);

                Console.WriteLine();

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

                CKKSEncoder encoder = new CKKSEncoder(context);

                ulong slotCount = encoder.SlotCount;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    evaluator.NegateInplace(kernels[i]);

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

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

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

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

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



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

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



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

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

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


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

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

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

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


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

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

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

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

                return(1);
            }
Exemplo n.º 24
0
        private static void CKKSPerformanceTest(SEALContext context)
        {
            Stopwatch timer;

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

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

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

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

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

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

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

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

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

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

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

            Random rnd = new Random();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            Console.Out.Flush();
        }
Exemplo n.º 25
0
        private static void HomoExample()
        {
            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);

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

            KeyGenerator keygen = new KeyGenerator(context);

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

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

            Decryptor decryptor = new Decryptor(context, secretKey);

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

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

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

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

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

            Console.Write("Encrypting plain1: ");

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

            Plaintext plainResult = new Plaintext();

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


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



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

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

            evaluator.AddInplace(encrypted1, encrypted2);

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

            evaluator.MultiplyInplace(encrypted1, encrypted2);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            Plaintext plainResult = new Plaintext();

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

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

            /*
             * Decode to obtain an integer result.
             */
            Utilities.PrintLine();
            Console.WriteLine("Decode plain_result.");
            Console.WriteLine("    + Decoded integer: {0} ...... Correct.",
                              encoder.DecodeInt32(plainResult));
        }
Exemplo n.º 27
0
        //constructor for debugging , because it enables to pass secretkey which will not happen in real life
        // special parameters :
        //  batchsize - number of batches sample in one ciphertext ,if the client batches mulitple  samples in the ciphertet .
        //  featureSize - number of features in sample

        private Svc(double[][] vectors, double[][] coefficients, double[] intercepts, String kernel, double gamma, double coef0, ulong degree, int power, PublicKey publicKey, SecretKey secretKey, RelinKeys relinKeys, GaloisKeys galoisKeys, int batchSize, int featureSize)
        {
            this._vectors      = vectors;
            this._coefficients = coefficients;
            this._intercepts   = intercepts;

            this._kernel = (Kernel)System.Enum.Parse(typeof(Kernel), kernel);
            this._gamma  = gamma;
            this._coef0  = coef0;
            this._degree = degree;
            this._power  = power;
            //Use the ckks SCheme
            EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

            // polyModulusDegree and CoeffModulus used for general SVM algorithm and depends on the polynomial kernel degree
            // ( and the percision constraint ) .
            // My implementation can be used up to dgree = 4 , but it can be easly refactored with some oprimizations  to higher
            // polynomial degree
            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);



            _publicKey  = publicKey;
            _secretKey  = secretKey;
            _relinKeys  = relinKeys;
            _galoisKeys = galoisKeys;

            _evaluator = new Evaluator(_context);
            if (_secretKey != null)
            {
                _decryptor = new Decryptor(_context, _secretKey);                 //FOR DEBUG ONLY ( not used in real server)
            }
            _encoder = new CKKSEncoder(_context);


            Stopwatch serverInitStopwatch = new Stopwatch();

            serverInitStopwatch.Start();



            _numOfrowsCount    = _vectors.Length;       //Number of Support Vectors
            _numOfcolumnsCount = _vectors[0].Length;    //Number of features in every Support vector
            _scale             = Math.Pow(2.0, _power);


            //	vars for batch rotations
            _svPlaintexts = new Plaintext[_numOfrowsCount];

            //Encode support vectors
            _sums = new Ciphertext[_numOfrowsCount];
            if (UseBatchInnerProduct)
            {
                double[] batchVectors = new double[batchSize * featureSize];

                for (int i = 0; i < _numOfrowsCount; i++)
                {
                    for (int k = 0; k < batchSize * featureSize; k++)
                    {
                        var index0 = k % featureSize;

                        batchVectors[k] = index0 < _numOfcolumnsCount ? _vectors[i][index0] : 0;
                    }
                    _svPlaintexts[i] = new Plaintext();
                    _encoder.Encode(batchVectors, _scale, _svPlaintexts[i]);
                    SVCUtilities.SvcUtilities.PrintScale(_svPlaintexts[i], "batch supportVectorsPlaintext" + i);
                    _sums[i] = new Ciphertext();
                }
            }
            else
            {
                /////////////////////////////////////////////////////////////////////////
                //
                //   vars for simple inner product
                //
                // Handle SV

                _svPlaintextsArr = new Plaintext[_numOfrowsCount, _numOfcolumnsCount];

                //Encode SV
                for (int i = 0; i < _numOfrowsCount; i++)
                {
                    for (int j = 0; j < _numOfcolumnsCount; j++)
                    {
                        _svPlaintextsArr[i, j] = new Plaintext();

                        _encoder.Encode(_vectors[i][j] != 0 ? _vectors[i][j] : Zero, _scale, _svPlaintextsArr[i, j]);
                        SvcUtilities.PrintScale(_svPlaintextsArr[i, j], $"supportVectorsPlaintext[{i}][{j}]");
                    }
                }

                // Prepare sum of inner product
                _innerProdSums = new Ciphertext[_numOfcolumnsCount];
                for (int i = 0; i < _numOfcolumnsCount; i++)
                {
                    _innerProdSums[i] = new Ciphertext();
                }
                //////////////////////////////////////////////////////////////
            }

            // Allocate memory for svm secure calculation
            _kernels      = new Ciphertext[_numOfrowsCount];
            _decisionsArr = new Ciphertext[_numOfrowsCount];
            _coefArr      = new Plaintext[_numOfrowsCount];

            for (int i = 0; i < _numOfrowsCount; i++)
            {
                _kernels[i]      = new Ciphertext();
                _decisionsArr[i] = new Ciphertext();
                _coefArr[i]      = new Plaintext();
            }
            _gamaPlaintext = new Plaintext();
            _encoder.Encode(_gamma != 0 ? _gamma : Zero, _scale, _gamaPlaintext);


            serverInitStopwatch.Stop();
            Console.WriteLine($"server Init elapsed {serverInitStopwatch.ElapsedMilliseconds} ms");
        }
Exemplo n.º 28
0
 public BlockKey(int keyId, long expiryDate, SecretKey key)
     : base(keyId, expiryDate, key)
 {
 }
Exemplo n.º 29
0
        private static void ExampleBFVBasics()
        {
            Utilities.PrintExampleBanner("Example: BFV Basics");

            /*
             * In this example, we demonstrate performing simple computations (a polynomial
             * evaluation) on encrypted integers using the BFV encryption scheme.
             *
             * The first task is to set up an instance of the EncryptionParameters class.
             * It is critical to understand how the different parameters behave, how they
             * affect the encryption scheme, performance, and the security level. There are
             * three encryption parameters that are necessary to set:
             *
             *  - PolyModulusDegree (degree of polynomial modulus);
             *  - CoeffModulus ([ciphertext] coefficient modulus);
             *  - PlainModulus (plaintext modulus; only for the BFV scheme).
             *
             * The BFV scheme cannot perform arbitrary computations on encrypted data.
             * Instead, each ciphertext has a specific quantity called the `invariant noise
             * budget' -- or `noise budget' for short -- measured in bits. The noise budget
             * in a freshly encrypted ciphertext (initial noise budget) is determined by
             * the encryption parameters. Homomorphic operations consume the noise budget
             * at a rate also determined by the encryption parameters. In BFV the two basic
             * operations allowed on encrypted data are additions and multiplications, of
             * which additions can generally be thought of as being nearly free in terms of
             * noise budget consumption compared to multiplications. Since noise budget
             * consumption compounds in sequential multiplications, the most significant
             * factor in choosing appropriate encryption parameters is the multiplicative
             * depth of the arithmetic circuit that the user wants to evaluate on encrypted
             * data. Once the noise budget of a ciphertext reaches zero it becomes too
             * corrupted to be decrypted. Thus, it is essential to choose the parameters to
             * be large enough to support the desired computation; otherwise the result is
             * impossible to make sense of even with the secret key.
             */
            EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);

            /*
             * The first parameter we set is the degree of the `polynomial modulus'. This
             * must be a positive power of 2, representing the degree of a power-of-two
             * cyclotomic polynomial; it is not necessary to understand what this means.
             *
             * Larger PolyModulusDegree makes ciphertext sizes larger and all operations
             * slower, but enables more complicated encrypted computations. Recommended
             * values are 1024, 2048, 4096, 8192, 16384, 32768, but it is also possible
             * to go beyond this range.
             *
             * In this example we use a relatively small polynomial modulus. Anything
             * smaller than this will enable only very restricted encrypted computations.
             */
            ulong polyModulusDegree = 4096;

            parms.PolyModulusDegree = polyModulusDegree;

            /*
             * Next we set the [ciphertext] `coefficient modulus' (CoeffModulus). This
             * parameter is a large integer, which is a product of distinct prime numbers,
             * numbers, each represented by an instance of the SmallModulus class. The
             * bit-length of CoeffModulus means the sum of the bit-lengths of its prime
             * factors.
             *
             * A larger CoeffModulus implies a larger noise budget, hence more encrypted
             * computation capabilities. However, an upper bound for the total bit-length
             * of the CoeffModulus is determined by the PolyModulusDegree, as follows:
             *
             +----------------------------------------------------+
             | PolyModulusDegree   | max CoeffModulus bit-length  |
             +---------------------+------------------------------+
             | 1024                | 27                           |
             | 2048                | 54                           |
             | 4096                | 109                          |
             | 8192                | 218                          |
             | 16384               | 438                          |
             | 32768               | 881                          |
             +---------------------+------------------------------+
             |
             | These numbers can also be found in native/src/seal/util/hestdparms.h encoded
             | in the function SEAL_HE_STD_PARMS_128_TC, and can also be obtained from the
             | function
             |
             |  CoeffModulus.MaxBitCount(polyModulusDegree).
             |
             | For example, if PolyModulusDegree is 4096, the coeff_modulus could consist
             | of three 36-bit primes (108 bits).
             |
             | Microsoft SEAL comes with helper functions for selecting the CoeffModulus.
             | For new users the easiest way is to simply use
             |
             |  CoeffModulus.BFVDefault(polyModulusDegree),
             |
             | which returns IEnumerable<SmallModulus> consisting of a generally good choice
             | for the given PolyModulusDegree.
             */
            parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);

            /*
             * The plaintext modulus can be any positive integer, even though here we take
             * it to be a power of two. In fact, in many cases one might instead want it
             * to be a prime number; we will see this in later examples. The plaintext
             * modulus determines the size of the plaintext data type and the consumption
             * of noise budget in multiplications. Thus, it is essential to try to keep the
             * plaintext data type as small as possible for best performance. The noise
             * budget in a freshly encrypted ciphertext is
             *
             *  ~ log2(CoeffModulus/PlainModulus) (bits)
             *
             * and the noise budget consumption in a homomorphic multiplication is of the
             * form log2(PlainModulus) + (other terms).
             *
             * The plaintext modulus is specific to the BFV scheme, and cannot be set when
             * using the CKKS scheme.
             */
            parms.PlainModulus = new SmallModulus(1024);

            /*
             * Now that all parameters are set, we are ready to construct a SEALContext
             * object. This is a heavy class that checks the validity and properties of the
             * parameters we just set.
             */
            SEALContext context = new SEALContext(parms);

            /*
             * Print the parameters that we have chosen.
             */
            Utilities.PrintLine();
            Console.WriteLine("Set encryption parameters and print");
            Utilities.PrintParameters(context);

            Console.WriteLine();
            Console.WriteLine("~~~~~~ A naive way to calculate 4(x^2+1)(x+1)^2. ~~~~~~");

            /*
             * The encryption schemes in Microsoft SEAL are public key encryption schemes.
             * For users unfamiliar with this terminology, a public key encryption scheme
             * has a separate public key for encrypting data, and a separate secret key for
             * decrypting data. This way multiple parties can encrypt data using the same
             * shared public key, but only the proper recipient of the data can decrypt it
             * with the secret key.
             *
             * We are now ready to generate the secret and public keys. For this purpose
             * we need an instance of the KeyGenerator class. Constructing a KeyGenerator
             * automatically generates the public and secret key, which can immediately be
             * read to local variables.
             */
            KeyGenerator keygen    = new KeyGenerator(context);
            PublicKey    publicKey = keygen.PublicKey;
            SecretKey    secretKey = keygen.SecretKey;

            /*
             * To be able to encrypt we need to construct an instance of Encryptor. Note
             * that the Encryptor only requires the public key, as expected.
             */
            Encryptor encryptor = new Encryptor(context, publicKey);

            /*
             * Computations on the ciphertexts are performed with the Evaluator class. In
             * a real use-case the Evaluator would not be constructed by the same party
             * that holds the secret key.
             */
            Evaluator evaluator = new Evaluator(context);

            /*
             * We will of course want to decrypt our results to verify that everything worked,
             * so we need to also construct an instance of Decryptor. Note that the Decryptor
             * requires the secret key.
             */
            Decryptor decryptor = new Decryptor(context, secretKey);

            /*
             * As an example, we evaluate the degree 4 polynomial
             *
             *  4x^4 + 8x^3 + 8x^2 + 8x + 4
             *
             * over an encrypted x = 6. The coefficients of the polynomial can be considered
             * as plaintext inputs, as we will see below. The computation is done modulo the
             * plain_modulus 1024.
             *
             * While this examples is simple and easy to understand, it does not have much
             * practical value. In later examples we will demonstrate how to compute more
             * efficiently on encrypted integers and real or complex numbers.
             *
             * Plaintexts in the BFV scheme are polynomials of degree less than the degree
             * of the polynomial modulus, and coefficients integers modulo the plaintext
             * modulus. For readers with background in ring theory, the plaintext space is
             * the polynomial quotient ring Z_T[X]/(X^N + 1), where N is PolyModulusDegree
             * and T is PlainModulus.
             *
             * To get started, we create a plaintext containing the constant 6. For the
             * plaintext element we use a constructor that takes the desired polynomial as
             * a string with coefficients represented as hexadecimal numbers.
             */
            Utilities.PrintLine();
            int       x      = 6;
            Plaintext xPlain = new Plaintext(x.ToString());

            Console.WriteLine($"Express x = {x} as a plaintext polynomial 0x{xPlain}.");

            /*
             * We then encrypt the plaintext, producing a ciphertext.
             */
            Utilities.PrintLine();
            Ciphertext xEncrypted = new Ciphertext();

            Console.WriteLine("Encrypt xPlain to xEncrypted.");
            encryptor.Encrypt(xPlain, xEncrypted);

            /*
             * In Microsoft SEAL, a valid ciphertext consists of two or more polynomials
             * whose coefficients are integers modulo the product of the primes in the
             * coeff_modulus. The number of polynomials in a ciphertext is called its `size'
             * and is given by Ciphertext.Size. A freshly encrypted ciphertext always has
             * size 2.
             */
            Console.WriteLine($"    + size of freshly encrypted x: {xEncrypted.Size}");

            /*
             * There is plenty of noise budget left in this freshly encrypted ciphertext.
             */
            Console.WriteLine("    + noise budget in freshly encrypted x: {0} bits",
                              decryptor.InvariantNoiseBudget(xEncrypted));

            /*
             * We decrypt the ciphertext and print the resulting plaintext in order to
             * demonstrate correctness of the encryption.
             */
            Plaintext xDecrypted = new Plaintext();

            Console.Write("    + decryption of encrypted_x: ");
            decryptor.Decrypt(xEncrypted, xDecrypted);
            Console.WriteLine($"0x{xDecrypted} ...... Correct.");

            /*
             * When using Microsoft SEAL, it is typically advantageous to compute in a way
             * that minimizes the longest chain of sequential multiplications. In other
             * words, encrypted computations are best evaluated in a way that minimizes
             * the multiplicative depth of the computation, because the total noise budget
             * consumption is proportional to the multiplicative depth. For example, for
             * our example computation it is advantageous to factorize the polynomial as
             *
             *  4x^4 + 8x^3 + 8x^2 + 8x + 4 = 4(x + 1)^2 * (x^2 + 1)
             *
             * to obtain a simple depth 2 representation. Thus, we compute (x + 1)^2 and
             * (x^2 + 1) separately, before multiplying them, and multiplying by 4.
             *
             * First, we compute x^2 and add a plaintext "1". We can clearly see from the
             * print-out that multiplication has consumed a lot of noise budget. The user
             * can vary the plain_modulus parameter to see its effect on the rate of noise
             * budget consumption.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute xSqPlusOne (x^2+1).");
            Ciphertext xSqPlusOne = new Ciphertext();

            evaluator.Square(xEncrypted, xSqPlusOne);
            Plaintext plainOne = new Plaintext("1");

            evaluator.AddPlainInplace(xSqPlusOne, plainOne);

            /*
             * Encrypted multiplication results in the output ciphertext growing in size.
             * More precisely, if the input ciphertexts have size M and N, then the output
             * ciphertext after homomorphic multiplication will have size M+N-1. In this
             * case we perform a squaring, and observe both size growth and noise budget
             * consumption.
             */
            Console.WriteLine($"    + size of xSqPlusOne: {xSqPlusOne.Size}");
            Console.WriteLine("    + noise budget in xSqPlusOne: {0} bits",
                              decryptor.InvariantNoiseBudget(xSqPlusOne));

            /*
             * Even though the size has grown, decryption works as usual as long as noise
             * budget has not reached 0.
             */
            Plaintext decryptedResult = new Plaintext();

            Console.Write("    + decryption of xSqPlusOne: ");
            decryptor.Decrypt(xSqPlusOne, decryptedResult);
            Console.WriteLine($"0x{decryptedResult} ...... Correct.");

            /*
             * Next, we compute (x + 1)^2.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute xPlusOneSq ((x+1)^2).");
            Ciphertext xPlusOneSq = new Ciphertext();

            evaluator.AddPlain(xEncrypted, plainOne, xPlusOneSq);
            evaluator.SquareInplace(xPlusOneSq);
            Console.WriteLine($"    + size of xPlusOneSq: {xPlusOneSq.Size}");
            Console.WriteLine("    + noise budget in xPlusOneSq: {0} bits",
                              decryptor.InvariantNoiseBudget(xPlusOneSq));
            Console.Write("    + decryption of xPlusOneSq: ");
            decryptor.Decrypt(xPlusOneSq, decryptedResult);
            Console.WriteLine($"0x{decryptedResult} ...... Correct.");

            /*
             * Finally, we multiply (x^2 + 1) * (x + 1)^2 * 4.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute encryptedResult (4(x^2+1)(x+1)^2).");
            Ciphertext encryptedResult = new Ciphertext();
            Plaintext  plainFour       = new Plaintext("4");

            evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour);
            evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult);
            Console.WriteLine($"    + size of encrypted_result: {encryptedResult.Size}");
            Console.WriteLine("    + noise budget in encrypted_result: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedResult));
            Console.WriteLine("NOTE: Decryption can be incorrect if noise budget is zero.");

            Console.WriteLine();
            Console.WriteLine("~~~~~~ A better way to calculate 4(x^2+1)(x+1)^2. ~~~~~~");

            /*
             * Noise budget has reached 0, which means that decryption cannot be expected
             * to give the correct result. This is because both ciphertexts xSqPlusOne and
             * xPlusOneSq consist of 3 polynomials due to the previous squaring operations,
             * and homomorphic operations on large ciphertexts consume much more noise budget
             * than computations on small ciphertexts. Computing on smaller ciphertexts is
             * also computationally significantly cheaper.
             *
             * `Relinearization' is an operation that reduces the size of a ciphertext after
             * multiplication back to the initial size, 2. Thus, relinearizing one or both
             * input ciphertexts before the next multiplication can have a huge positive
             * impact on both noise growth and performance, even though relinearization has
             * a significant computational cost itself. It is only possible to relinearize
             * size 3 ciphertexts down to size 2, so often the user would want to relinearize
             * after each multiplication to keep the ciphertext sizes at 2.
             *
             * Relinearization requires special `relinearization keys', which can be thought
             * of as a kind of public key. Relinearization keys can easily be created with
             * the KeyGenerator.
             *
             * Relinearization is used similarly in both the BFV and the CKKS schemes, but
             * in this example we continue using BFV. We repeat our computation from before,
             * but this time relinearize after every multiplication.
             *
             * We use KeyGenerator.RelinKeys() to create relinearization keys.
             */
            Utilities.PrintLine();
            Console.WriteLine("Generate relinearization keys.");
            RelinKeys relinKeys = keygen.RelinKeys();

            /*
             * We now repeat the computation relinearizing after each multiplication.
             */
            Utilities.PrintLine();
            Console.WriteLine("Compute and relinearize xSquared (x^2),");
            Console.WriteLine(new string(' ', 13) + "then compute xSqPlusOne (x^2+1)");
            Ciphertext xSquared = new Ciphertext();

            evaluator.Square(xEncrypted, xSquared);
            Console.WriteLine($"    + size of xSquared: {xSquared.Size}");
            evaluator.RelinearizeInplace(xSquared, relinKeys);
            Console.WriteLine("    + size of xSquared (after relinearization): {0}",
                              xSquared.Size);
            evaluator.AddPlain(xSquared, plainOne, xSqPlusOne);
            Console.WriteLine("    + noise budget in xSqPlusOne: {0} bits",
                              decryptor.InvariantNoiseBudget(xSqPlusOne));
            Console.Write("    + decryption of xSqPlusOne: ");
            decryptor.Decrypt(xSqPlusOne, decryptedResult);
            Console.WriteLine($"0x{decryptedResult} ...... Correct.");

            Utilities.PrintLine();
            Ciphertext xPlusOne = new Ciphertext();

            Console.WriteLine("Compute xPlusOne (x+1),");
            Console.WriteLine(new string(' ', 13) +
                              "then compute and relinearize xPlusOneSq ((x+1)^2).");
            evaluator.AddPlain(xEncrypted, plainOne, xPlusOne);
            evaluator.Square(xPlusOne, xPlusOneSq);
            Console.WriteLine($"    + size of xPlusOneSq: {xPlusOneSq.Size}");
            evaluator.RelinearizeInplace(xPlusOneSq, relinKeys);
            Console.WriteLine("    + noise budget in xPlusOneSq: {0} bits",
                              decryptor.InvariantNoiseBudget(xPlusOneSq));
            Console.Write("    + decryption of xPlusOneSq: ");
            decryptor.Decrypt(xPlusOneSq, decryptedResult);
            Console.WriteLine($"0x{decryptedResult} ...... Correct.");

            Utilities.PrintLine();
            Console.WriteLine("Compute and relinearize encryptedResult (4(x^2+1)(x+1)^2).");
            evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour);
            evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult);
            Console.WriteLine($"    + size of encryptedResult: {encryptedResult.Size}");
            evaluator.RelinearizeInplace(encryptedResult, relinKeys);
            Console.WriteLine("    + size of encryptedResult (after relinearization): {0}",
                              encryptedResult.Size);
            Console.WriteLine("    + noise budget in encryptedResult: {0} bits",
                              decryptor.InvariantNoiseBudget(encryptedResult));

            Console.WriteLine();
            Console.WriteLine("NOTE: Notice the increase in remaining noise budget.");

            /*
             * Relinearization clearly improved our noise consumption. We have still plenty
             * of noise budget left, so we can expect the correct answer when decrypting.
             */
            Utilities.PrintLine();
            Console.WriteLine("Decrypt encrypted_result (4(x^2+1)(x+1)^2).");
            decryptor.Decrypt(encryptedResult, decryptedResult);
            Console.WriteLine("    + decryption of 4(x^2+1)(x+1)^2 = 0x{0} ...... Correct.",
                              decryptedResult);

            /*
             * For x=6, 4(x^2+1)(x+1)^2 = 7252. Since the plaintext modulus is set to 1024,
             * this result is computed in integers modulo 1024. Therefore the expected output
             * should be 7252 % 1024 == 84, or 0x54 in hexadecimal.
             */
        }
Exemplo n.º 30
0
        static private void ExampleCKKSEncoder()
        {
            Utilities.PrintExampleBanner("Example: Encoders / CKKS Encoder");

            /*
             * [CKKSEncoder] (For CKKS scheme only)
             *
             * In this example we demonstrate the Cheon-Kim-Kim-Song (CKKS) scheme for
             * computing on encrypted real or complex numbers. We start by creating
             * encryption parameters for the CKKS scheme. There are two important
             * differences compared to the BFV scheme:
             *
             *  (1) CKKS does not use the PlainModulus encryption parameter;
             *  (2) Selecting the CoeffModulus in a specific way can be very important
             *      when using the CKKS scheme. We will explain this further in the file
             *      `CKKS_Basics.cs'. In this example we use CoeffModulus.Create to
             *      generate 5 40-bit prime numbers.
             */
            using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);

            ulong polyModulusDegree = 8192;

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

            /*
             * We create the SEALContext as usual and print the parameters.
             */
            using SEALContext context = new SEALContext(parms);
            Utilities.PrintParameters(context);
            Console.WriteLine();

            /*
             * Keys are created the same way as for the BFV scheme.
             */
            using KeyGenerator keygen = new KeyGenerator(context);
            using SecretKey secretKey = keygen.SecretKey;
            keygen.CreatePublicKey(out PublicKey publicKey);
            keygen.CreateRelinKeys(out RelinKeys relinKeys);

            /*
             * We also set up an Encryptor, Evaluator, and Decryptor as usual.
             */
            using Encryptor encryptor = new Encryptor(context, publicKey);
            using Evaluator evaluator = new Evaluator(context);
            using Decryptor decryptor = new Decryptor(context, secretKey);

            /*
             * To create CKKS plaintexts we need a special encoder: there is no other way
             * to create them. The BatchEncoder cannot be used with the
             * CKKS scheme. The CKKSEncoder encodes vectors of real or complex numbers into
             * Plaintext objects, which can subsequently be encrypted. At a high level this
             * looks a lot like what BatchEncoder does for the BFV scheme, but the theory
             * behind it is completely different.
             */
            using CKKSEncoder encoder = new CKKSEncoder(context);

            /*
             * In CKKS the number of slots is PolyModulusDegree / 2 and each slot encodes
             * one real or complex number. This should be contrasted with BatchEncoder in
             * the BFV scheme, where the number of slots is equal to PolyModulusDegree
             * and they are arranged into a matrix with two rows.
             */
            ulong slotCount = encoder.SlotCount;

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

            /*
             * We create a small vector to encode; the CKKSEncoder will implicitly pad it
             * with zeros to full size (PolyModulusDegree / 2) when encoding.
             */
            double[] input = new double[] { 0.0, 1.1, 2.2, 3.3 };
            Console.WriteLine("Input vector: ");
            Utilities.PrintVector(input);

            /*
             * Now we encode it with CKKSEncoder. The floating-point coefficients of `input'
             * will be scaled up by the parameter `scale'. This is necessary since even in
             * the CKKS scheme the plaintext elements are fundamentally polynomials with
             * integer coefficients. It is instructive to think of the scale as determining
             * the bit-precision of the encoding; naturally it will affect the precision of
             * the result.
             *
             * In CKKS the message is stored modulo CoeffModulus (in BFV it is stored modulo
             * PlainModulus), so the scaled message must not get too close to the total size
             * of CoeffModulus. In this case our CoeffModulus is quite large (200 bits) so
             * we have little to worry about in this regard. For this simple example a 30-bit
             * scale is more than enough.
             */
            using Plaintext plain = new Plaintext();
            double scale = Math.Pow(2.0, 30);

            Utilities.PrintLine();
            Console.WriteLine("Encode input vector.");
            encoder.Encode(input, scale, plain);

            /*
             * We can instantly decode to check the correctness of encoding.
             */
            List <double> output = new List <double>();

            Console.WriteLine("    + Decode input vector ...... Correct.");
            encoder.Decode(plain, output);
            Utilities.PrintVector(output);

            /*
             * The vector is encrypted the same was as in BFV.
             */
            using Ciphertext encrypted = new Ciphertext();
            Utilities.PrintLine();
            Console.WriteLine("Encrypt input vector, square, and relinearize.");
            encryptor.Encrypt(plain, encrypted);

            /*
             * Basic operations on the ciphertexts are still easy to do. Here we square
             * the ciphertext, decrypt, decode, and print the result. We note also that
             * decoding returns a vector of full size (PolyModulusDegree / 2); this is
             * because of the implicit zero-padding mentioned above.
             */
            evaluator.SquareInplace(encrypted);
            evaluator.RelinearizeInplace(encrypted, relinKeys);

            /*
             * We notice that the scale in the result has increased. In fact, it is now
             * the square of the original scale: 2^60.
             */
            Console.WriteLine("    + Scale in squared input: {0} ({1} bits)",
                              encrypted.Scale,
                              (int)Math.Ceiling(Math.Log(encrypted.Scale, newBase: 2)));
            Utilities.PrintLine();
            Console.WriteLine("Decrypt and decode.");
            decryptor.Decrypt(encrypted, plain);
            encoder.Decode(plain, output);
            Console.WriteLine("    + Result vector ...... Correct.");
            Utilities.PrintVector(output);

            /*
             * The CKKS scheme allows the scale to be reduced between encrypted computations.
             * This is a fundamental and critical feature that makes CKKS very powerful and
             * flexible. We will discuss it in great detail in `3_Levels.cs' and later in
             * `4_CKKS_Basics.cs'.
             */
        }
Exemplo n.º 31
0
 public MasterKeyData(MasterKey masterKeyRecord, SecretKey secretKey)
 {
     this.masterKeyRecord    = masterKeyRecord;
     this.generatedSecretKey = secretKey;
 }
Exemplo n.º 32
0
 public static byte[] getServerHash(String toencode, PublicKey par1PublicKey, SecretKey par2SecretKey)
 {
     return digest("SHA-1", new byte[][] { Encoding.GetEncoding("iso-8859-1").GetBytes(toencode), par2SecretKey.getEncoded(), par1PublicKey.getEncoded() });
 }
Exemplo n.º 33
0
        private static void ExampleCKKSBasics()
        {
            Utilities.PrintExampleBanner("Example: CKKS Basics");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            /*
             * While we did not show any computations on complex numbers in these examples,
             * the CKKSEncoder would allow us to have done that just as easily. Additions
             * and multiplications of complex numbers behave just as one would expect.
             */
        }