How to hide URL query information in ASP.NET in C#

In many cases, the URL query contains information that should keep on hidden from the user. You can switch to another form of state management or encrypt the query string. You can encrypt the query string by using the cryptography classes provided with .NET and by leveraging the DPAPI.

As a first step you should build an EncryptedQueryString class:

public class EncryptedQueryString :

System.Collections.Specialized.StringDictionary

{

public EncryptedQueryString()

{

// Nothing to do here

}

public EncryptedQueryString(string encryptedData)

{

// Decrypt information and add to the dictionary

}

public override string ToString()

{

// Encrypt information and return as

// HEX-encoded string

}

}

The EncryptedQueryString is derived from the StringDictionary class, which represents a collection of strings indexed by strings:

encryptedQueryString[“value 1”] = “Sample Value”;

The EncryptedQueryString class provides a ToString() method that examines all the collection data and combines it in a single encrypted string. The first portion of the ToString() method escapes and joins the collection settings into one string, while the second portion encrypts the data using DPAPI:

 

public override string ToString()

{

StringBuilder Content = new StringBuilder();

// Build a typical query string based on the contents

foreach (string key in base.Keys)

{

Content.Append(HttpUtility.UrlEncode(key));

Content.Append(“=”);

Content.Append(HttpUtility.UrlEncode(base[key]));

Content.Append(“&”);

}

// Remove the last ‘&’

Content.Remove(Content.Length-1, 1);

// Encrypt the contents using DPAPI

byte[] EncryptedData = ProtectedData.Protect(Encoding.UTF8.GetBytes(Content.ToString()),null, DataProtectionScope.LocalMachine);

// Convert encrypted byte array to a URL-legal string.

// Check that data is not larger than typical 4 KB query string

return HexEncoding.GetString(EncryptedData);

}

 

The ToString() method uses internally hex encoding, which replaces each character with an alphanumeric code. This functionality is provided by a class named HexEncoding:

public static class HexEncoding

{

public static string GetString(byte[] data)

{

StringBuilder Results = new StringBuilder();

foreach (byte b in data)

{

Results.Append(b.ToString(“X2”));

}

return Results.ToString();

}

public static byte[] GetBytes(string data)

{

// GetString encodes the hex numbers with two digits

byte[] Results = new byte[data.Length / 2];

for (int i = 0; i < data.Length; i += 2)

{

Results[i / 2] = Convert.ToByte(data.Substring(i, 2), 16);

}

return Results;

}

}

You can place the string returned from EncryptedQueryString.ToString() directly into a query string using the Response.Redirect() method. The destination page that receives the query data has to deserialize and decrypt the string. You need to create a new EncryptedQueryString object which supplies the encrypted data. You can add a new constructor to the EncryptedQueryString class that accepts the encrypted string. This constructor first decodes the hexadecimal information from the string passed in and uses the DPAPI to decrypt information stored in the query string. It then splits the information back into its parts and adds the key/value pairs to the base StringCollection:

 

public EncryptedQueryString(string encryptedData)

{

// Decrypt data passed in using DPAPI

byte[] RawData = HexEncoding.GetBytes(encryptedData);

byte[] ClearRawData = ProtectedData.Unprotect(RawData, null, DataProtectionScope.LocalMachine);

string StringData = Encoding.UTF8.GetString(ClearRawData);

 

// Split the data and add the contents

int Index;

string[] SplittedData = StringData.Split(new char[] { ‘&’ });

foreach (string SingleData in SplittedData)

{

Index = SingleData.IndexOf(‘=’);

base.Add(HttpUtility.UrlDecode(SingleData.Substring(0, Index)),

HttpUtility.UrlDecode(SingleData.Substring(Index + 1)));

}

}