private void oLoadItemButton_Click(object sender, RoutedEventArgs e)
        {
            // select all the certs associated with this user
            X509Certificate2 oCert = GetUserKey(UserListSelected.Where <User>(u => u.IsOwnedByCurrentUser));

            if (oCert == null)
            {
                return;
            }

            using (CryptureEntities oContent = new CryptureEntities())
            {
                // reconnect our instance so we can lookup the cipher
                oContent.Entry(ThisItem).State = EntityState.Unchanged;

                // look for the matching instance
                Instance oInstance = ThisItem.Instances.Where(
                    i => StructuralComparisons.StructuralEqualityComparer.Equals(
                        i.User.Certificate, oCert.RawData)).FirstOrDefault();

                try
                {
                    // setup an aes decryptor using the iv and decrypted key
                    using (Aes oCng = AesCng.Create())
                    {
                        // always attempt to use next generation classes first before
                        // resorting to using legacy crytographic classes
                        try
                        {
                            using (RSA oRSA = oCert.GetRSAPrivateKey())
                            {
                                oCng.Key = oRSA.Decrypt(oInstance.CipherKey, RSAEncryptionPadding.Pkcs1);
                                oCng.IV  = ThisItem.Cipher.CipherVector;
                            }
                        }
                        catch (CryptographicException eCryptoOperation)
                        {
                            // exit if user opted to cancel
                            if ((uint)eCryptoOperation.HResult == 0x8010006E)
                            {
                                return;
                            }

                            using (RSACryptoServiceProvider oRSA = oCert.PrivateKey as RSACryptoServiceProvider)
                            {
                                oCng.Key = oRSA.Decrypt(oInstance.CipherKey, false);
                                oCng.IV  = ThisItem.Cipher.CipherVector;
                            }
                        }

                        // attempt to decode the data
                        using (MemoryStream oMemory = new MemoryStream())
                            using (CryptoStream oCrypto = new CryptoStream(
                                       oMemory, oCng.CreateDecryptor(), CryptoStreamMode.Write))
                            {
                                oCrypto.Write(ThisItem.Cipher.CipherText, 0, ThisItem.Cipher.CipherText.Length);
                                oCrypto.FlushFinalBlock();

                                // process text item
                                if (ThisItem.ItemType == "text")
                                {
                                    oItemData.Text = Encoding.Unicode.GetString(oMemory.ToArray());
                                }

                                // text binary item
                                else
                                {
                                    BinaryItemData = oMemory.ToArray();
                                }
                            }
                    }
                    // change the ui to allow saving again
                    SetEditingControls(true);
                }
                catch (Exception eError)
                {
                    MessageBox.Show(this,
                                    "An error occurred during item decryption: " +
                                    Environment.NewLine + Environment.NewLine + eError.Message,
                                    "Error During Item Decryption", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
        private void oSaveItemButton_Click(object sender, RoutedEventArgs e)
        {
            // perform data validation if in text mode and option is set
            if (ThisItem.ItemType.Equals("text") &&
                !String.IsNullOrWhiteSpace(Properties.Settings.Default.ItemTextExpressionFilter))
            {
                if (!Regex.Match(oItemData.Text, Properties.Settings.Default.ItemTextExpressionFilter).Success)
                {
                    // note to the user that the data was invalid
                    MessageBox.Show(this, "The item text provided does not satifsy the content filter.",
                                    "Invalid Item Text", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
            }

            // update the entity using the local copy we have
            using (CryptureEntities oContent = new CryptureEntities())
            {
                oContent.Entry(ThisItem).State = (ThisItem.CreatedDate == DateTime.MinValue)
                    ? EntityState.Added : EntityState.Modified;

                // verify the selected users
                foreach (User oUser in UserListSelected.ToArray())
                {
                    using (X509Certificate2 oCert = new X509Certificate2(oUser.Certificate))
                    {
                        if (CertificateOperations.CheckCertificateStatus(oCert) == false &&
                            MessageBox.Show(this,
                                            "The certificate for '" + oUser.Name + "' cannot be verified. " +
                                            "Should this certificate be removed from the list?",
                                            "Cannot Verify Certificate",
                                            MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                        {
                            // remove from list and force refresh
                            UserListSelected.Remove(oUser);
                            oAddCertDropDown.Items.Refresh();
                        }
                    }
                }

                // error if there are no selected users
                if (UserListSelected.Count == 0)
                {
                    MessageBox.Show(this, "This certificate share list is empty and cannot be saved.",
                                    "Empty Certificates List", MessageBoxButton.OK, MessageBoxImage.Question);
                    return;
                }

                using (Aes oCng = AesCng.Create())
                {
                    // create new cipher object and associate it with this id
                    ThisItem.Cipher      = new Cipher();
                    ThisItem.Cipher.Item = ThisItem;

                    using (MemoryStream oMemory = new MemoryStream())
                        using (CryptoStream oCrypto = new CryptoStream(
                                   oMemory, oCng.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            byte[] oPlainByte = ThisItem.ItemType.Equals("text") ?
                                                Encoding.Unicode.GetBytes(oItemData.Text) : BinaryItemData;
                            oCrypto.Write(oPlainByte, 0, oPlainByte.Length);
                            oCrypto.FlushFinalBlock();
                            ThisItem.Cipher.CipherText = oMemory.ToArray();
                        }

                    ThisItem.Cipher.CipherVector = oCng.IV;
                    ThisItem.CreatedDate         = DateTime.Now;
                    ThisItem.ModifiedDate        = DateTime.Now;

                    // clear out any existing instances
                    oContent.Instances.RemoveRange(ThisItem.Instances);

                    // encode each instance
                    foreach (User oUser in UserListSelected)
                    {
                        Instance oInstance = new Instance();
                        oInstance.Signature = new byte[] { };
                        oInstance.UserId    = oUser.UserId;
                        oInstance.ItemId    = ThisItem.ItemId;

                        byte[] oCipherByte = null;
                        using (X509Certificate2 oCert = new X509Certificate2(oUser.Certificate))
                        {
                            // always attempt to use next generation classes first before
                            // resorting to using legacy crytographic classes
                            try
                            {
                                using (RSA oRSA = oCert.GetRSAPublicKey())
                                {
                                    oCipherByte = oRSA.Encrypt(oCng.Key, RSAEncryptionPadding.Pkcs1);
                                }
                            }
                            catch (CryptographicException)
                            {
                                using (RSACryptoServiceProvider oRSA = oCert.PublicKey.Key as RSACryptoServiceProvider)
                                {
                                    oCipherByte = oRSA.Encrypt(oCng.Key, false);
                                }
                            }
                        }

                        oInstance.CipherKey = oCipherByte;
                        ThisItem.Instances.Add(oInstance);
                    }
                }

                // commit changes to database
                oContent.SaveChanges();
            }

            // close and return to calling dialog
            Close();
        }
Beispiel #3
0
        /// <summary>対称アルゴリズム暗号化サービスプロバイダ生成</summary>
        /// <param name="esa">EnumSymmetricAlgorithm</param>
        /// <param name="cm">CipherMode</param>
        /// <param name="pm">PaddingMode</param>
        /// <returns>SymmetricAlgorithm</returns>
        private SymmetricAlgorithm CreateSymmetricAlgorithm(EnumSymmetricAlgorithm esa, CipherMode cm, PaddingMode pm)
        {
            #region Constructor
            SymmetricAlgorithm sa = null;

            #region Aes
            if (esa.HasFlag(EnumSymmetricAlgorithm.AES_CSP))
            {
                // AesCryptoServiceProviderサービスプロバイダ
                sa = AesCryptoServiceProvider.Create(); // devps(1703)
            }
            else if (esa.HasFlag(EnumSymmetricAlgorithm.AES_M))
            {
                // AesManagedサービスプロバイダ
                sa = AesManaged.Create(); // devps(1703)
            }
#if NET45 || NET46
#else
            else if (esa.HasFlag(EnumSymmetricAlgorithm.AES_CNG))
            {
                // AesCngサービスプロバイダ
                sa = AesCng.Create(); // devps(1703)
            }
#endif
            #endregion

            #region TripleDES
            else if (esa.HasFlag(EnumSymmetricAlgorithm.TDES_CSP))
            {
                // TripleDESCryptoServiceProviderサービスプロバイダ
                sa = TripleDESCryptoServiceProvider.Create(); // devps(1703)
            }

#if NET45 || NET46
#else
            else if (esa.HasFlag(EnumSymmetricAlgorithm.TDES_CNG))
            {
                // TripleDESCngサービスプロバイダ
                sa = TripleDESCng.Create(); // devps(1703)
            }
#endif
            #endregion

            #region Others
            else if (esa.HasFlag(EnumSymmetricAlgorithm.DES_CSP))
            {
                // DESCryptoServiceProviderサービスプロバイダ
                sa = DESCryptoServiceProvider.Create(); // devps(1703)
            }

            else if (esa.HasFlag(EnumSymmetricAlgorithm.RC2_CSP))
            {
                // RC2CryptoServiceProviderサービスプロバイダ
                sa = RC2CryptoServiceProvider.Create(); // devps(1703)
            }

            else if (esa.HasFlag(EnumSymmetricAlgorithm.Rijndael_M))
            {
                // RijndaelManagedサービスプロバイダ
                sa = RijndaelManaged.Create(); // devps(1703)
            }
            #endregion

            else
            {
                throw new ArgumentException(
                          PublicExceptionMessage.ARGUMENT_INCORRECT, "EnumSymmetricAlgorithm esa");
            }
            #endregion

            #region Options
            // cmが設定されている場合。
            if (cm != 0)
            {
                sa.Mode = cm;
            }

            // pmが設定されている場合。
            if (pm != 0)
            {
                sa.Padding = pm;
            }
            #endregion

            return(sa);
        }
Beispiel #4
0
        private static void Main(string[] args)
        {
            // Get secrets
            var devEnvironmentVariable = Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT");
            var isDevelopment          = string.IsNullOrEmpty(devEnvironmentVariable) || devEnvironmentVariable.ToLower() == "development";

            string secretsPath = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                @"Microsoft\UserSecrets\9a735c2c-ec7a-4c5a-936e-7210fc978f5d",
                "secrets.json");

            var secrets = JsonConvert.DeserializeObject <UserSecrets>(File.ReadAllText(secretsPath));

            // Do everything else

            int val = 0;

            string systemName         = "aSystem";
            string rabbitMQServerName = "garage";
            string userName           = "******";
            string password           = "******";

            var duhh1 = AesCng.Create();


            CngProvider provider = new CngProvider("dumdum");


            var random = new Random();

            UInt32 key = random.NextUInt32();
            UInt32 iv  = random.NextUInt32();

            (var cipherText, var signature) = SimpleCBC.Encode("Hi", key, iv, 2);

            var sig = BitConverter.GetBytes(signature);

            var duhh    = System.Text.Encoding.UTF8.GetString(cipherText);
            var message = SimpleCBC.Decode(cipherText, key, iv, 2);


            var errorTag = new MessageTagValue("Severity", "Error");
            var infoTag  = new MessageTagValue("Severity", "Info");
            var debugTag = new MessageTagValue("Severity", "Debug");

            using var serverPublicInfo  = MessageClientIdentity.ImportFromFile(@"Keys\system-server.pub");
            using var serverPrivateInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-server.priv", "abc");

            using var coordinatorPublicInfo  = MessageClientIdentity.ImportFromFile(@"Keys\system-coordinator.pub");
            using var coordinatorPrivateInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-coordinator.priv", "monkey123");

            using var client1PublicInfo  = MessageClientIdentity.ImportFromFile(@"Keys\system-client1.pub");
            using var client1PrivateInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-client1.priv", "abc");

            using var client2PublicInfo  = MessageClientIdentity.ImportFromFile(@"Keys\system-client2.pub");
            using var client2PrivateInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-client2.priv", "abc");

            using var client3PublicInfo  = MessageClientIdentity.ImportFromFile(@"Keys\system-client3.pub");
            using var client3PrivateInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-client3.priv", "abc");

            //using var pushoverPublicInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-pushoverClient.pub");
            //using var pushoverPrivateInfo = MessageClientIdentity.ImportFromFile(@"Keys\system-pushoverClient.priv", "abc");


            Console.WriteLine(serverPublicInfo.IdentityHash);
            Console.WriteLine(client1PublicInfo.IdentityHash);
            Console.WriteLine(client2PublicInfo.IdentityHash);
            Console.WriteLine(client3PublicInfo.IdentityHash);



            var xbeeModule        = new XBeeNetworkGatewayModule("COM8", new SerialPortParameters(115200, 8, StopBits.One, Parity.None, Handshake.None));
            var coordinatorModule = new TrustCoordinatorModule(TimeSpan.FromMinutes(1));

            var server = new MessageClientConfigurationBuilder()
                         .RabbitMQCredentials(userName, password)
                         .RabbitMQServerHostName(rabbitMQServerName)
                         .Identity(coordinatorPrivateInfo)
                         .AddClientIdentity(client1PublicInfo)
                         .AddClientIdentity(client2PublicInfo)
                         .AddClientIdentity(client3PublicInfo)
                         //.AddClientIdentity(pushoverPublicInfo)
                         .AutoDeleteQueuesOnClose(true)
                         .QueuesAreDurable(false)
                         .AddModule(coordinatorModule)
                         .AddModule(xbeeModule)
                         .CreateMessageClient();


#if false
            var server = new MessageServerConfigurationBuilder()
                         .RabbitMQCredentials(userName, password)
                         .RabbitMQServerHostName(rabbitMQServerName)
                         .Identity(serverPrivateInfo)
                         .AddClientIdentity(client1PublicInfo)
                         .AddClientIdentity(client2PublicInfo)
                         .AddClientIdentity(client3PublicInfo)
                         //.AddClientIdentity(pushoverPublicInfo)
                         .AutoDeleteQueuesOnClose(true)
                         .QueuesAreDurable(false)
                         .CreateMessageServer();
#endif

            server.MessageReceived += (sender, e) =>
            {
                e.Response = MessageResponse.Ack;

                if (e.MessageEnevelope.Message.GetType() == typeof(XBeeFromXBeeMessage))
                {
                    var tempMessage = (XBeeFromXBeeMessage)e.MessageEnevelope.Message;

                    Log.Verbose($"{tempMessage.XBeeSourceAddress}: {tempMessage.RawData}");
                }
            };

            server.AsynchronousException += Client_AsynchronousException;

            System.Timers.Timer sendTimer = new System.Timers.Timer(1000)
            {
                AutoReset = true
            };

            sendTimer.Elapsed += (sender, e) =>
            {
                IntMessage message = new IntMessage(val);

                string tag = val % 2 == 0 ? "even" : "odd";

                server.WriteToSubscriptionQueues(message, true, new MessageTagValue("duhh", tag), errorTag, infoTag);
                val++;

                //server.BroacastToAllClients(message);
            };

            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Verbose()
                         //.WriteTo.DistributedWorkersSink(server)
                         .WriteTo.Console()
                         .CreateLogger();

            //Log.Verbose($"Server public string: {serverInfo.PublicKey.PublicKeyToString()}");

            server.Connect(TimeSpan.FromSeconds(20));
            sendTimer.Start();

            //Thread.Sleep(30000);

            var odd   = new MessageTagValue("duhh", "odd");
            var even  = new MessageTagValue("duhh", "even");
            var never = new MessageTagValue("duhh", "never");

#if false
            var pushoverModule = new PushoverModule(secrets.PushoverAppApiKey, secrets.PushoverUserKey);
            pushoverModule.AddTransform <IntMessage>(t =>
            {
                if (t.Payload % 10 == 0)
                {
                    return(null); // (t.Payload.ToString());
                }

                return(null);
            });
#endif



            // TODO: Not all configuration options return the right configuration builder type
#if false
            var pushoverClient = new PushoverMessageClientConfigurationBuilder()
                                 .PushoverAppApiKey(secrets.PushoverAppApiKey)
                                 .PushoverUserKey(secrets.PushoverUserKey)
                                 .RabbitMQCredentials(userName, password)
                                 .RabbitMQServerHostName(rabbitMQServerName)
                                 .ServerIdentity(serverPublicInfo)
                                 .Identity(pushoverPrivateInfo)
                                 .AutoDeleteQueuesOnClose(true)
                                 .QueuesAreDurable(false)
                                 .CreateMessageClient();


            pushoverClient.AddTransform <IntMessage>(t =>
            {
                if (t.Payload % 10 == 0)
                {
                    return(null); // (t.Payload.ToString());
                }

                return(null);
            });

            pushoverClient.AsynchronousException += Client_AsynchronousException;
            pushoverClient.Connect(20000);
#endif

            AzureIoTModule iotModule = new AzureIoTModule(secrets.AzureIoTHubConnectionString);
            iotModule.ForwardMessageToIoTHubTransform = (me) =>
            {
                return(null);

                if (me.Message.GetType() == typeof(XBeeFromXBeeMessage))
                {
                    var xBeeMessage = (XBeeFromXBeeMessage)me.Message;

                    var iotMessage = new Microsoft.Azure.Devices.Client.Message();

                    var tempData = xBeeMessage.GetJObject()["Data"];

                    iotMessage.Properties.Add("Refrigerator Temperature", tempData[0]["Refrigerator"].ToString());
                    iotMessage.Properties.Add("Freezer Temperature", tempData[1]["Freezer"].ToString());

                    return(iotMessage);
                }

                return(null);
            };

            MessageClient client1 = new MessageClientConfigurationBuilder()
                                    .RabbitMQCredentials(userName, password)
                                    .RabbitMQServerHostName(rabbitMQServerName)
                                    .TrustCoordinatorIdentity(coordinatorPublicInfo)
                                    .Identity(client1PrivateInfo)
                                    .AutoDeleteQueuesOnClose(true)
                                    .QueuesAreDurable(false)
                                    //.AddModule(pushoverModule)
                                    .AddModule(iotModule)
                                    .CreateMessageClient();

            xbeeModule.OpenXBee();

            client1.AsynchronousException += Client_AsynchronousException;

            client1.MessageReceived += (sender, e) =>
            {
                e.Response = MessageResponse.Ack;

                if (e.MessageEnevelope.Message.GetType() == typeof(IntMessage))
                {
                    Console.WriteLine($"Client 1: Message Payload: {((IntMessage)e.MessageEnevelope.Message).Value}.");
                }
            };
            client1.Connect(TimeSpan.FromSeconds(10), odd, new XBeeReceivedDataTag());
            client1.BeginFullWorkConsume(true);

            MessageClient client2 = new MessageClientConfigurationBuilder()
                                    .RabbitMQCredentials(userName, password)
                                    .RabbitMQServerHostName(rabbitMQServerName)
                                    .TrustCoordinatorIdentity(coordinatorPublicInfo)
                                    .Identity(client2PrivateInfo)
                                    .AutoDeleteQueuesOnClose(true)
                                    .QueuesAreDurable(false)
                                    .CreateMessageClient();

            client2.AsynchronousException += Client_AsynchronousException;

            client2.MessageReceived += (sender, e) =>
            {
                e.Response = MessageResponse.Ack;
                if (e.MessageEnevelope.Message.GetType() == typeof(IntMessage))
                {
                    Console.WriteLine($"Client 2: Message Payload: {((IntMessage)e.MessageEnevelope.Message).Value}.");
                }
                else if (e.MessageEnevelope.Message.GetType() == typeof(XBeeFromXBeeMessage))
                {
                    var tempMessage = (XBeeFromXBeeMessage)e.MessageEnevelope.Message;

                    Console.WriteLine($"Client 2 XBee ({tempMessage.XBeeSourceAddress}): {tempMessage.RawData}");
                }
            };
            client2.Connect(TimeSpan.FromSeconds(10), even, new XBeeReceivedDataTag());
            //client2.BeginFullWorkConsume(true);

#if false
            MessageClient client3 = new MessageClientConfiguration()
                                    .RabbitMQCredentials(userName, password)
                                    .RabbitMQServer(rabbitMQServerName)
                                    .ServerInfo(serverInfo)
                                    .ClientInfo(client3Info)
                                    .AutoDeleteQueuesOnClose(true)
                                    .QueuesAreDurable(false)
                                    .CreateMessageClient();
            client3.MessageReceived += (sender, e) =>
            {
                e.Response = MessageResponse.Ack;
                Console.WriteLine($"Client 3: Message Payload: {((IntMessage)e.MessageEnevelope.Message).Payload}.");
            };

            client3.BeginFullWorkConsume(true);
#endif

            //
            //client3.Connect(TimeSpan.FromSeconds(10));


            var serialPort = new XBeeRemoteSerialPort(xbeeModule, new SerializableXBeeAddress(new XBee64BitAddress("0013A20041AE9E32")));

            Log.Information("Dumdum");

            Console.ReadKey();
        }
        private byte[] EncryptBinaryDataInternal(ref byte[] data, ref byte[] encryptedKey, bool useExternalKey)
        {
            var ms            = new MemoryStream(data);
            var msEncodedData = new MemoryStream();

            using (Aes aesAlg = AesCng.Create("AES"))
            {
                if (useExternalKey)
                {
                    ProtectedMemory.Unprotect(encryptedKey, MemoryProtectionScope.SameProcess);
                }

                if (aesAlg == null)
                {
                    return(msEncodedData.ToArray());
                }

                var hashAlg = SHA512Cng.Create("SHA512");
                hashAlg.Initialize();

                aesAlg.BlockSize = 128;
                aesAlg.KeySize   = 256;
                aesAlg.Padding   = PaddingMode.PKCS7;
                aesAlg.Mode      = CipherMode.CBC;
                aesAlg.GenerateIV();
                Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(encryptedKey, SaltBytes, 1000, HashAlgorithmName.SHA256);
                byte[]             key = rfc2898DeriveBytes.CryptDeriveKey("AES", "SHA256", 256, aesAlg.IV);

                // Create AES Crypto Transform to be used in the CryptoStream transform function
                ICryptoTransform cryptoTransform = aesAlg.CreateEncryptor(key, aesAlg.IV);

                // Protect encryption Key Again
                if (useExternalKey)
                {
                    ProtectedMemory.Protect(encryptedKey, MemoryProtectionScope.SameProcess);
                }

                // Create the streams used for encryption.
                int bufferSize = (int)Math.Min(MaxBufferSize, ms.Length);
                var buffer     = new byte[bufferSize];
                ms.Position = 0;

                //Write Init Vector - Always 16 bytes
                msEncodedData.Write(aesAlg.IV, 0, 16);

                // Write Validation Hash - Always 64 bytes
                byte[] hashBuffer = hashAlg.ComputeHash(data);
                msEncodedData.Write(hashBuffer, 0, hashBuffer.Length);

                // Write 32 byte of entropy
                hashBuffer = rfc2898DeriveBytes.GetBytes(32);
                msEncodedData.Write(hashBuffer, 0, hashBuffer.Length);

                using (var csEncrypt = new CryptoStream(msEncodedData, cryptoTransform, CryptoStreamMode.Write))
                {
                    int bytesRead;
                    while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        csEncrypt.Write(buffer, 0, bytesRead);
                    }

                    csEncrypt.FlushFinalBlock();
                    msEncodedData.Flush();
                }

                rfc2898DeriveBytes.Dispose();
            }

            return(msEncodedData.ToArray());
        }
        private byte[] DecryptBinaryDataInternal(ref byte[] data, ref byte[] encryptedKey, bool useExternalKey, out bool dataIsValid)
        {
            var msDecrypted = new MemoryStream();
            var msEncrypted = new MemoryStream(data, MetadataLength - 1, data.Length - MetadataLength);
            var msMetadata  = new MemoryStream(data, 0, MetadataLength);

            using (Aes aesAlg = AesCng.Create("AES"))
            {
                if (useExternalKey)
                {
                    ProtectedMemory.Unprotect(encryptedKey, MemoryProtectionScope.SameProcess);
                }

                if (aesAlg == null)
                {
                    dataIsValid = false;
                    return(null);
                }

                SHA512 hashAlg = SHA512Cng.Create("SHA512");
                hashAlg.Initialize();


                byte[] initVector = new byte[16];
                msMetadata.Read(initVector, 0, initVector.Length);

                byte[] hashBuffer = new byte[64];
                msMetadata.Read(hashBuffer, 0, hashBuffer.Length);

                byte[] entropyBytes = new byte[32];
                msMetadata.Read(entropyBytes, 0, entropyBytes.Length);


                int encryptedDataLength = data.Length;

                aesAlg.BlockSize = 128;
                aesAlg.KeySize   = 256;
                aesAlg.Padding   = PaddingMode.PKCS7;
                aesAlg.Mode      = CipherMode.CBC;
                aesAlg.IV        = initVector;
                var    rfc2898DeriveBytes = new Rfc2898DeriveBytes(encryptedKey, SaltBytes, 1000, HashAlgorithmName.SHA256);
                byte[] key = rfc2898DeriveBytes.CryptDeriveKey("AES", "SHA256", 256, aesAlg.IV);

                // Create AES Crypto Transform to be used in the CryptoStream transform function
                ICryptoTransform cryptoTransform = aesAlg.CreateDecryptor(key, initVector);

                // Create the streams used for encryption.
                int bufferSize     = Math.Min(MaxBufferSize, encryptedDataLength);
                var plainTextBytes = new byte[bufferSize];


                // Protect encryption Key Again
                if (useExternalKey)
                {
                    ProtectedMemory.Protect(encryptedKey, MemoryProtectionScope.SameProcess);
                }

                // Create the streams used for decryption.
                using (var csDecrypt = new CryptoStream(msEncrypted, cryptoTransform, CryptoStreamMode.Read))
                {
                    int decryptedByteCount;
                    while ((decryptedByteCount = csDecrypt.Read(plainTextBytes, 0, plainTextBytes.Length)) > 0)
                    {
                        msDecrypted.Write(plainTextBytes, 0, decryptedByteCount);
                    }
                }

                byte[] validationHash = hashAlg.ComputeHash(msDecrypted);
                dataIsValid = validationHash.AsEnumerable().SequenceEqual(hashBuffer);
                rfc2898DeriveBytes.Dispose();
                msEncrypted.Dispose();
                msMetadata.Dispose();
            }

            return(msDecrypted.ToArray());
        }