// -------------------------------------------------------------------------------

        /// <summary>
        /// Encrypts and compress the plaintext. (with signature)
        /// </summary>
        /// <param name="plaintext">The plaintext to be encrypted.</param>
        /// <param name="compressStreamWriter">A StreamWriter for the compressing the stream</param>
        /// <returns>The encrypted plaintext (-> ciphertext).</returns>
        public byte[] Encrypt(byte[] plaintext, CompressStreamWriterDelegate compressStreamWriter)
        {
            byte[] ret;

            try
            {
                ret = SignedEncrypt(plaintext, compressStreamWriter);
            }
            catch (Exception ex)
            {
                throw new Exception("Error within OlympCryptography.Encrypt, see inner exception.", ex);
            }

            return(ret);
        }
        // -------------------------------------------------------------------------------
        /// <summary>
        /// SignedEncrypts the plaintext.
        /// </summary>
        /// <param name="plaintext">The plaintext to be encrypted.</param>
        /// <param name="compressStreamWriter">A StreamWriter for the compressing the stream</param>
        /// <returns>The encrypted plaintext (-> ciphertext).</returns>
        private byte[] SignedEncrypt(byte[] plaintext, CompressStreamWriterDelegate compressStreamWriter)
        {
            byte[] ciphertext = null;

            MemoryStream memoryStream = new MemoryStream();
            byte[] IV = new byte[16];

            //Creates the default implementation, which is RijndaelManaged.
            SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();

            //RNGCryptoServiceProvider is an implementation of a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            // The array is now filled with cryptographically strong random bytes, and none are zero.
            rng.GetNonZeroBytes(IV);

            // creates a symmetric encryptor object with the specified Key and initialization vector (IV).
            ICryptoTransform encryptor = rijn.CreateEncryptor(this.key, IV);

            // write the unencrypted initialization vector
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, IV);

            // write the digital signature and the DSA parameters
            SHA1 sha1Provider = new SHA1CryptoServiceProvider();
            DSACryptoServiceProvider dsaProvider = new DSACryptoServiceProvider();
            byte[] hashbytes = sha1Provider.ComputeHash(plaintext);
            byte[] signature = dsaProvider.SignHash(hashbytes, CryptoConfig.MapNameToOID(SHA1));
            formatter.Serialize(memoryStream, signature);

            // very important !!!!
            // only the public key is serialized -> false as argument to ExportParameters.
            formatter.Serialize(memoryStream, dsaProvider.ExportParameters(false));

            if (compressStreamWriter != null)
            {
                // write plaintext into compressed and encrypted stream
                MemoryStream compressedStream = new MemoryStream();
                using (Stream sw = compressStreamWriter(compressedStream))
                {
                    sw.Write(plaintext, 0, plaintext.Length);
                    sw.Flush();
                    sw.Close();
                }

                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(compressedStream.ToArray(), 0, compressedStream.ToArray().Length);
                    cryptoStream.Flush();
                    cryptoStream.Close();
                }
            }
            else
            {
                // write plaintext into encrypted stream
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plaintext, 0, plaintext.Length);
                    cryptoStream.Flush();
                    cryptoStream.Close();
                }
            }

            ciphertext = memoryStream.ToArray();

            return ciphertext;
        }
        // -------------------------------------------------------------------------------
        /// <summary>
        /// Encrypts and compress the plaintext. (with signature)
        /// </summary>
        /// <param name="plaintext">The plaintext to be encrypted.</param>
        /// <param name="compressStreamWriter">A StreamWriter for the compressing the stream</param>
        /// <returns>The encrypted plaintext (-> ciphertext).</returns>
        public byte[] Encrypt(byte[] plaintext, CompressStreamWriterDelegate compressStreamWriter)
        {
            byte[] ret;

            try
            {
                ret = SignedEncrypt(plaintext, compressStreamWriter);
            }
            catch (Exception ex)
            {
                throw new Exception("Error within OlympCryptography.Encrypt, see inner exception.", ex);
            }

            return ret;
        }
        // -------------------------------------------------------------------------------

        /// <summary>
        /// SignedEncrypts the plaintext.
        /// </summary>
        /// <param name="plaintext">The plaintext to be encrypted.</param>
        /// <param name="compressStreamWriter">A StreamWriter for the compressing the stream</param>
        /// <returns>The encrypted plaintext (-> ciphertext).</returns>
        private byte[] SignedEncrypt(byte[] plaintext, CompressStreamWriterDelegate compressStreamWriter)
        {
            byte[] ciphertext = null;

            MemoryStream memoryStream = new MemoryStream();

            byte[] IV = new byte[16];

            //Creates the default implementation, which is RijndaelManaged.
            SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();

            //RNGCryptoServiceProvider is an implementation of a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            // The array is now filled with cryptographically strong random bytes, and none are zero.
            rng.GetNonZeroBytes(IV);

            // creates a symmetric encryptor object with the specified Key and initialization vector (IV).
            ICryptoTransform encryptor = rijn.CreateEncryptor(this.key, IV);

            // write the unencrypted initialization vector
            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(memoryStream, IV);

            // write the digital signature and the DSA parameters
            SHA1 sha1Provider = new SHA1CryptoServiceProvider();
            DSACryptoServiceProvider dsaProvider = new DSACryptoServiceProvider();

            byte[] hashbytes = sha1Provider.ComputeHash(plaintext);
            byte[] signature = dsaProvider.SignHash(hashbytes, CryptoConfig.MapNameToOID(SHA1));
            formatter.Serialize(memoryStream, signature);

            // very important !!!!
            // only the public key is serialized -> false as argument to ExportParameters.
            formatter.Serialize(memoryStream, dsaProvider.ExportParameters(false));

            if (compressStreamWriter != null)
            {
                // write plaintext into compressed and encrypted stream
                MemoryStream compressedStream = new MemoryStream();
                using (Stream sw = compressStreamWriter(compressedStream))
                {
                    sw.Write(plaintext, 0, plaintext.Length);
                    sw.Flush();
                    sw.Close();
                }

                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(compressedStream.ToArray(), 0, compressedStream.ToArray().Length);
                    cryptoStream.Flush();
                    cryptoStream.Close();
                }
            }
            else
            {
                // write plaintext into encrypted stream
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plaintext, 0, plaintext.Length);
                    cryptoStream.Flush();
                    cryptoStream.Close();
                }
            }

            ciphertext = memoryStream.ToArray();

            return(ciphertext);
        }