Reputation: 5600
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
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
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
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
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