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