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

Inherits System.Collections.Specialized.StringDictionary

 

Public Sub New()

‘ Nothing to do here

End Sub

‘ Decrypt information and add to the dictionary

Public Sub New(encryptedData As String)

‘ Decrypt information and add to the dictionary

End Sub

Public Overrides Function ToString() As String

‘ Encrypt information and return as

‘ HEX-encoded string

End Function

End Class

 

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 Overrides Function ToString() As String

Dim Content As New StringBuilder()

‘ Build a typical query string based on the contents

For Each key As String In MyBase.Keys

Content.Append(HttpUtility.UrlEncode(key))

Content.Append(“=”)

Content.Append(HttpUtility.UrlEncode(MyBase.Item(key)))

Content.Append(“&”)

Next

‘ Remove the last ‘&’

Content.Remove(Content.Length – 1, 1)

‘ Encrypt the contents using DPAPI

Dim EncryptedData As Byte() = ProtectedData.Protect(Encoding.UTF8.GetBytes(Content.ToString()), Nothing, 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)

End Function

 

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 NotInheritable Class HexEncoding

Private Sub New()

End Sub

Public Shared Function GetString(data As Byte()) As String

Dim Results As New StringBuilder()

For Each b As Byte In data

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

Next

Return Results.ToString()

End Function

Public Shared Function GetBytes(data As String) As Byte()

‘ GetString encodes the hex numbers with two digits

Dim Results As Byte() = New Byte(data.Length \ 2 – 1) {}

For i As Integer = 0 To data.Length – 1 Step 2

Results(i \ 2) = Convert.ToByte(data.Substring(i, 2), 16)

Next

Return Results

End Function

End Class

 

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 Sub New(encryptedData As String)

‘ Decrypt data passed in using DPAPI

Dim RawData As Byte() = HexEncoding.GetBytes(encryptedData)

Dim ClearRawData As Byte() = ProtectedData.Unprotect(RawData, Nothing, DataProtectionScope.LocalMachine)

Dim StringData As String = Encoding.UTF8.GetString(ClearRawData)

 

‘ Split the data and add the contents

Dim Index As Integer

Dim SplittedData As String() = StringData.Split(New Char() {“&”C})

For Each SingleData As String In SplittedData

Index = SingleData.IndexOf(“=”C)

MyBase.Add(HttpUtility.UrlDecode(SingleData.Substring(0, Index)), HttpUtility.UrlDecode(SingleData.Substring(Index + 1)))

Next

End Sub