Global Query String Encryption in C#

Introduction

In this article I will tell you how to encrypt a Query String globally in your application.

This article will help you to encrypt a Query String in a very convenient and easy manner, you don't need to write code again and again, you just need to add a class and only a few modifications in the Web.config file are needed.

In my last article I told you how to Get Values From Query String Using jQuery. I am working on the same application and will show you how encryption can save our data from being changed and/or read by an unauthorized user or attacker.

Step 1

First of all you need to add a class named "QueryStringModule". You can get this class from my code that is available in Zip/RAR format at the start of this article.

In this class first of all the Init function is called that will be called on each initiated request. In this function "Beginrequest" is called:

  1. public void Init(HttpApplication context)  
  2. {  
  3.     context.BeginRequest += context_BeginRequest;  

In the Beginrequest our URL is checked for two thingsthe , first is .aspx and the second is "?". Both of these things confirm that it is an aspx page and has a query string associated with it.

After checking the URL two strings are declared, the first has "RawURL", in other words a real and complete URL that is to be seen when the page is loaded and the second string gets only the name of the page that is to be loaded, this is done by sending the URL as the parameter to another function "GetVirtualPath" that splits the URL from "?" and returns the first part of the URL.

Now if the URL contains a specified text that will be appended after the encryption is done then it's sent for decryption otherwise it goes for encryption.

  1. private const string PARAMETER_NAME = "encrypt=1&";  
  2. private const string ENCRYPTION_KEY = "key";  
  3. void context_BeginRequest(object sender, EventArgs e)  
  4. {  
  5.   
  6.     HttpContext context = HttpContext.Current;  
  7.     if (context.Request.Url.OriginalString.Contains("aspx") &&  
  8.                context.Request.RawUrl.Contains("?"))  
  9.     {  
  10.         string query = context.Request.RawUrl;  
  11.         string path = GetVirtualPath();  
  12.   
  13.         if (query.Contains(PARAMETER_NAME))  
  14.         {  
  15.             // Decrypts the query string and rewrites the path.  
  16.             //string rawQuery = query.Replace(PARAMETER_NAME, string.Empty);  
  17.             string decryptedQuery = Decrypt(query);  
  18.             context.RewritePath(path, string.Empty, decryptedQuery);  
  19.         }  
  20.         else if (context.Request.HttpMethod == "GET")  
  21.         {  
  22.             // Encrypt the query string and redirects to the encrypted URL.  
  23.             // Remove if you don't want all query strings to be encrypted automatically.  
  24.             if (query != "")  
  25.             {  
  26.                 string encryptedQuery = Encrypt(query);  
  27.                 context.Response.Redirect(encryptedQuery);  
  28.             }  
  29.         }  
  30.     }  

Step 2

In the Encrypt function the URL is sliced at various levels and from different positions.

First it's sliced from "&" that will come after the "?" mark in URL. After breaking it from "&", the sliced part is again sliced from the "=" mark, this means we will get two values for each "&" mark, first as the name of the parameter and the second as the value of the parameter. This code will encrypt the value of the parameter and will then again concatenate it to the URL, this will go on until all the "&" marks are not covered. So, this means that now you will see a different URL whose parameter names are unchanged but the values they are now having are totally different.

After doing the encryption I had made one more change, in other words I replaced "?" with the "?encrypt=1&", this is done because "?" is also being encrypted and if you try to decrypt the URL then it finds it difficult to identify the first parameter, so I had add a new parameter in the URL (which is of no use) so that effect will be only on this new parameter and not on the parameters that are really of use.

  1. public static string Encrypt(string url)  
  2. {  
  3.     string cookedUrl = url;  
  4.   
  5.     if (url != null && url.Contains(".aspx?"))  
  6.     {  
  7.         cookedUrl = url.Substring(0, url.IndexOf('?') + 1);  
  8.   
  9.         var queryStrings = url.Substring(url.IndexOf('?') + 1).Split('&');  
  10.   
  11.         foreach (var queryString in queryStrings)  
  12.         {  
  13.             if (!string.IsNullOrEmpty(queryString))   
  14.                 cookedUrl += queryString.Split('=')[0] + "=" + Encrypting(queryString.Split('=')[1]) + "&";  
  15.         }  
  16.         cookedUrl = cookedUrl.Substring(0, cookedUrl.Length - 1);  
  17.         cookedUrl = cookedUrl.Replace("?""?" + PARAMETER_NAME);  
  18.     }  
  19.     return cookedUrl;  
  20.   

Step 3

Now the encryption is done and now it's time for decrypting this encryption.

This will be done in the same manner in which the encryption was done, it will again break the URL at various levels and from different positions.

It will again look for the "?", "&" and "=" mark and will decrypt the value part.

  1. public static string Decrypt(string url)  
  2. {  
  3.     if (url.Contains(".aspx?"))  
  4.     {  
  5.         var path = HttpContext.Current.Request.RawUrl;  
  6.         path = path.Substring(0, path.IndexOf("?", StringComparison.Ordinal) + 1);  
  7.         path = path.Substring(path.LastIndexOf("/", StringComparison.Ordinal) + 1);  
  8.   
  9.         var queryStrings = url.Substring(url.IndexOf('?') + 1).Split('&');  
  10.   
  11.         foreach (var queryString in queryStrings)  
  12.         {  
  13.             path += queryString.Split('=')[0] + "=" + Decrypting(queryString.Substring(queryString.IndexOf('=') + 1)) + "&";  
  14.         }  
  15.         path = path.Substring(0, path.Length - 1);  
  16.         url = path;  
  17.     }  
  18.     return url;  

Step 4

Now our work on this class is completed and we need to move towards the web.config file because we need to make some changes and updates to get this class working.

You need to add this code to your WebConfig file to get the code working:

  1. <configuration>  
  2.   <system.web>  
  3.   
  4.     <compilation debug="true" targetFramework="4.5" />  
  5.     <httpRuntime targetFramework="4.5" />  
  6.   </system.web>  
  7.   <system.web>  
  8.     <httpModules>  
  9.       <add type="QueryStringModule" name="QueryStringModule"/>  
  10.     </httpModules>  
  11.   </system.web>  
  12.   <system.webServer>  
  13.     <modules>  
  14.       <add name="QueryStringModule" type="QueryStringModule"/>  
  15.       <remove name="ScriptModule"/>  
  16.     </modules>  
  17.     <validation validateIntegratedModeConfiguration="false"/>  
  18.   </system.webServer>  
  19.   
  20. </configuration> 

Now our work is completed and we can move forward to see the output.

Output

On running the application, two textboxes will be available, make some entries in these texboxes and click the Submit button.

QueryStringEncryption

On reaching the second code you will see a complete different output of what we got previously.

Previously:

QueryStringEncryption

After Encryption:

QueryStringEncryption