/// <summary>
        /// This function takes a IV and turn it into the legal block size for a given algorithm. It pads the string
        /// with spaces if it is shorter or truncate if it is longer.
        /// </summary>
        public static byte[] MakeLegalInitializationVector(SymmetricAlgorithmTypeEnum provider, string iv)
        {
            SymmetricAlgorithm alg = CreateSymmetricAlgorithmProvider(provider);

            string ret;

            if (alg.LegalBlockSizes.Length > 0)
            {
                int blockSize = iv.Length * 8;
                if (blockSize < alg.LegalBlockSizes[0].MinSize)
                {
                    int pad = (alg.LegalBlockSizes[0].MinSize - blockSize) / 8;
                    ret = iv.PadRight(pad + iv.Length, ' ');
                }
                else if (blockSize > alg.LegalBlockSizes[0].MaxSize)
                {
                    int len = alg.LegalBlockSizes[0].MaxSize / 8;
                    ret = iv.Substring(0, len);
                }
                else
                {
                    ret = iv;
                }
            }
            else
            {
                ret = iv;
            }

            return(ASCIIEncoding.ASCII.GetBytes(ret));
        }
        /// <summary>
        /// This function takes a key and turn it into the legal key size for a given algorithm. It pads the string
        /// with spaces if it is shorter or truncate if it is longer.
        /// </summary>
        public static string MakeKeyLegalSize(SymmetricAlgorithmTypeEnum provider, string secretKey)
        {
            SymmetricAlgorithm alg = CreateSymmetricAlgorithmProvider(provider);

            string ret;

            if (alg.LegalKeySizes.Length > 0)
            {
                int keySize = secretKey.Length * 8;
                if (keySize < alg.LegalKeySizes[0].MinSize)
                {
                    int pad = (alg.LegalKeySizes[0].MinSize - keySize) / 8;
                    ret = secretKey.PadRight(pad + secretKey.Length, ' ');
                }
                else if (keySize > alg.LegalKeySizes[0].MaxSize)
                {
                    int len = alg.LegalKeySizes[0].MaxSize / 8;
                    ret = secretKey.Substring(0, len);
                }
                else
                {
                    ret = secretKey;
                }
            }
            else
            {
                ret = secretKey;
            }

            return(ret);
        }
 /// <summary>
 /// Encrypts the data and encode using Base-64. Base-64 is useful when the string will be in transit through
 /// systems that are designed to deal with textual data.
 /// </summary>
 public static string EncryptToBase64(SymmetricAlgorithmTypeEnum provider, string plainText,
                                      string secretKey, byte[] bufInitVector, Encoding encoding)
 {
     byte[] bufEncryptedData = EncryptData(provider,
                                           encoding.GetBytes(plainText),
                                           encoding.GetBytes(secretKey), bufInitVector);
     return(Convert.ToBase64String(bufEncryptedData));
 }
        /// <summary>
        /// Decrypts the data using the provider, key and IV.
        /// </summary>
        public static byte[] DecryptData(SymmetricAlgorithmTypeEnum provider, byte[] bufEncryptedData, byte[] bufKey,
                                         byte[] bufInitVector)
        {
            SymmetricAlgorithm alg = CreateSymmetricAlgorithmProvider(provider);

            alg.Key = bufKey;
            alg.IV  = bufInitVector;
            return(DecryptData(alg, bufEncryptedData));
        }
        /// <summary>
        /// Decrypt the give Base 64 cypher string .
        /// </summary>
        public static string DecryptFromBase64(SymmetricAlgorithmTypeEnum provider, string cypherStringBase64,
                                               string secretKey, byte[] bufInitVector, Encoding encoding)
        {
            byte[] bufKey           = encoding.GetBytes(secretKey);
            byte[] bufEncryptedData = Convert.FromBase64String(cypherStringBase64);
            byte[] bufData          = DecryptData(provider, bufEncryptedData, bufKey, bufInitVector);
            string plainText        = encoding.GetString(bufData);

            //?? return plainText.Substring(0, plainText.IndexOf('\0'));
            return(plainText);
        }
        /// <summary>
        /// Decrypt the data using the given key and passed IV
        /// </summary>
        public static string DecryptData(SymmetricCipherResults cipherResults,
                                         SymmetricAlgorithmTypeEnum symmetricAlgorithm,
                                         string key)
        {
            key = SymmetricOperation.MakeKeyLegalSize(symmetricAlgorithm, key);

            byte[] IV = Convert.FromBase64String(cipherResults.IV);

            string PlainText = SymmetricOperation.DecryptFromBase64(symmetricAlgorithm,
                                                                    cipherResults.CipherText, key, IV, System.Text.Encoding.UTF8);

            return(PlainText);
        }
        /// <summary>
        /// Encrypt the data using the symmetric algorithm provided and key. Generates the Initialization Vector.
        /// Returns the IV and the encrypted string
        /// </summary>
        public static SymmetricCipherResults EncryptData(string plainText,
                                                         SymmetricAlgorithmTypeEnum symmetricAlgorithm,
                                                         string key)
        {
            SymmetricAlgorithm algorithm = SymmetricOperation.CreateSymmetricAlgorithmProvider(symmetricAlgorithm);

            key = SymmetricOperation.MakeKeyLegalSize(symmetricAlgorithm, key);
            algorithm.GenerateIV();
            string iv = Convert.ToBase64String(algorithm.IV);

            string cipherText = SymmetricOperation.EncryptToBase64(symmetricAlgorithm,
                                                                   plainText, key, algorithm.IV, System.Text.Encoding.UTF8);

            return(new SymmetricCipherResults()
            {
                CipherText = cipherText, IV = iv
            });
        }
        /// <summary>
        /// Creates a algorithm specific .NET implementation of the symmetric algorithm provider.
        /// </summary>
        public static SymmetricAlgorithm CreateSymmetricAlgorithmProvider(SymmetricAlgorithmTypeEnum provider)
        {
            switch (provider)
            {
            case SymmetricAlgorithmTypeEnum.DES:
                return(new DESCryptoServiceProvider());

            case SymmetricAlgorithmTypeEnum.RC2:
                return(new RC2CryptoServiceProvider());

            case SymmetricAlgorithmTypeEnum.Rijndael:
                return(new RijndaelManaged());

            case SymmetricAlgorithmTypeEnum.TripleDES:
                return(new TripleDESCryptoServiceProvider());

            default:
                return(new TripleDESCryptoServiceProvider());
            }
        }