Introduction
Have you ever wanted to allow a user to bookmark a page, but you didn't want the user to be able to manually alter the query string parameters that would be required to generate the page?
These two functions take String Data and a Key and create a protected string which, if altered will generate an error when attempting to de-protect it. It also makes it nearly impossible for the user to validate data string with out knowing the Key.
This does not encrypt the data, an experienced individual can easily decode the data. However it is encoded with "base 64 encoding" so it is not human readable. You can however encrypt data using a separate function and then pass the encrypted data to these functions to protect it from tampering.
Real world example
One possible use is to save complex SQL selection criteria. It would just confuse the user if you passed this data on the querystring and it would be very important that they couldn't alter it and send it back. This is the type of thing you might generate from an advanced search form. Passing the data on the query string allows the user to bookmark the page or save the link for future use and yet does not allow them to submit data that is not generated by your web page.
Using the code
Pass your string data and secret key to TamperProofStringEncode
. This generates a protected string which can be stored in a database, file, etc.
If you want to send this data on the querystring then you also need to use HttpUtility.UrlEncode
. This formats the string so that it is read properly when using Request.QueryString
.
Example Usage
<A href='yourpage.aspx?Data=
<%= HttpUtility.UrlEncode(TamperProofStringEncode("Your String Data Here",
"Your Secret Key")) %>'>Click Here</A>
This code evaluates to something like:
<a href='yourpage.aspx?Data=
WW91ciBTdHJpbmcgRGF0YSBIZXJl-M%2b6N4pjf280%3d'>Click Here</a>
To read the data from the query string:
Try
DataString = TamperProofStringDecode(Request.QueryString("Data"), _
"Your Secret Key")
Catch ex As Exception
End Try
Details
Function TamperProofStringEncode(ByVal value As String, _
ByVal key As String) As String
Dim mac3des As New System.Security.Cryptography.MACTripleDES()
Dim md5 As New System.Security.Cryptography.MD5CryptoServiceProvider()
mac3des.Key = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key))
Return Convert.ToBase64String( _
System.Text.Encoding.UTF8.GetBytes(value)) & "-"c & _
Convert.ToBase64String(mac3des.ComputeHash( _
System.Text.Encoding.UTF8.GetBytes(value)))
End Function
Function TamperProofStringDecode(ByVal value As String, _
ByVal key As String) As String
Dim dataValue As String = ""
Dim calcHash As String = ""
Dim storedHash As String = ""
Dim mac3des As New System.Security.Cryptography.MACTripleDES()
Dim md5 As New System.Security.Cryptography.MD5CryptoServiceProvider()
mac3des.Key = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key))
Try
dataValue = System.Text.Encoding.UTF8.GetString( _
Convert.FromBase64String(value.Split("-"c)(0)))
storedHash = System.Text.Encoding.UTF8.GetString(_
Convert.FromBase64String(value.Split("-"c)(1)))
calcHash = System.Text.Encoding.UTF8.GetString( _
mac3des.ComputeHash(System.Text.Encoding.UTF8.GetBytes(dataValue)))
If storedHash <> calcHash Then
Throw New ArgumentException("Hash value does not match")
End If
Catch ex As Exception
Throw New ArgumentException("Invalid TamperProofString")
End Try
Return dataValue
End Function
Helper Functions
Optionally you can create two simple helper functions. The following are the two functions and their usage.
Private TamperProofKey As String =
ConfigurationSettings.AppSettings("TamperProofKey")
Function QueryStringEncode(ByVal value As String) As String
Return HttpUtility.UrlEncode(TamperProofStringEncode(value, TamperProofKey))
End Function
Function QueryStringDecode(ByVal value As String) As String
Return TamperProofStringDecode(value, TamperProofKey)
End Function
<A href='yourpage.aspx?Data=<%=
QueryStringEncode("Your Data String") %>'>HyperLink Text</A>
DataString = QueryStringDecode(Request.QueryString("Data"))
Notes
I strongly recommend storing the key in the web.config file or at the very least in a private string variable. This prevents a typo in your code from resulting in transmitting the secret key to the client.
Please see the attached source code for more information on how to use these functions.
This function does not protect an empty string. An empty string results in the same protected value regardless of the key. Therefore if you want to allow an empty string then add a character to your data and then strip this character off when you retrieve the data. This modification could easily be added to these functions, but it makes the code more difficult to understand.
Additional Information
The ZIP file contains a working example as a single aspx page. Please try it out. The ZIP file also contains a C# class based implementation.
History
- Replaced
Chr(0)
with "-"c
to make the output string more portable. It can now be safely written to a plain text file or other basic text storage location.
- Added a C# version class based implementation to the ZIP file.. This has currently only been tested on ASP.NET 2.0 beta 1.