Unable to decode Base-64 URLs

时光毁灭记忆、已成空白 提交于 2019-12-12 17:24:56

问题


I have an application that builds an HTML email. Included in the content is an encoded URL parameter that might, for example, contain a promotional code or product reference. The email is generated by a Windows service (essentially a console application) and the link, when clicked is handled by an MVC web site. Here is the code for creating the email link:

string CreateLink(string domain, string code) {
    // code == "xyz123"
    string encrypted = DES3Crypto.Encrypt(code);  // H3uKbdyzrUo=
    string urlParam = encrypted.EncodeBase64();   // SDN1S2JkeXpyVW890
    return domain + "/" + urlParam;
}

The action method on the MVC controller is constructed as follows:

public ActionResult Index(string id) {
    string decoded = id.DecodeBase64();
    string decrypted = DES3Crypto.Decrypt(decoded);
    ...
}

In all our testing, this mechanism has worked as expected, however, now we have gone live we are seeing around a 4% error rate where the conversion from base-64 fails with the following exception:

The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters.

The id parameter from the url 'looks' OK. The problem appears to be with the EncodeBase64/DecodeBase64 methods that are failing as DecodeBase64 method returns a 'garbled' string such as "�nl����□��7y�b�8�sJ���=" on the failed links.

Furthermore, most of the errors are from IE6 user agents leading me to think this is a character encoding problem but I don't see why.

For reference, here is the code for my base-64 URL encoding:

  public static string EncodeBase64(this string source)
  {
     byte[] bytes = Encoding.UTF8.GetBytes(source);
     string encodedString = HttpServerUtility.UrlTokenEncode(bytes);
     return encodedString;
  }

  public static string DecodeBase64(this string encodedString)
  {
     byte[] bytes = HttpServerUtility.UrlTokenDecode(encodedString);
     string decodedString = Encoding.UTF8.GetString(bytes);
     return decodedString;
  }

Any advice would be much appreciated.


回答1:


To recap, I was creating a URL that used a base-64 encoded parameter which was itself a Triple DES encrypted string. So the URL looked like http://[Domain_Name]/SDN1S2JkeXpyVW890 The link referenced a controller action on an MVC web site.

The URL was then inserted into an HTML formatted email. Looking at the error log, we saw that around 5% of the public users that responded to the link were throwing an "invalid base-64 string error". Most, but not all, of these errors were related to the IE6 user agent.

After trying many possible solutions based around character and URL encoding, it was discovered that somewhere in the client's process the url was being converted to lower-case - this, of course, broke the base-64 encoding (as it is uses both upper and lower case encoding characters).

Whether the case corruption was caused by the client's browser, email client or perhaps local anti-virus software, I have not been able to determine.

The Solution Do not use any of the standard base-64 encoding methods, instead use a base-32 or zBase-32 encoding instead - both of which are case-insensitive.

See the following links for more details

Base-32 - Wikipedia

MyTenPennies Base-32 .NET Implementation

The moral of the story is, Base-64 URL encoding can be unreliable in some public environments. Base-32, whilst slightly more verbose, is a better choice.

Hope this helps.




回答2:


It looks like you were really close. You had an extra zero coming back from your encyrpted.EncodeBase64() function.

Try this:

string data = "H3uKbdyzrUo=";
string b64str = Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(data));
string clearText = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(b64str));



回答3:


This is an interesting issue. My guess is that IE 6 is eating some of the characters.

For example, the length of the string that you included "ywhar0xznxpjdnfnddc0yxzbk2jnqt090" is not a multiple of four (which is a requirement for FromBase64 to work http://msdn.microsoft.com/en-us/library/system.convert.frombase64string.aspx)

But if you were to pad that string until it's length is a multiple of four ("ywhar0xznxpjdnfnddc0yxzbk2jnqt090" + "a12") then that works.

The MSDN documentation says that one ("=") or two ("==") equal characters are used for padding to/fromBase64 methods and I suspect IE 6 is truncating that from the string that you send.

This is total speculation but I hope it helps.



来源:https://stackoverflow.com/questions/11828864/unable-to-decode-base-64-urls

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