Why asp.net accidentally corrupts your base64 encoded strings if you pass them as a query string (its nothing personal)

We are going to investigate one of the gotchas when using base 64 encoded data with the asp.net Request.QueryString array.

If you try to extract a base64 encoded string from a query string then it will get corrupted. This is because a valid base64 encoded string will more than likely have plus + symbols it. As far as a url is concerned a plus symbol has a special meaning - it is the url encoded equivalent of the whitespace character.

This means that when you retrieve them from the Request.QueryString collection asp.net innocently performs its due diligence and url decodes the incoming string, replacing all + symbols with spaces.

If you try to decode the remaining base64 string you will get an error because its not in a valid format.

Is this going to happen to me?

One thing to note - this will only occur if you have a third party external system pass you a plain base64 encoded string without url encoding it first. If you're putting the base64 string into your query string via some asp.net code then you will not experience this particular bug.

How do I work around this?

The trick to work around this is to do a string.Replace(" ", "+") on any base64 encoded strings that have come from a QueryString before you use them.

string validBase64String = Request.QueryString["data"].Replace(" ", "+");

And that's safe?

Its safe to do this because a space character is not a valid character in a base64 encoded string. Based on this fact you can be sure that if there are any space characters then you already have a broken base64 string on your hands. Doing the Replace() is not going to corrupt your data any further.

kick it on DotNetKicks.com Shout it


schmik07 said...

Could you not urlencode the querystring before you pass it, and the ureldecode the querystring when you read it:

HttpContext.Current.Server.UrlEncode(myQuerystring) to pass it:

HttpContext.Current.Server.UrlDecode(myQuerystring) to read it...?

rtpHarry said...

schmik07 - yes this is how you should do it. I pointed out in the "is this going to happen to me?" section that this only happens with certain third party scripts not passing in urlencoded data.

I am referring to SagePay/Protx. When it passes itself back to your site it passes base64 with data that isn't urlencoded.

Oblio said...

You can also use Uri.UnescapeDataString(myQuerystring)