/// <summary>
 /// Decrypts the specified key.
 /// </summary>
 /// <param name="key">The key.</param>
 /// <param name="IV">The iv.</param>
 /// <param name="data">The data.</param>
 /// <param name="cm">The cm.</param>
 /// <param name="symName">Name of the sym.</param>
 /// <returns></returns>
 public static byte[] Decrypt(byte[] key, byte[] IV, byte[] data, CipherMode cm, string symName)
 {
     using (var sa = CryptoServices.CreateSymmetricAlgorithm(symName))
     {
         return(Decrypt(key, IV, data, cm, sa));
     }
 }
        /// <summary>
        /// Encrypts the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="data">The data.</param>
        /// <param name="cm">The cm.</param>
        /// <param name="symName">Name of the sym.</param>
        /// <param name="hashName">Name of the hash.</param>
        /// <returns></returns>
        public static byte[] Encrypt(byte[] key, byte[] data, CipherMode cm, string symName, string hashName)
        {
            var bSize         = BitConverter.GetBytes(data.Length);
            var dataToEncrypt = new byte[data.Length + bSize.Length];

            Array.Copy(bSize, 0, dataToEncrypt, 0, bSize.Length);
            Array.Copy(data, 0, dataToEncrypt, bSize.Length, data.Length);

            using (var sa = CryptoServices.CreateSymmetricAlgorithm(symName))
            {
                try
                {
                    using (var ha = CryptoServices.CreateHashAlgorithm(hashName))
                    {
                        try
                        {
                            var IV    = sa.IV;
                            var rKey  = CryptoServices.InsureVector(ha.ComputeHash(key), sa.Key.Length, ha);
                            var rIV   = CryptoServices.InsureVector(ha.ComputeHash(IV), sa.IV.Length, ha);
                            var eData = Encrypt(rKey, rIV, dataToEncrypt, cm, sa);
                            var rData = new byte[IV.Length + eData.Length];

                            Array.Copy(IV, 0, rData, 0, IV.Length);
                            Array.Copy(eData, 0, rData, IV.Length, eData.Length);

                            return(rData);
                        }
                        finally
                        {
                            ha.Clear();
                        }
                    }
                }
                finally
                {
                    sa.Clear();
                }
            }
        }
        /// <summary>
        /// Decrypts the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="data">The data.</param>
        /// <param name="cm">The cm.</param>
        /// <param name="symName">Name of the sym.</param>
        /// <param name="hashName">Name of the hash.</param>
        /// <returns></returns>
        public static byte[] Decrypt(byte[] key, byte[] data, CipherMode cm, string symName, string hashName)
        {
            using (var sa = CryptoServices.CreateSymmetricAlgorithm(symName))
            {
                try
                {
                    using (var ha = CryptoServices.CreateHashAlgorithm(hashName))
                    {
                        try
                        {
                            var IV    = new byte[sa.IV.Length];
                            var eData = new byte[data.Length - IV.Length];

                            Array.Copy(data, 0, IV, 0, IV.Length);
                            Array.Copy(data, IV.Length, eData, 0, eData.Length);

                            var rKey = CryptoServices.InsureVector(ha.ComputeHash(key), sa.Key.Length, ha);
                            var rIV  = CryptoServices.InsureVector(ha.ComputeHash(IV), sa.IV.Length, ha);

                            var tmpDecryptData = Decrypt(rKey, rIV, eData, cm, sa);
                            var rData          = new byte[BitConverter.ToInt32(tmpDecryptData, 0)];
                            Array.Copy(tmpDecryptData, Marshal.SizeOf(rData.Length), rData, 0, rData.Length);

                            return(rData);
                        }
                        finally
                        {
                            ha.Clear();
                        }
                    }
                }
                finally
                {
                    sa.Clear();
                }
            }
        }