Zaki
Zaki

Reputation: 5600

Encrypt and Decrypt password

I am using the following code to encrypt and decrypt passwords in asp.net. the encryption works perfectly but when decrypting it throws this error Invalid length for a Base-64 char array.

my password is 123 and i am using it as follow to encrypt: HttpUtility.UrlEncode(CryptorEngine.Encrypt(strpassword, true)); and to decrypt I am using it as follow :

CryptorEngine.Decrypt(HttpUtility.UrlDecode(strpassword), true));

and here is the code :

 public class CryptorEngine
    {
        /// <summary>
        /// Encrypt a string using dual encryption method. Return a encrypted cipher Text
        /// </summary>
        /// <param name="toEncrypt">string to be encrypted</param>
        /// <param name="useHashing">use hashing? send to for extra secirity</param>
        /// <returns></returns>
        public static string Encrypt(string toEncrypt, bool useHashing)
        {
            byte[] keyArray;
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
            // Get the key from config file
            string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
            //System.Windows.Forms.MessageBox.Show(key);
            if (useHashing)
            {
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
                hashmd5.Clear();
            }
            else
                keyArray = UTF8Encoding.UTF8.GetBytes(key);

            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            tdes.Key = keyArray;
            tdes.Mode = CipherMode.ECB;
            tdes.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = tdes.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            tdes.Clear();
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }
        /// <summary>
        /// DeCrypt a string using dual encryption method. Return a DeCrypted clear string
        /// </summary>
        /// <param name="cipherString">encrypted string</param>
        /// <param name="useHashing">Did you use hashing to encrypt this data? pass true is yes</param>
        /// <returns></returns>
        public static string Decrypt(string cipherString, bool useHashing)
        {
            byte[] keyArray;
            byte[] toEncryptArray = Convert.FromBase64String(cipherString);

            System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
            //Get your key from config file to open the lock!
            string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));

            if (useHashing)
            {
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
                hashmd5.Clear();
            }
            else
                keyArray = UTF8Encoding.UTF8.GetBytes(key);

            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            tdes.Key = keyArray;
            tdes.Mode = CipherMode.ECB;
            tdes.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = tdes.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            tdes.Clear();
            return UTF8Encoding.UTF8.GetString(resultArray);
        }
    }

Upvotes: 1

Views: 10554

Answers (4)

MichaelBolton
MichaelBolton

Reputation: 84

A little late here but the problem could be something else (it was for me).

Request.Querystring does some decoding already. In my case I was essentially decoding twice. Adding a second "HttpUtility.UrlEncode" did the trick (at least after 20 different tests).

I haven't exactly found firm documentation from Microsoft on this behavior, and the old books are stored away (I try not to leave my chair), but these links were helpful:

does Request.Querystring automatically url decode a string?

http://forums.asp.net/t/1354726.aspx?Request+Querystring+without+decoding+possible+

Upvotes: 0

Chris
Chris

Reputation: 27619

The code you have provided works fine. I tested it with this little program:

void Main()
{
    var cryptB64 =CryptorEngine.Encrypt("123", true);
    var encoded = HttpUtility.UrlEncode(cryptB64);
    var decoded = HttpUtility.UrlDecode(encoded);
    var decrypted = CryptorEngine.Decrypt(decoded, true);

    bool matches = (decrypted=="123");
    Console.WriteLine(matches);
}

And it returned true as expected.

The problem is presumably that you are mangling your encrypted value at some point. I would guess it is being transmitted via HTTP which I would guess is where the problem happens.

Additional Note:

When calling CryptorEngine.Decrypt(HttpUtility.UrlDecode(strpassword), true)); then you need to make sure that strpassword is the encrypted form of the password, not the plaintext password you are comparing against.

Upvotes: 1

rohan panchal
rohan panchal

Reputation: 881

hiii please use this code this works good

//Encryption method for credit card

public string EncryptTripleDES(string Plaintext, string Key)
{

    System.Security.Cryptography.TripleDESCryptoServiceProvider DES =

    new System.Security.Cryptography.TripleDESCryptoServiceProvider();

    System.Security.Cryptography.MD5CryptoServiceProvider hashMD5 =

    new System.Security.Cryptography.MD5CryptoServiceProvider();

    DES.Key = hashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(Key));

    DES.Mode = System.Security.Cryptography.CipherMode.ECB;

    System.Security.Cryptography.ICryptoTransform DESEncrypt = DES.CreateEncryptor();

    Buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(Plaintext);
   string TripleDES = Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));

    return TripleDES;

}
//Decryption Method 

public string DecryptTripleDES(string base64Text, string Key)
{

    System.Security.Cryptography.TripleDESCryptoServiceProvider DES =

    new System.Security.Cryptography.TripleDESCryptoServiceProvider();

    System.Security.Cryptography.MD5CryptoServiceProvider hashMD5 =

    new System.Security.Cryptography.MD5CryptoServiceProvider();
    DES.Key = hashMD5.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(Key));
    DES.Mode = System.Security.Cryptography.CipherMode.ECB;
    System.Security.Cryptography.ICryptoTransform DESDecrypt = DES.CreateDecryptor();
    Buffer = Convert.FromBase64String(base64Text);

    string DecTripleDES = System.Text.ASCIIEncoding.ASCII.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
   return DecTripleDES;

}

Upvotes: 1

Aristos
Aristos

Reputation: 66641

In the URL there are come characters that conflict with the encrypted output, and at least on my code, this is what make the problem. So I use this two functions to change this characters and avoid that.

public static string ChangeSPChart(string sTheInput)
{
    StringBuilder sRetMe = new StringBuilder(sTheInput);

    sRetMe.Replace('+', '-');
    sRetMe.Replace('/', '*');
    sRetMe.Replace('=', '!');

    return sRetMe.ToString();
}

public static string FixSPChart(string sTheInput)
{
    StringBuilder sRetMe = new StringBuilder(sTheInput);

    sRetMe.Replace('-', '+');
    sRetMe.Replace('*', '/');
    sRetMe.Replace('!', '=');

    return sRetMe.ToString();
}

and the encryption/decryption code will be:

public static string Encrypt(string toEncrypt, bool useHashing)
{
    byte[] keyArray;
    byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

    System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
    // Get the key from config file
    string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
    //System.Windows.Forms.MessageBox.Show(key);
    if (useHashing)
    {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
        hashmd5.Clear();
    }
    else
        keyArray = UTF8Encoding.UTF8.GetBytes(key);

    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = keyArray;
    tdes.Mode = CipherMode.ECB;
    tdes.Padding = PaddingMode.PKCS7;

    ICryptoTransform cTransform = tdes.CreateEncryptor();
    byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

    tdes.Clear();
    var encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);

    // here I change it
    return  ChangeSPChart(encrypted);
}
/// <summary>
/// DeCrypt a string using dual encryption method. Return a DeCrypted clear string
/// </summary>
/// <param name="cipherString">encrypted string</param>
/// <param name="useHashing">Did you use hashing to encrypt this data? pass true is yes</param>
/// <returns></returns>
public static string Decrypt(string cipherString, bool useHashing)
{
    cipherString = FixSPChart(cipherString);

    byte[] keyArray;
    byte[] toEncryptArray = Convert.FromBase64String(cipherString);

    System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
    //Get your key from config file to open the lock!
    string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));

    if (useHashing)
    {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
        hashmd5.Clear();
    }
    else
        keyArray = UTF8Encoding.UTF8.GetBytes(key);

    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = keyArray;
    tdes.Mode = CipherMode.ECB;
    tdes.Padding = PaddingMode.PKCS7;

    ICryptoTransform cTransform = tdes.CreateDecryptor();
    byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

    tdes.Clear();
    return UTF8Encoding.UTF8.GetString(resultArray);
}

Upvotes: 2

Related Questions