/// <summary>
        /// Decrypt received file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void DownloadButton_Click(object sender, RoutedEventArgs e)
        {
            // TODO: select a place to save
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Title = "Save as"
            };

            if (saveFileDialog.ShowDialog() == true)
            {
                FileStream   outputStream = null;
                MemoryStream memoryStream = null;

                try
                {
                    outputStream = new FileStream(saveFileDialog.FileName, FileMode.CreateNew, FileAccess.Write);

                    if (sender is Button button)
                    {
                        if (button.DataContext is Message message)
                        {
                            // convert packet to memoryStream
                            memoryStream = new MemoryStream(message.Packet.EncryptedData.Length + 2_000);

                            memoryStream.Write(new byte[] { (byte)message.Packet.DataType }, 0, 1);

                            memoryStream.Write(BitConverter.GetBytes((ushort)message.Packet.EncryptedSessionKey.Length), 0, 2);
                            memoryStream.Write(message.Packet.EncryptedSessionKey, 0, message.Packet.EncryptedSessionKey.Length);

                            memoryStream.Write(message.Packet.Iv, 0, message.Packet.Iv.Length);
                            memoryStream.Write(message.Packet.Hmac, 0, message.Packet.Hmac.Length);
                            memoryStream.Write(message.Packet.Signature, 0, message.Packet.Signature.Length);
                            await memoryStream.WriteAsync(message.Packet.EncryptedData, 0, message.Packet.EncryptedData.Length).ConfigureAwait(false);

                            try
                            {
                                await HybridEncryption.DecryptFile(memoryStream, outputStream, AsymmetricEncryption.PublicKeyFromXml(message.Sender.PublicKey)).ConfigureAwait(false);

                                await outputStream.FlushAsync().ConfigureAwait(false);
                            }
                            catch (CryptoException exception)
                            {
                                ErrorText = exception.Message;
                                MessageBox.Show(exception.Message);
                            }
                        }
                    }
                }
                catch (IOException exception)
                {
                    MessageBox.Show(exception.Message);
                }
                finally
                {
                    outputStream?.Close();
                    memoryStream?.Close();
                }
            }
        }
        public async Task Can_Decrypt_Large_Stream_Of_Data()
        {
            byte[] fileBytes = Random.GetNumbers(128_000_000);

            MemoryStream rawStream = new MemoryStream(fileBytes);

            MemoryStream encryptedBytes = new MemoryStream();
            await HybridEncryption.EncryptFile(rawStream, encryptedBytes, asymmetricPublicKey);

            encryptedBytes.Position = 0;

            MemoryStream decryptedStream = new MemoryStream();
            bool         hashOk          = await HybridEncryption.DecryptFile(encryptedBytes, decryptedStream, asymmetricPublicKey);

            decryptedStream.Position = 0;
            byte[] decryptedBytes = decryptedStream.ToArray();

            Assert.True(hashOk);
            CollectionAssert.IsNotEmpty(decryptedBytes);
            CollectionAssert.AreEqual(fileBytes, decryptedBytes);
        }
        private async void DecryptButton_Click(object sender, RoutedEventArgs e)
        {
            ErrorTextBlock.Visibility = Visibility.Hidden;
            StatusImage.Visibility    = Visibility.Hidden;

            if (UserInputRSADetails())
            {
                return;
            }

            // ask user for file to decrypt
            string originalFile = null;

            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Title  = "Choose a file to decrypt";
            openFileDialog.Filter = "Decrypted file (*.crypto)|*.crypto|All files (*.*)|*.*";

            if (openFileDialog.ShowDialog() == true)
            {
                originalFile = openFileDialog.FileName;
            }

            // ask user for location to save decrypted file
            string decryptedFile = null;

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title = "Save as";

            if (saveFileDialog.ShowDialog() == true)
            {
                decryptedFile = saveFileDialog.FileName;
            }

            // only open filestreams if files were selected by user
            if (originalFile != null && decryptedFile != null)
            {
                // open streams
                FileStream inputStream  = null;
                FileStream outputStream = null;

                try
                {
                    inputStream  = File.OpenRead(originalFile);
                    outputStream = File.OpenWrite(decryptedFile);

                    bool succeeded = await HybridEncryption.DecryptFile(inputStream, outputStream, AsymmetricEncryption.PublicKeyFromXml(PublicRSAKeyReceiver.Text));

                    if (succeeded)
                    {
                        StatusImage.Visibility = Visibility.Visible;
                        StatusImage.Source     = new BitmapImage(new Uri(@"/Images/checkmark.png", UriKind.Relative));
                    }
                    else
                    {
                        StatusImage.Visibility = Visibility.Visible;
                        StatusImage.Source     = new BitmapImage(new Uri(@"/Images/redx.png", UriKind.Relative));
                    }
                }
                catch (IOException exception)
                {
                    ErrorTextBlock.Visibility = Visibility.Visible;
                    ErrorTextBlock.Text       = exception.Message;
                }
                finally
                {
                    inputStream?.Close();
                    outputStream?.Close();
                }
            }
        }
        private async void DecryptFileStenographyButton_Click(object sender, RoutedEventArgs e)
        {
            FileStream   stegFile      = null;
            MemoryStream encryptedData = null;
            MemoryStream messageData   = null;

            try
            {
                // open file
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Title = "Choose a file to put decrypted message";

                if (openFileDialog.ShowDialog() == true)
                {
                    stegFile = new FileStream(openFileDialog.FileName, FileMode.Open, FileAccess.Read);
                }
                else
                {
                    return;
                }

                // get length
                byte[] stegBuffer = new byte[64];
                stegFile.Read(stegBuffer, 0, 64);

                byte[] lengthBuffer = new byte[8];
                for (int i = 0; i < 8; i++)
                {
                    lengthBuffer[i] = GlueByteTogether(stegBuffer.Skip(i * 8).Take(8).ToArray());
                }

                long length = BitConverter.ToInt64(lengthBuffer, 0);
                encryptedData = new MemoryStream();

                // read rest of bytes
                long current = 0;
                stegBuffer = new byte[8];
                while (current < length)
                {
                    current++;

                    // read from input
                    await stegFile.ReadAsync(stegBuffer, 0, 8);

                    // convert to single byte
                    byte gluedByte = GlueByteTogether(stegBuffer);

                    // write byte to memorystream
                    await encryptedData.WriteAsync(new byte[] { gluedByte }, 0, 1);
                }

                // decrypt data
                messageData = new MemoryStream();
                await HybridEncryption.DecryptFile(encryptedData, messageData, AsymmetricEncryption.PublicKeyFromXml(PublicRSAKeyReceiver.Text));

                // show message to user
                string message = Encoding.UTF8.GetString(messageData.ToArray());
                MessageBox.Show(message);
            }
            catch (IOException exception)
            {
                ErrorTextBlock.Text       = exception.Message;
                ErrorTextBlock.Visibility = Visibility.Visible;
            }
            catch (CryptoException exception)
            {
                ErrorTextBlock.Text       = exception.Message;
                ErrorTextBlock.Visibility = Visibility.Visible;
            }
            finally
            {
                stegFile?.Close();
                encryptedData?.Close();
                messageData?.Close();
            }
        }
        private async void DecryptMessageButton_Click(object sender, RoutedEventArgs e)
        {
            //bericht is leeg
            ErrorTextBlock.Visibility = Visibility.Hidden;
            StatusImage.Visibility    = Visibility.Hidden;

            if (UserInputRSADetails())
            {
                return;
            }

            // ask user for file to decrypt
            string originalFile = null;

            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Title  = "Choose a file to put decrypted message";
            openFileDialog.Filter = "Decrypted message (*.crypto)|*.crypto|All files (*.*)|*.*";

            if (openFileDialog.ShowDialog() == true)
            {
                originalFile = openFileDialog.FileName;
            }

            // only open filestreams if files were selected by user
            FileStream   inputStream  = null;
            MemoryStream outputStream = null;

            if (originalFile != null)
            {
                try
                {
                    inputStream  = File.OpenRead(originalFile);
                    outputStream = new MemoryStream();

                    bool succeeded = await HybridEncryption.DecryptFile(inputStream, outputStream, AsymmetricEncryption.PublicKeyFromXml(PublicRSAKeyReceiver.Text));

                    if (succeeded)
                    {
                        StatusImage.Visibility = Visibility.Visible;
                        StatusImage.Source     = new BitmapImage(new Uri(@"/Images/checkmark.png", UriKind.Relative));

                        outputStream.Position = 0;
                        byte[] messageBuffer = new byte[outputStream.Length];
                        outputStream.Read(messageBuffer, 0, messageBuffer.Length);
                        string message = Encoding.UTF8.GetString(messageBuffer);
                        MessageBox.Show(message);
                    }
                    else
                    {
                        StatusImage.Visibility = Visibility.Visible;
                        StatusImage.Source     = new BitmapImage(new Uri(@"/Images/redx.png", UriKind.Relative));
                    }
                }
                catch (IOException exception)
                {
                    ErrorTextBlock.Visibility = Visibility.Visible;
                    ErrorTextBlock.Text       = exception.Message;
                }
                finally
                {
                    inputStream?.Close();
                    outputStream?.Close();
                }
            }
        }