private async void EncryptMessageButton_Click(object sender, RoutedEventArgs e)
        {
            StatusImage.Visibility    = Visibility.Hidden;
            ErrorTextBlock.Visibility = Visibility.Hidden;

            if (UserInputRSADetails())
            {
                return;
            }

            // ask user for location to save encrypted message
            string encryptedFile = null;

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title  = "Save as";
            saveFileDialog.Filter = "Encrypted message (*.crypto)|*.crypto";

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

            // only open filestreams if files were selected by user
            if (encryptedFile != null)
            {
                // open streams
                MemoryStream inputStream  = new MemoryStream();
                byte[]       messageBytes = Encoding.UTF8.GetBytes(InputMessageBox.Text);
                inputStream.Write(messageBytes, 0, messageBytes.Length);

                // message requires a minimum length, pad it with 32 0x00 bytes
                if (inputStream.Length < 32)
                {
                    inputStream.Write(new byte[32], 0, 32);
                }

                inputStream.Position = inputStream.Seek(0, SeekOrigin.Begin);
                FileStream outputStream = null;

                try
                {
                    outputStream = File.OpenWrite(encryptedFile);

                    await HybridEncryption.EncryptFile(inputStream, outputStream, AsymmetricEncryption.PublicKeyFromXml(PublicRSAKeyReceiver.Text));

                    MessageBox.Show("Done");
                }
                catch (IOException exception)
                {
                    ErrorTextBlock.Visibility = Visibility.Visible;
                    ErrorTextBlock.Text       = exception.Message;
                }
                finally
                {
                    inputStream?.Close();
                    outputStream?.Close();
                }
            }
        }
예제 #2
0
        public void Can_Convert_XML_String_To_Public_Key()
        {
            string xml = AsymmetricEncryption.PublicKeyAsXml();

            RSAParameters rsaParameters = AsymmetricEncryption.PublicKeyFromXml(xml);

            Assert.NotNull(rsaParameters);
            CollectionAssert.AreEqual(publicKey.Exponent, rsaParameters.Exponent);
            CollectionAssert.AreEqual(publicKey.Modulus, rsaParameters.Modulus);
        }
        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 EncryptFileStenographyButton_Click(object sender, RoutedEventArgs e)
        {
            ErrorTextBlock.Visibility = Visibility.Hidden;

            FileStream   baseFile      = null;
            FileStream   saveFile      = null;
            MemoryStream messageData   = null;
            MemoryStream encryptedData = null;

            try
            {
                // put original message into a memory stream
                byte[] messageBytes = Encoding.UTF8.GetBytes(InputMessageBox.Text);
                messageData = new MemoryStream();
                messageData.Write(messageBytes, 0, messageBytes.Length);
                if (messageData.Length < 32) // make sure it's longer than the minimum length
                {
                    messageData.Write(new byte[32], 0, 32);
                }
                messageData.Position = 0;

                // select file to use as base
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Title = "Choose a file to put encrypted message";

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

                // select file to save
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Title        = "Save as";
                saveFileDialog.DefaultExt   = openFileDialog.SafeFileName.Split('.').Last();
                saveFileDialog.AddExtension = true;

                if (saveFileDialog.ShowDialog() == true)
                {
                    saveFile = new FileStream(saveFileDialog.FileName, FileMode.Create, FileAccess.Write);
                }
                else
                {
                    return;
                }

                // encrypt message into memory stream
                encryptedData = new MemoryStream();
                await HybridEncryption.EncryptFile(messageData, encryptedData, AsymmetricEncryption.PublicKeyFromXml(PublicRSAKeyReceiver.Text)).ConfigureAwait(false);

                encryptedData.Position = 0;

                // write length to output
                byte[] baseFileBuffer = new byte[8];

                byte[] length = BitConverter.GetBytes(encryptedData.Length);
                for (int i = 0; i < 8; i++)
                {
                    await baseFile.ReadAsync(baseFileBuffer, 0, 8); // read 8 bytes of input

                    HideInBytes(baseFileBuffer, length[i]);
                    await saveFile.WriteAsync(baseFileBuffer, 0, 8); // write 8 bytes to output
                }

                // hide message in output
                byte[] encryptedDataBuffer = new byte[1];
                for (int i = 0; i < encryptedData.Length; i++)
                {
                    await encryptedData.ReadAsync(encryptedDataBuffer, 0, 1);

                    await baseFile.ReadAsync(baseFileBuffer, 0, 8); // read 8 bytes of input

                    HideInBytes(baseFileBuffer, encryptedDataBuffer[0]);
                    await saveFile.WriteAsync(baseFileBuffer, 0, 8); // write 8 bytes to output
                }

                // write rest of file to output
                byte[] fileBuffer = new byte[1024];
                while (await baseFile.ReadAsync(fileBuffer, 0, 1024) > 0)
                {
                    await saveFile.WriteAsync(fileBuffer, 0, 1024);
                }

                await saveFile.FlushAsync().ConfigureAwait(false);
            }
            catch (IOException exception)
            {
                ErrorTextBlock.Text       = exception.Message;
                ErrorTextBlock.Visibility = Visibility.Visible;
            }
            catch (CryptoException exception)
            {
                ErrorTextBlock.Text       = exception.Message;
                ErrorTextBlock.Visibility = Visibility.Visible;
            }
            finally
            {
                baseFile?.Close();
                saveFile?.Close();
                messageData?.Close();
                encryptedData?.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();
                }
            }
        }
        private async void EncryptButton_Click(object sender, RoutedEventArgs e)
        {
            ErrorTextBlock.Visibility = Visibility.Hidden;
            StatusImage.Visibility    = Visibility.Hidden;

            if (UserInputRSADetails())
            {
                return;
            }

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

            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Title = "Choose a file to encrypt";

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

            // ask user for location to save encrypted file
            string encryptedFile = null;

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title  = "Save as";
            saveFileDialog.Filter = "Encrypted file (*.crypto)|*.crypto"; // TODO: verzin betere file extensie

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

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

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

                    await HybridEncryption.EncryptFile(inputStream, outputStream, AsymmetricEncryption.PublicKeyFromXml(PublicRSAKeyReceiver.Text));

                    MessageBox.Show("Done"); // TODO: tell user their encryption is done
                }
                catch (IOException exception)
                {
                    ErrorTextBlock.Visibility = Visibility.Visible;
                    ErrorTextBlock.Text       = exception.Message;
                }
                finally
                {
                    inputStream?.Close();
                    outputStream?.Close();
                }
            }
        }
        /// <summary>
        /// Add received messages from list of packets
        /// </summary>
        /// <param name="received"></param>
        /// <returns>Amount of packages which failed to be decrypted</returns>
        private async Task <int> AddReceivedMessages(IList <StrippedDownEncryptedPacket> received)
        {
            // try to link messages to contacts
            BoxedInt    boxedInt = new BoxedInt();
            List <Task> tasks    = new List <Task>(received.Count);

            foreach (StrippedDownEncryptedPacket packet in received)
            {
                // find sender in contact list
                tasks.Add(Task.Run(() =>
                {
                    ContactPerson sender = contactList.FirstOrDefault(c => c.Id == packet.Sender.Id);
                    if (sender != null)
                    {
                        // ignore duplicates
                        if (sender.Messages.All(m => m.SendTime != packet.SendDateTime))
                        {
                            if (packet.DataType == DataType.Message)
                            {
                                try
                                {
                                    string message = Encoding.UTF8.GetString(HybridEncryption.Decrypt(packet.EncryptedPacket, AsymmetricEncryption.PublicKeyFromXml(sender.PublicKey)));

                                    // add new message to chat
                                    lock (sender.LockObject)
                                    {
                                        sender.Messages.Add(new Message
                                        {
                                            SenderName        = sender.UserName,
                                            SendTime          = packet.SendDateTime,
                                            MessageFromSender = message,
                                            DataType          = packet.DataType,
                                            Packet            = packet,
                                            Sender            = sender
                                        });
                                    }
                                }
                                catch (CryptoException)
                                {
                                    lock (boxedInt)
                                    {
                                        boxedInt.Integer++;
                                    }
                                }
                            }
                            else
                            {
                                lock (sender.LockObject)
                                {
                                    sender.Messages.Add(new Message
                                    {
                                        SenderName        = sender.UserName,
                                        SendTime          = packet.SendDateTime,
                                        MessageFromSender = $"This is a {packet.DataType}",
                                        DataType          = packet.DataType,
                                        Packet            = packet,
                                        Sender            = sender
                                    });
                                }
                            }
                        }
                    }
                }));
            }

            await Task.WhenAll(tasks);

            return(boxedInt.Integer);
        }
        /// <summary>
        /// Send a file to currently selected user
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void SendAttachmentButton_Click(object sender, RoutedEventArgs e)
        {
            // get currently selected contact, do nothing if none is selected
            ContactPerson contact = (ContactPerson)ContactListListView.SelectedItem;

            if (contact == null)
            {
                return;
            }

            // ask user to select file
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Title       = "Choose a file to encrypt";
            openFileDialog.Multiselect = false;

            if (openFileDialog.ShowDialog() == true)
            {
                FileStream fileStream;
                FileInfo   fileInfo;

                try
                {
                    fileInfo = new FileInfo(openFileDialog.FileName);

                    if (fileInfo.Length > 10_000_000) // only upload files smaller than 10MB
                    {
                        ErrorText = "Due to server limitations, files bigger than 10MB (10 000 000 bytes) are not supported.";
                        return;
                    }

                    fileStream = new FileStream(openFileDialog.FileName, FileMode.Open, FileAccess.Read);

                    // encrypt file for receiver
                    EncryptedPacket packetForReceiver = null;
                    await Task.Run(() =>
                    {
                        try
                        {
                            packetForReceiver = HybridEncryption.EncryptFile(fileStream, AsymmetricEncryption.PublicKeyFromXml(contact.PublicKey));
                        }
                        catch (CryptoException exception)
                        {
                            // show to user
                            ErrorText = exception.Message;
                        }
                    });

                    // send to receiver
                    await Client.SendNewMessage(packetForReceiver, contact.Id);
                }
                catch (IOException exception)
                {
                    // show to user
                    ErrorText = exception.Message;
                }
                catch (ClientException exception)
                {
                    // show to user
                    ErrorText = exception.Message;
                }
            }
        }
        /// <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();
                }
            }
        }
        /// <summary>
        /// Send a new message
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void SendButton_Click(object sender, RoutedEventArgs e)
        {
            ContactPerson contact = (ContactPerson)ContactListListView.SelectedItem;

            if (contact == null)
            {
                return;
            }

            EncryptedPacket packetForReceiver = null, packetForSender = null;
            string          text = MessageTextBox.Text;
            await Task.Run(() =>
            {
                try
                {
                    packetForReceiver = HybridEncryption.Encrypt(DataType.Message, Encoding.UTF8.GetBytes(text), AsymmetricEncryption.PublicKeyFromXml(contact.PublicKey));
                    packetForSender   = HybridEncryption.Encrypt(DataType.Message, Encoding.UTF8.GetBytes(text), AsymmetricEncryption.PublicKey);
                }
                catch (CryptoException exception)
                {
                    ErrorText = exception.Message;
                }
            });

            // try to send message and clear input
            if (packetForReceiver != null && packetForSender != null)
            {
                try
                {
                    // send to server
                    await Client.SendNewMessage(packetForReceiver, contact.Id, true);

                    await Client.SendNewMessage(packetForSender, contact.Id, false);

                    // add to chat
                    contact.Messages.Add(new Message
                    {
                        SenderName        = Client.UserName,
                        SendTime          = DateTime.Now,
                        MessageFromSender = MessageTextBox.Text,
                        DataType          = DataType.Message
                    });
                    MessageTextBox.Clear();
                }
                catch (ClientException exception)
                {
                    // show message to user
                    ErrorText = exception.Message;
                }
            }
        }