问题
Let me explain the situation. In my code , I am encrypting the userid converted to string which is generated after a registration is done. The ecrypted string is passed as a url parameter as below.
string ConfirmCode = string.Empty;
Common.Secure.Security mySec = new Common.Secure.Security();
ConfirmCode = mySec.Encrypt(myMember.MemberID.ToString());
string EmailValidationLink = "<a href=\'" + pageScheme + "://" + CurrentDomain.HostName + "/Contents/Common/" + "EN" + "/" + CurrentDomain.EmailValidationPage + "?ConfirmCode=" + **UrlEncode(ConfirmCode)** + "\'>Click here to validate your account.</a>";
And:
protected String UrlEncode(String text)
{
return HttpContext.Current.Server.UrlEncode(text);
}
I am using the UrlEncode to pass the encrypted string, but the problem is if the encrypted text has a '+' symbol, while decryption I am getting a Format Exception , because this '+' symbol is taken as a ' ' space.
for example if the encrypted text is like 'S7+5tZzTm0k=' while fetching it, the + symbol is taken as 'S7 5tZzTm0k=' which is causing the format exception.
my encryption and decryption code is like below
public string Decrypt(string Text)
{
if (!ENABLED) return Text;
des.Key = hashmd5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey));
des.Mode = CipherMode.ECB;
ICryptoTransform desdencrypt = des.CreateDecryptor();
Byte[] buff = Convert.FromBase64String(Text);
return ASCIIEncoding.ASCII.GetString(desdencrypt.TransformFinalBlock(buff, 0, buff.Length));
}
public string Encrypt(string Text)
{
if (!ENABLED) return Text;
des.Key = hashmd5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey));
des.Mode = CipherMode.ECB;
ICryptoTransform desdencrypt = des.CreateEncryptor();
ASCIIEncoding MyASCIIEncoding = new ASCIIEncoding();
Byte[] buff = ASCIIEncoding.ASCII.GetBytes(Text);
return Convert.ToBase64String(desdencrypt.TransformFinalBlock(buff, 0, buff.Length));
}
I have been googling about this and everybody suggests that using UrlEncode would solve the problem , but in my case even after using it has not solved the problem.
Please let me know how to go about this ?
if (Request.QueryString["ConfirmCode"] != null)
{
bool isAccountSuspended;
isAccountSuspended = AccountManagement.AcountManager.EmailValidationNote(HttpContext.Current.Server.UrlDecode(Request.QueryString["ConfirmCode"]));
if (!isAccountSuspended)
{
lblMessage.Text = "Your account is already suspended. Please contact customer service.";
lblMessage.ForeColor = System.Drawing.Color.Red;
}
else
{
lblMessage.Text = "Thank you for verifying your email address. We hope you’ll enjoy playing with us.";
}
}
Regards Srividhya
回答1:
Required Using Directive: using System.Security.Cryptography;
Way to encrypt: HttpUtility.UrlEncode(Encrypt(Value));
Example: string value=HttpUtility.UrlEncode(Encrypt(Value));
Way to decrypt: Decrypt(HttpUtility.UrlDecode(value);
private string Encrypt(string clearText)
{
string EncryptionKey = "MAKV2SPBNsdsI99212";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
private string Decrypt(string cipherText)
{
string EncryptionKey = "MAKV2SPBNsdsI99212";
cipherText = cipherText.Replace(" ", "+");
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
回答2:
You can simply replace all occurrences of +
with the percent encoding - %2B
.
UrlEncode(ConfirmCode).Replace("+", "%2B")
回答3:
On looking a bit I believe that Request.QueryString
will give you a decoded version of what is in the querystring so that is giving you the version with the + and then you are effectively decoding it again which is where the mistake happens.
Change the line to the following
isAccountSuspended = AccountManagement.AcountManager.EmailValidationNote(Request.QueryString["ConfirmCode"]);
(ie remove the decode) and it should work.
回答4:
This is speculative, but I suspect you may be calling UrlDecode
on the same string twice.
You indicated that the value in the URL is ConfirmCode=S7%2b5tZzTm0k%3d
, which is correct (%2b is the correct encoding for '+').
If you decode this string once, you get S7+b5tZTm0k=
, as expected.
If you decode that string, you will get S7 b5tZTm0k=
, since '+' is decoded as ' '. This is what you are seeing.
You may want to look through your decoding logic to ensure that the resultant string is only being decoded once.
回答5:
OK, from all given data from you and other comments and answers, I've come to only one possible logical conclusion: your url encoded string is decoded twice. First decode of S7%2B5tZzTm0k%3D
gives you S7+5tZzTm0k=
, second decode gives you S7 5tZzTm0k=
. It's only a matter of careful debug to detect place there string is url decoded twice.
P.S. As a way to verify that, encode value twice, it will be decoded correctly then. Twice encoded url value should be S7%252B5tZzTm0k%253D
.
来源:https://stackoverflow.com/questions/10025838/urlencode-is-not-encoding-the-symbol-and-while-decrypting-format-exception-is