UrlEncode is not encoding the + symbol and while decrypting Format Exception is coming up

不打扰是莪最后的温柔 提交于 2021-01-29 03:43:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!