/// <summary>
        /// Waits for a new packet from the remote client.
        /// </summary>
        /// <returns>The data</returns>
        /// <exception cref="IOException">If anything went wrong with the I/O</exception>
        public byte[] ReceivePacket()
        {
            try
            {
                // Receives the length of the packet
                int len = this.ReadByte() | (this.ReadByte() << 8);

                // Reserves the space to store the data
                byte[] back = new byte[len];

                // Waits for the data
                for (int i = 0; i < len; i++)
                {
                    back[i] = this.ReadByte();
                }

                // Decrypts the data
                byte[] dec = SimpleSecurityUtils.DecryptAES(back, this.aesKey, this.aesIv);

                // Checks if the decryption failed
                if (dec == null)
                {
                    throw new Exception("Data-decryption failed.");
                }

                this.log
                .Debug("Checking nonce")
                .Critical($"Received bytes=[{string.Join(",",dec)}}}");

                // Checks if the dec has at least enough bytes for the nonce bytes
                if (dec.Length < this.nonceBytes.Length)
                {
                    throw new IOException("No nonce provided.");
                }

                // Check if the bytes of the nonce match
                for (int i = 0; i < this.nonceBytes.Length; i++)
                {
                    if (this.nonceBytes[i] != dec[i])
                    {
                        throw new IOException("Nonce does not match.");
                    }
                }

                this.log
                .Debug("Nonce is correct.");

                // Creates a copy of the packet without the nonce
                byte[] finPkt = new byte[dec.Length - this.nonceBytes.Length];
                // Copies the bytes of the actual packet
                Array.Copy(dec, this.nonceBytes.Length, finPkt, 0, finPkt.Length);

                return(finPkt);
            }
            catch (Exception e)
            {
                // Converts any exception to an i/o-exception
                throw new IOException(e.Message);
            }
        }
        /// <summary>
        /// Encryptes the given data and sends it as a packet to the receiver
        /// </summary>
        /// <param name="data">The raw bytes that shall be send</param>
        /// <exception cref="IOException">If anything went wrong with the I/O</exception>
        public void SendPacket(params byte[] data)
        {
            try
            {
                // Encryptes the data using the received key
                byte[] encrypted = SimpleSecurityUtils.EncryptAES(data, this.aesKey, this.aesIv);

                // Checks if anything failed with the encryption
                if (encrypted == null)
                {
                    throw new Exception("Encryption failed");
                }

                // Sends the length of the packet
                this.stream.WriteByte((byte)encrypted.Length);
                this.stream.WriteByte((byte)(encrypted.Length >> 8));

                // Sends the actual encrypted data
                this.stream.Write(encrypted, 0, encrypted.Length);
                this.stream.Flush();
            }
            catch (Exception e)
            {
                // Converts any exception to an i/o-exception
                throw new IOException(e.Message);
            }
        }
        /// <summary>
        /// Saves the config file encrypted using the passed key
        /// </summary>
        /// <param name="filePath">The path to the file where to save the configuration</param>
        /// <param name="key">The key for encrypting the file</param>
        /// <exception cref="ConfigException">Something went wrong while encryption (Unknown)</exception>
        /// <exception cref="Exception">All exception that can be passed on by File.WriteAllBytes called with the filePath</exception>
        public void SaveConfig(string filePath, string key)
        {
            // Generates the object that will be saved as the config file
            JObject json = new JObject()
            {
                ["port"] = this.Port,
                ["host"] = this.Host,
                ["rsa"]  = SimpleSecurityUtils.SaveRSAToJson(this.PrivateKey)
            };

            // Generates the actual key and iv from the previous plain text key
            byte[] aesKey = SimpleSecurityUtils.HashSHA256(Encoding.UTF8.GetBytes(key));
            byte[] aesIv  = SimpleSecurityUtils.HashMD5(Encoding.UTF8.GetBytes(key));

            // Encryptes the config-json object
            byte[] encData = SimpleSecurityUtils.EncryptAES(Encoding.UTF8.GetBytes(json.ToString()), aesKey, aesIv);

            // Checks if the encryption failed
            if (encData == null)
            {
                // Unknown exception
                throw new ConfigException();
            }

            // Writes all data to the file
            File.WriteAllBytes(filePath, encData);
        }
        public ConfigWindow(Config cfg, string password)
        {
            InitializeComponent();
            this.cfg      = cfg;
            this.password = password;

            // Sets the values
            this.FieldPort.Text = cfg.Port.ToString();
            this.FieldHost.Text = cfg.Host;
            this.FieldRSA.Text  = SimpleSecurityUtils.SaveRSAToJson(cfg.PrivateKey).ToString(Formatting.None);

            // Disables the save button
            this.buttonSave.IsEnabled = false;
        }
        private void OnButtonSaveClicked(object _, RoutedEventArgs _2)
        {
            // Checks if the port couldn't be passed
            if (!int.TryParse(this.FieldPort.Text, out int port))
            {
                this.ShowError(Lang.config_save_port);
                return;
            }
            this.cfg.Port = port;

            try
            {
                // Tries to load the private key
                this.cfg.PrivateKey = SimpleSecurityUtils.LoadRSAFromJson(JObject.Parse(this.FieldRSA.Text));
            }
            catch
            {
                this.ShowError(Lang.config_save_key);
                return;
            }

            // Sets the host
            this.cfg.Host = this.FieldHost.Text;

            try
            {
                // Tries to save the config
                this.cfg.SaveConfig(PLCA.CONFIG_PATH, this.password);

                // Updates the main config
                PLCA.LOADED_CONFIG = this.cfg;

                // Closes the window
                this.Close();
            }
            catch (Exception ex)
            {
                // Shows the error
                this.ShowError(Lang.config_save_unknown, ex.Message);
            }
        }
        /// <summary>
        /// Loads the given config-file, decryptes it using the passed key and loads it as a config object
        /// </summary>
        /// <param name="filePath">The path to the configuration file.</param>
        /// <param name="key">The key to decrypt those bytes</param>
        /// <returns>The fully loaded config</returns>
        /// <exception cref="ConfigInvalidKeyException">If the given key couldn't decrypt the config</exception>
        /// <exception cref="ConfigCurruptedException">If the config seems to be currupted</exception>
        /// <exception cref="Exception">All exception that can be passed by File.ReadAllBytes using the filepath.</exception>
        public static Config LoadConfig(string filePath, string key)
        {
            // Reads the content of the passed config file
            byte[] rawData = File.ReadAllBytes(filePath);

            // Generates the actual key and iv from the previous plain text key
            byte[] aesKey = SimpleSecurityUtils.HashSHA256(Encoding.UTF8.GetBytes(key));
            byte[] aesIv  = SimpleSecurityUtils.HashMD5(Encoding.UTF8.GetBytes(key));

            // Tries to decrypt the config
            byte[] decrypted = SimpleSecurityUtils.DecryptAES(rawData, aesKey, aesIv);

            // Checks if the decryption failed
            if (decrypted == null)
            {
                throw new ConfigInvalidKeyException();
            }

            try
            {
                // The config that will be created
                Config cfg = new Config();

                // Tries to parse the config from json
                JObject json = JObject.Parse(Encoding.UTF8.GetString(decrypted));

                // Gets all values
                cfg.Port       = (int)json["port"];
                cfg.Host       = (string)json["host"] ?? string.Empty;
                cfg.PrivateKey = SimpleSecurityUtils.LoadRSAFromJson((JObject)json["rsa"]);

                // Returns the fully loaded config
                return(cfg);
            }
            catch
            {
                throw new ConfigCurruptedException(Encoding.UTF8.GetString(decrypted));
            }
        }