using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.IO;
//using System.Windows.Forms;
using System.Collections.ObjectModel;

namespace CrossProduct.Core
{
    /// <summary>
    /// Text Encryption Types that are Supported by the PerSeCryptography class.
    /// </summary>
    internal enum PerSeTextEncryptionTypes
    {
        Code,
        Filename,
        Text
    }

    /// <summary>
    /// The PerSeCryptography class contains functionality to perform
    /// custom PerSe cryptography routines
    /// </summary>    
    public class PerSeCryptography
    {
        #region Member Variables
        private const string KeyEncryptionString = "7:i#t~<Tm*I{cC1-+AygowsP}Zeb,WRp5^k?>QzV_BMF4u3!" +
                                                  "XH;/)=(8dhEUnD.OJ6%0@G2&rNfqSv\\ja[LxYK$]l9";
        private const string ValidCodeCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private const string ValidFilenameCharacters = "!#$%&'()-0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
                                                    "^_`{}~ƒ¡¢£¥ª°±²µ·º»¼½¿ÄÅÆÇÉÑÖÜß÷";
        private const string ValidTextCharacters = "!#$%&()-0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
                                                   "^_`{}~ƒ¡¢£¥ª°±²µ·º»¼½¿ÄÅÆÇÉÑÖÜß÷ ;:\",.*/\\<>?|+=";

        private const int KeyStringLength = 5;
        private const int MaxExtraEncryptionCharacters = 7;
        private const int SplitKeyIndex = 4;
        private const int InvalidStringCharacters = 50;
        private const int EncryptionKeyBitMask = 15;
        private const int EncryptionKeyShift = 4;
        private const int EncryptionKeyMaxUnchangedCount = 10;
        private const int EncryptionKeySkipKeys = 5;
        private const int EncryptionKeySeed = 32767;
        private const int RandomNumberBitMask = 65535;
        private const int RandomNumberMultiplier = 17405;
        private const int RandomNumberExtraValue = 196;
        private const float RandomNumberDivisor = 65536.0f;

        private int _currentRandomNumber;
        private Random _randomNumGen;
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="PerSeCryptography"/> class.
        /// </summary>
        /// Change Made On: 6/23/2009
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        public PerSeCryptography()
        {         
            _randomNumGen = new Random();
            _currentRandomNumber = _randomNumGen.Next() & RandomNumberBitMask;        
        }

        /// <summary>
        /// Decrypts a String with an Embedded Key
        /// </summary>
        /// <param name="encryptedText">encrypted text string to decrypt</param>
        /// <returns>the decrypted text string</returns>
        public string DecryptText(string encryptedText)
        {
            return Decrypt(encryptedText, PerSeTextEncryptionTypes.Text);
        }

        /// <summary>
        /// Decrypts a Text string using a key
        /// </summary>
        /// <param name="encryptedText">text string to decrypt</param>        
        /// <param name="key">key to use to decrypt the string</param>
        /// <returns>decrypted text</returns>
        public string DecryptText(string encryptedText, int key)
        {
            return Decrypt(encryptedText, key, PerSeTextEncryptionTypes.Text);
        }

        /// <summary>
        /// Encrypts a String to Binary
        /// </summary>
        /// <param name="decryptedText">text to encrypt</param>
        /// <returns>encrypted text</returns>
        public string EncryptBinaryString(string decryptedText)
        {
            try
            {
                return DataEncryption.EncryptString(decryptedText);
            }
            catch (Exception ex)
            {
                throw new Exception("Error Encrypting binary String", ex);
            }
        }

        /// <summary>
        /// Decrypts a text string from binary to text
        /// </summary>
        /// <param name="encryptedText">The encrypted text.</param>
        /// <returns>decrypted text</returns>
        public string DecryptBinaryString(string encryptedText)
        {
            try
            {
                return DataEncryption.DecryptString(encryptedText);
            }
            catch (Exception ex)
            {
                throw new Exception("Error Decrypting Binary String", ex);
            }
        }

        /// <summary>
        /// Encrypts a Text string using a key and industry standard encryption modes - Rijndael will be default which is the same as AES 256 bit encryption.
        /// </summary>
        /// <param name="text">text string to encrypt</param>        
        /// <param name="key">key to use to encrypt the string</param>
        /// <param name="encryptionMode">Mode of encryption of choice - "DES" or "RC2" or "Rijndael" or "TripleDES" - Default will be "Rijndael"</param>
        /// <returns>the text encrypted</returns>
        public string EncryptText(string text, string key, string encryptionMode)
        {
            byte[] encryptedData = Encrypt(text, key, encryptionMode);
            return Convert.ToBase64String(encryptedData);
        }

        /// <summary>
        /// Decrypts a Text string using a key and industry standard encryption modes - Rijndael will be default which is the same as AES 256 bit encryption.
        /// </summary>
        /// <param name="text">text string to decrypt</param>        
        /// <param name="key">key to use to decrypt the string</param>
        /// <param name="encryptionMode">Mode of encryption of choice - "DES" or "RC2" or "Rijndael" or "TripleDES" - Default will be "Rijndael"</param>
        /// <returns>decrypted text</returns>
        public string DecryptText(string text, string key, string encryptionMode)
        {
            string decryptedData = string.Empty;
            decryptedData = Decrypt(Convert.FromBase64String(text), key, encryptionMode);
            return decryptedData;
        }

        /// <summary>
        /// Encrypts Key Text
        /// </summary>
        /// <param name="text">key text</param>
        /// <param name="key">key to use when encrypting the key</param>
        /// <returns></returns>
        public string EncryptText(string text, int key)
        {
            return Encrypt(text, key, PerSeTextEncryptionTypes.Text);
        }

        /// <summary>
        /// Encrypts text
        /// </summary>
        /// <param name="text">Text to encrypt</param>
        /// <returns>the text encrypted</returns>
        public string EncryptText(string text)
        {
            string strEncryptValue;

            strEncryptValue = Encrypt(text, PerSeTextEncryptionTypes.Text);

            return strEncryptValue;

            //return Encrypt( text, PerSeTextEncryptionTypes.Text );
        }

        /// <summary>
        /// Encrypts text
        /// </summary>
        /// <param name="text">Text to encrypt</param>
        /// <returns>the text encrypted</returns>
        public string EncryptText(string text, bool EnsureUniqueKey, string assemblyname)
        {
            string strEncryptValue;

            strEncryptValue = Encrypt(text, PerSeTextEncryptionTypes.Text);

            if (EnsureUniqueKey && !String.IsNullOrEmpty(assemblyname))
                strEncryptValue = SimpleStringBinaryConverter.GetString(strEncryptValue, assemblyname);

            return strEncryptValue;

            //return Encrypt( text, PerSeTextEncryptionTypes.Text );
        }

        /// <summary>
        /// Encrypts the text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <returns></returns>
        /// Change Made On: 7/15/2010
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        public ReadOnlyCollection<String> EncryptText(ReadOnlyCollection<String> text)
        {
            List<string> result = new List<string>();
            foreach (string value in text)
            {
                result.Add(Encrypt(value, PerSeTextEncryptionTypes.Text));
            }
            ReadOnlyCollection<string> temp = new ReadOnlyCollection<string>(result);
            return temp;
        }

        /// <summary>
        /// Decrypts a Text string using an Embedded key
        /// </summary>
        /// <param name="encryptedText">encrypted text to decrypt</param>
        /// <param name="encryptionType"></param>
        /// <returns>decrypted text string</returns>
        private string Decrypt(string encryptedText, PerSeTextEncryptionTypes encryptionType)
        {
            try
            {
                StringBuilder decryptedText = new StringBuilder();
                int key = GetEmbeddedKey(encryptedText);
                int index = 0;

                if (key != -1)
                {
                    index = encryptedText.Length - (KeyStringLength - SplitKeyIndex) + 1;
                    if (index >= (SplitKeyIndex + 1))
                    {
                        string encryptedTextWithoutKey = encryptedText.Substring(SplitKeyIndex, (index - SplitKeyIndex - 1));
                        decryptedText.Append(Decrypt(encryptedTextWithoutKey, key, encryptionType));
                    }
                }
                else
                {
                    for (index = 0; index < InvalidStringCharacters; index++)
                    {
                        int charIndex = RandomNumber(ValidTextCharacters.Length);
                        decryptedText.Append(ValidTextCharacters[charIndex]);
                    }
                }

                return decryptedText.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("Error Decrypting string", ex);
            }
        }

        /// <summary>
        /// Decrypts a text string
        /// </summary>
        /// <param name="encryptedText">Encrypted Text to decrypt</param>
        /// <param name="key">key to use when decrypting the text</param>
        /// <param name="encryptionType">the type of text to decrypt</param>
        /// <returns>the encrypted string decrypted</returns>
        private string Decrypt(string encryptedText, int key, PerSeTextEncryptionTypes encryptionType)
        {
            try
            {
                string validCharacters;
                string encryptionCodeCharacters;
                int extraCharacerOdds;
                int extraCharacters;
                int realCharacters;
                int originalKey;

                encryptionCodeCharacters = GenerateEncryptionCode(key, encryptionType);

                originalKey = _currentRandomNumber;
                _currentRandomNumber = key;

                switch (encryptionType)
                {
                    case PerSeTextEncryptionTypes.Code:
                        {
                            validCharacters = ValidCodeCharacters;
                            extraCharacters = 0;
                            realCharacters = encryptedText.Length;
                            extraCharacerOdds = 0;
                            break;
                        }
                    case PerSeTextEncryptionTypes.Filename:
                        {
                            validCharacters = ValidFilenameCharacters;
                            extraCharacters = 0;
                            realCharacters = encryptedText.Length;
                            extraCharacerOdds = 0;
                            break;
                        }
                    default: // Text
                        {
                            validCharacters = ValidTextCharacters;
                            extraCharacters = RandomNumber(MaxExtraEncryptionCharacters + 1);
                            realCharacters = encryptedText.Length - extraCharacters;
                            if (realCharacters > 0)
                                extraCharacerOdds = (int)Decimal.Truncate((decimal)((50 * extraCharacters) / realCharacters));
                            else
                                extraCharacerOdds = 0;
                            break;
                        }
                }

                int index = 0;
                int characterPositionIndex;
                StringBuilder decryptedText = new StringBuilder();
                bool isFilename = (encryptionType == PerSeTextEncryptionTypes.Filename);

                while (realCharacters > 0)
                {
                    if (extraCharacters > 0)
                    {
                        if (extraCharacerOdds >= (RandomNumber(100) + 1))
                        {
                            RandomNumber(0); // Need (unused) call here to keep in synch with encrypt side
                            index++;
                            --extraCharacters;
                        }
                    }

                    characterPositionIndex = encryptionCodeCharacters.IndexOf(encryptedText[index]);
                    if (characterPositionIndex < 0)
                    {
                        decryptedText.Append(encryptedText[index]);
                    }
                    else
                    {
                        characterPositionIndex = characterPositionIndex - RandomNumber(validCharacters.Length) - 1;
                        while (characterPositionIndex < 0)
                        {
                            characterPositionIndex += validCharacters.Length;
                        }
                        decryptedText.Append(validCharacters[characterPositionIndex]);
                    }

                    // Since all subdirectories of a directory path need to be encrypted/decrypted
                    // identically, we reset the seed value whenever we start a new subdirectory.
                    if (isFilename && (encryptedText[index] == '\\'))
                    {
                        _currentRandomNumber = key;
                    }

                    index++;
                    realCharacters--;
                }
                _currentRandomNumber = originalKey;

                return decryptedText.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("Error decrypting string", ex);
            }
        }

        /// <summary>
        /// Decrypts an encrypted key
        /// </summary>
        /// <param name="encryptedKey">The encrypted key.</param>
        /// <returns>the key in it's original integer form</returns>
        private int DecryptKey(string encryptedKey)
        {
            try
            {
                int count;
                int index;
                int maxIndex;
                int tempKey;
                int decryptedKey;
                int value;

                maxIndex = KeyEncryptionString.Length;
                tempKey = 0;

                for (count = 1; count < encryptedKey.Length; count++)
                {
                    index = KeyEncryptionString.IndexOf(encryptedKey[count]);
                    value = index - KeyEncryptionString.IndexOf(encryptedKey[count - 1]);

                    if (value < 0)
                    {
                        value += maxIndex;
                    }

                    if (value == 16)
                    {
                        value = 0;
                    }

                    tempKey = (tempKey << EncryptionKeyShift) + (value & EncryptionKeyBitMask);
                }

                decryptedKey = 0;
                for (count = 0; count < (16 / 4); count++)
                {
                    decryptedKey = (decryptedKey << EncryptionKeyShift) | (tempKey & EncryptionKeyBitMask);
                    tempKey = tempKey >> EncryptionKeyShift;
                }

                return decryptedKey;
            }
            catch (Exception ex)
            {
                throw new Exception("Error decrypting key", ex);
            }
        }

        /// <summary>
        /// Retrieves the embedded key out of Encrypted Text
        /// </summary>
        /// <param name="encryptedText">the encrypted text to retrieve the embedded key from</param>
        /// <returns>embedded encrypted key</returns>
        private int GetEmbeddedKey(string encryptedText)
        {
            int index;
            int decryptedKey;
            string encryptedKey;

            decryptedKey = -1;
            index = encryptedText.Length - (KeyStringLength - SplitKeyIndex) + 1;

            if (index >= (SplitKeyIndex + 1))
            {
                encryptedKey = encryptedText.Substring(0, SplitKeyIndex) +
                               encryptedText.Substring(index - 1);
                decryptedKey = DecryptKey(encryptedKey);
            }

            return decryptedKey;
        }

        /// <summary>
        /// Generates a valid Encryption Key
        /// </summary>
        /// <returns>encryption key</returns>
        private int GenerateEncryptionKey()
        {
            string charString;
            string codeString;
            int key;
            int identicalCharacterCount;
            bool isKeyValid = false;

            do
            {
                for (int i = 0; i < EncryptionKeySkipKeys; i++)
                {
                    RandomNumber(EncryptionKeySeed);
                }
                key = _currentRandomNumber;

                codeString = GenerateEncryptionCode(key);
                charString = ValidTextCharacters;

                identicalCharacterCount = 0;
                for (int i = 0; i < codeString.Length; i++)
                {
                    if (codeString[i] == charString[i])
                    {
                        identicalCharacterCount++;
                    }
                }
                isKeyValid = ((identicalCharacterCount < EncryptionKeyMaxUnchangedCount) && (key != -1));
            }
            while (!isKeyValid);

            return key;
        }

        /// <summary>
        /// Encrypts text for the specified encryption type
        /// </summary>
        /// <param name="decryptedText">text to encrypt</param>
        /// <param name="encryptionType">encryption type to perform</param>
        /// <returns>the text encrypted</returns>
        private string Encrypt(string decryptedText, PerSeTextEncryptionTypes encryptionType)
        {
            int decryptedKey;
            string encryptedKey = string.Empty;

            decryptedKey = GenerateEncryptionKey();
            encryptedKey = EncryptKey(decryptedKey);

            string encryptedText = Encrypt(decryptedText, decryptedKey, encryptionType);
            encryptedText = encryptedKey.Substring(0, SplitKeyIndex) + encryptedText + encryptedKey.Substring(SplitKeyIndex, encryptedKey.Length - SplitKeyIndex);

            return encryptedText;
        }

        /// <summary>
        /// Encrypts text for the specified encryption type
        /// </summary>
        /// <param name="decryptedText">text to encrypt</param>
        /// <param name="key">key to use for encryption</param>
        /// <param name="encryptionType">type of encryption to perform</param>
        /// <returns>decrypted text encrypted </returns>
        private string Encrypt(string decryptedText, int key, PerSeTextEncryptionTypes encryptionType)
        {
            try
            {
                string charString = string.Empty;
                string codeString = string.Empty;
                int extraCharacterOdds;
                int extraCharacters;
                int posIndex;
                int originalKey;
                StringBuilder encryptedText = new StringBuilder();

                codeString = GenerateEncryptionCode(key);
                originalKey = _currentRandomNumber;

                _currentRandomNumber = key;

                charString = ValidTextCharacters;
                extraCharacters = RandomNumber(MaxExtraEncryptionCharacters + 1);

                if (decryptedText.Length > 0)
                {
                    extraCharacterOdds = (50 * extraCharacters) / decryptedText.Length;
                }
                else
                {
                    extraCharacterOdds = 0;
                }

                if (decryptedText.Length > 0)
                {
                    for (int i = 0; i < decryptedText.Length; i++)
                    {
                        if (extraCharacters > 0)
                        {
                            if (extraCharacterOdds >= (RandomNumber(100) + 1))
                            {
                                posIndex = RandomNumber(codeString.Length) + 1;
                                if (posIndex >= codeString.Length)
                                {
                                    posIndex = codeString.Length - 1;
                                }
                                encryptedText.Append(codeString[posIndex]);
                                extraCharacters--;
                            }
                        }
                        posIndex = charString.IndexOf(decryptedText[i]);
                        if (posIndex < 0)
                        {
                            encryptedText.Append(decryptedText[i]);
                        }
                        else
                        {
                            posIndex = ((posIndex + RandomNumber(codeString.Length) + 1) % codeString.Length);
                            encryptedText.Append(codeString[posIndex]);
                        }
                    }
                }

                while (extraCharacters > 0)
                {
                    posIndex = RandomNumber(codeString.Length) + 1;
                    if (posIndex >= codeString.Length)
                    {
                        posIndex = codeString.Length - 1;
                    }
                    encryptedText.Append(codeString[posIndex]);
                    extraCharacters--;
                }
                _currentRandomNumber = originalKey;

                return encryptedText.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("Error Encrypting key", ex);
            }
        }

        /// <summary>
        /// Encrypts a Key
        /// </summary>
        /// <param name="decryptedKey">key to encrypt</param>
        /// <returns>encrypted key</returns>
        private string EncryptKey(int decryptedKey)
        {
            int count;
            int index;
            int maxIndex;
            StringBuilder encryptedKey = new StringBuilder();
            int value;

            maxIndex = KeyEncryptionString.Length;
            index = RandomNumber(maxIndex);
            encryptedKey.Append(KeyEncryptionString[index]);

            for (count = 0; count < (16 / 4); count++)
            {
                value = decryptedKey & EncryptionKeyBitMask;
                if (value == 0)
                {
                    value = 16;
                }
                decryptedKey >>= EncryptionKeyShift;
                index = ((index + value) % maxIndex);
                encryptedKey.Append(KeyEncryptionString[index]);
            }
            return encryptedKey.ToString();
        }

        /// <summary>
        /// Generates a Random number based on the Value, seeds and other custom inhouse 
        /// values        
        /// </summary>
        /// <param name="seed">random number seed</param>
        /// <returns></returns>
        private int RandomNumber(int seed)
        {
            float newValue;
            int newRandomNumber;

            _currentRandomNumber = ((_currentRandomNumber * RandomNumberMultiplier) + RandomNumberExtraValue) & RandomNumberBitMask;
            newValue = _currentRandomNumber / RandomNumberDivisor;
            newRandomNumber = (int)Decimal.Truncate((decimal)(seed * newValue));

            return newRandomNumber;
        }

        /// <summary>
        /// Generates an Encryption Code String based on the Seed
        /// </summary>
        /// <param name="seed">seed to build the encryption code string for</param>
        /// <returns>encryption code string</returns>
        private string GenerateEncryptionCode(int seed)
        {
            return GenerateEncryptionCode(seed, PerSeTextEncryptionTypes.Text);
        }

        /// <summary>
        /// Generates an Encryption Code String based on the Seed and Encryption Type
        /// </summary>
        /// <param name="seed">seed to build the encryption code string for</param>
        /// <param name="encryptionType">Encryption type to build the encryption code string for</param>
        /// <returns>encryption code string</returns>
        private string GenerateEncryptionCode(int seed, PerSeTextEncryptionTypes encryptionType)
        {
            try
            {
                StringBuilder encryptionCodeString = new StringBuilder();
                StringBuilder validEncryptionCharacters = new StringBuilder();

                switch (encryptionType)
                {
                    case PerSeTextEncryptionTypes.Code:
                        validEncryptionCharacters.Append(ValidCodeCharacters);
                        break;

                    case PerSeTextEncryptionTypes.Filename:
                        validEncryptionCharacters.Append(ValidFilenameCharacters);
                        break;

                    default: // Text
                        validEncryptionCharacters.Append(ValidTextCharacters);
                        break;

                }

                int index;
                int originalKey = _currentRandomNumber;

                _currentRandomNumber = seed;
                while (validEncryptionCharacters.Length > 0)
                {
                    index = RandomNumber(validEncryptionCharacters.Length);
                    encryptionCodeString.Append(validEncryptionCharacters[index]);
                    validEncryptionCharacters.Remove(index, 1);
                }
                _currentRandomNumber = originalKey;

                return encryptionCodeString.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("Error Generating Encryption code", ex);
            }
        }

        /// <summary>
        /// Encrypts the specified text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="key">The key.</param>
        /// <param name="encryptionMode">The encryption mode.</param>
        /// <returns></returns>
        /// Change Made On: 5/6/2009
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        private byte[] Encrypt(string text, string key, string encryptionMode)
        {
            SymmetricAlgorithm cryptoObj = null;
            cryptoObj = GetEncryptionProviderObject(encryptionMode);

            byte[] bytIn = Encoding.ASCII.GetBytes(text);
            // create a MemoryStream so that the process can be done without I/O files
            MemoryStream ms = new MemoryStream();

            // set the private key
            cryptoObj.Key = GetLegalKey(key, encryptionMode);
            cryptoObj.IV = GetLegalVectorSize(key, encryptionMode);

            // create an Encryptor from the Provider Service instance
            ICryptoTransform encrypto = cryptoObj.CreateEncryptor();

            // create Crypto Stream that transforms a stream using the encryption
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);

            // write out encrypted content into MemoryStream
            cs.Write(bytIn, 0, bytIn.Length);
            cs.FlushFinalBlock();
            cs.Close();

            return ms.ToArray();
        }

        /// <summary>
        /// Decrypts the specified ciphertext.
        /// </summary>
        /// <param name="ciphertext">The ciphertext.</param>
        /// <param name="key">The key.</param>
        /// <param name="encryptionMode">The encryption mode.</param>
        /// <returns></returns>
        /// Change Made On: 5/6/2009
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        private string Decrypt(byte[] ciphertext, string key, string encryptionMode)
        {
            SymmetricAlgorithm deCryptoObj = null;
            deCryptoObj = GetEncryptionProviderObject(encryptionMode);

            // create a MemoryStream with the input
            MemoryStream ms = new MemoryStream(ciphertext, 0, ciphertext.Length);

            // set the private key
            deCryptoObj.Key = GetLegalKey(key, encryptionMode);
            deCryptoObj.IV = GetLegalVectorSize(key, encryptionMode);

            // create a Decryptor from the Provider Service instance
            ICryptoTransform encrypto = deCryptoObj.CreateDecryptor();

            // create Crypto Stream that transforms a stream using the decryption
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);

            // read out the result from the Crypto Stream
            StreamReader sr = new StreamReader(cs);
            return sr.ReadToEnd();

        }

        /// <summary>
        /// Gets the encryption provider object.
        /// </summary>
        /// <param name="encryptionMode">The encryption mode.</param>
        /// <returns></returns>
        /// Change Made On: 5/6/2009
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        private SymmetricAlgorithm GetEncryptionProviderObject(string encryptionMode)
        {
            SymmetricAlgorithm tmpCryptoObj = null;

            switch (encryptionMode)
            {
                case "DES":
                    tmpCryptoObj = new DESCryptoServiceProvider();
                    break;
                case "RC2":
                    tmpCryptoObj = new RC2CryptoServiceProvider();
                    break;
                case "Rijndael":
                    tmpCryptoObj = new RijndaelManaged();
                    break;
                case "TripleDES":
                    tmpCryptoObj = new TripleDESCryptoServiceProvider();
                    break;
                default:
                    tmpCryptoObj = new RijndaelManaged();
                    break;
            }

            return tmpCryptoObj;
        }

        /// <summary>
        /// Gets the legal key.
        /// </summary>
        /// <param name="Key">The key.</param>
        /// <param name="encryptionMode">The encryption mode.</param>
        /// <returns></returns>
        /// Change Made On: 5/6/2009
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        private byte[] GetLegalKey(string Key, string encryptionMode)
        {
            string sTemp = Key;

            switch (encryptionMode)
            {
                case "DES":
                case "RC2":
                    if (Key.Length > 8)
                    {
                        sTemp = Key.Substring(0, 8);
                    }
                    break;
                case "TripleDES":
                    if (Key.Length > 16)
                    {
                        sTemp = Key.Substring(0, 16);
                    }
                    break;
                case "Rijndael":
                default:
                    if (Key.Length > 32)
                    {
                        sTemp = Key.Substring(0, 32);
                    }
                    break;
            }

            // convert the secret key to byte array
            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }

        /// <summary>
        /// Gets the size of the legal vector.
        /// </summary>
        /// <param name="Key">The key.</param>
        /// <param name="encryptionMode">The encryption mode.</param>
        /// <returns></returns>
        /// Change Made On: 5/6/2009
        /// Change Made By: Shane.Calhoun
        /// ==============================================
        private byte[] GetLegalVectorSize(string Key, string encryptionMode)
        {
            string sTemp = Key;

            switch (encryptionMode)
            {
                case "DES":
                case "RC2":
                    if (Key.Length > 8)
                    {
                        sTemp = Key.Substring(0, 8);
                    }
                    break;
                case "TripleDES":
                    if (Key.Length > 8)
                    {
                        sTemp = Key.Substring(0, 8);
                    }
                    break;
                case "Rijndael":
                default:
                    if (Key.Length > 16)
                    {
                        sTemp = Key.Substring(0, 16);
                    }
                    break;
            }

            // convert the secret key to byte array
            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }
    }
}
