Query string encryption

5/20/2008

I've talked before about encryption.  It's incredibly easy to add and rather effective at keeping prying eyes from viewing items you might not want them to view.  One of those items should be query strings. And to be honest, it's rather easy to do. However, how do we go about encrypting it and decrypting it in an almost transparent manner? Simple, HTTP Modules... Well, for the decryption anyway (I'll explain why it doesn't quite work for encryption in a little bit).

Encrypting the Query String

   1: public static string EncryptQueryString(StringDictionary Values)
   2: {
   3:     string InitialString="";
   4:     string Seperator="";
   5:     foreach (string Key in Values.Keys)
   6:     {
   7:         InitialString = Seperator + Key + "=" + Values[Key];
   8:         Seperator = "&";
   9:     }
  10:     return "?Request=" + //Encrypt InitialString here
  11: }

The above code takes a key/value pairing in the form of a StringDictionary and returns an encrypted query string (note that you have to add the encryption yourself and you may wish to look at my previous post dealing with that). Why do we have to call this function ourselves? Why can't we create an HTTP Module to do it for us?

  1. If all of our links are Hyperlinks or one of the other .Net toolbox items.
    1. Then no problem, just iterate through the page and change the query strings on the end of any links.
  2. What if we add links as literal controls?
    1. This means we might have to parse literal controls.
    2. The literal controls could be divided in an odd way, causing us to miss links, miss parts of a query string, etc.
      1. For instance "<a href='Page.aspx?Test=1" might be in the first literal control and "&Test2=1'>" could be in the second one.

All of these instances are easy to overcome if you want to put the time into it but to be honest, I'm lazy. So for me, I'll just make the call to the function and add it onto the end of the link.

Decrypting the Query String

   1: class EncryptQueryString:IHttpModule
   2: {
   3:     #region IHttpModule Members 
   4:  
   5:     /// <summary>
   6:     /// Disposes of the object
   7:     /// </summary>
   8:     public void Dispose()
   9:     {
  10:     } 
  11:  
  12:     /// <summary>
  13:     /// Initializes the object
  14:     /// </summary>
  15:     /// <param name="context">Application object</param>
  16:     public void Init(HttpApplication context)
  17:     {
  18:         context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
  19:     } 
  20:  
  21:     /// <summary>
  22:     /// Decrypts the query string and forwards it to the proper spot
  23:     /// </summary>
  24:     /// <param name="sender">Application object</param>
  25:     /// <param name="e"></param>
  26:     void context_AcquireRequestState(object sender, EventArgs e)
  27:     {
  28:         HttpApplication Application = (HttpApplication)sender;
  29:         HttpContext Context = Application.Context;
  30:         string EncryptedString = Context.Request.QueryString["Request"];
  31:         if (string.IsNullOrEmpty(EncryptedString))
  32:             return;
  33:         string OtherQueryStringValues="";
  34:         foreach (string Key in Context.Request.QueryString.Keys)
  35:         {
  36:             if (!Key.Equals("Request"))
  37:             {
  38:                 OtherQueryStringValues += "&" + Key + "=" + Context.Request.QueryString[Key];
  39:             }
  40:         }
  41:         string DecryptedString = //Decrypt string here
  42:         Context.Server.Transfer(Context.Request.AppRelativeCurrentExecutionFilePath + DecryptedString + OtherQueryStringValues);
  43:     } 
  44:  
  45:     #endregion
  46: }

The code above will take any encrypted query strings it comes across and decrypt it. At the same time, if we have portions of the query string which are not encrypted (for instance if you're using URL rewriting where it attach??s the relative location of the page requested), it will forward that along as well. You of course need to add this to your Web.config file but other than that, you shouldn't have to do anything. The page will receive the query string completely unencrypted.

Anyway, look at the code, leave feedback, and happy coding.



Comments