views:

4129

answers:

8

I need to encrypt and decrypt a querystring in ASP.NET.

The querystring might look something like this:

http://www.mysite.com/report.aspx?id=12345&year=2008

How do I go about encrypting the entire querystring so that it looks something like the following?

http://www.mysite.com/report.aspx?crypt=asldjfaf32as98df8a

And then, of course, how to I decrypt it? What's the best encryption to use for something like this? TripleDES?

A: 

I can't give you a turn key solution off the top of my head, but you should avoid TripleDES since it is not as secure as other encryption methods.

If I were doing it, I'd just take the entire URL (domain and querystring) as a URI object, encrypt it with one of the built-in .NET libraries and supply it as the crypt object. When I need to decrypt it, do so, then create a new URI object, which will let you get everything back out of the original querystring.

swilliams
A: 

You should look at Secure Query String.

Vivek
+5  A: 

Here is a way to do it in VB From: http://www.devcity.net/Articles/47/1/encrypt_querystring.aspx

Wrapper for the encryption code: Pass your querystring parameters into this, and change the key!!!

Private _key as string = "!#$a54?3"
Public Function encryptQueryString(ByVal strQueryString As String) As String
    Dim oES As New ExtractAndSerialize.Encryption64()
    Return oES.Encrypt(strQueryString, _key)
End Function

Public Function decryptQueryString(ByVal strQueryString As String) As String
    Dim oES As New ExtractAndSerialize.Encryption64()
    Return oES.Decrypt(strQueryString, _key)
End Function

Encryption Code:

Imports System
Imports System.IO
Imports System.Xml
Imports System.Text
Imports System.Security.Cryptography

Public Class Encryption64
    Private key() As Byte = {}
    Private IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}

    Public Function Decrypt(ByVal stringToDecrypt As String, _
        ByVal sEncryptionKey As String) As String
        Dim inputByteArray(stringToDecrypt.Length) As Byte
         Try
            key = System.Text.Encoding.UTF8.GetBytes(Left(sEncryptionKey, 8))
            Dim des As New DESCryptoServiceProvider()
            inputByteArray = Convert.FromBase64String(stringToDecrypt)
            Dim ms As New MemoryStream()
            Dim cs As New CryptoStream(ms, des.CreateDecryptor(key, IV), _
                CryptoStreamMode.Write)
            cs.Write(inputByteArray, 0, inputByteArray.Length)
            cs.FlushFinalBlock()
            Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8
            Return encoding.GetString(ms.ToArray())
        Catch e As Exception
            Return e.Message
        End Try
    End Function

    Public Function Encrypt(ByVal stringToEncrypt As String, _
        ByVal SEncryptionKey As String) As String
        Try
            key = System.Text.Encoding.UTF8.GetBytes(Left(SEncryptionKey, 8))
            Dim des As New DESCryptoServiceProvider()
            Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes( _
                stringToEncrypt)
            Dim ms As New MemoryStream()
            Dim cs As New CryptoStream(ms, des.CreateEncryptor(key, IV), _
                CryptoStreamMode.Write)
            cs.Write(inputByteArray, 0, inputByteArray.Length)
            cs.FlushFinalBlock()
            Return Convert.ToBase64String(ms.ToArray())
        Catch e As Exception
            Return e.Message
        End Try
    End Function

End Class
Brian Schmitt
This almost works. I changed these two lines:Return Server.UrlEncode(enc64.Encrypt(qs, _key))andReturn Server.UrlDecode(enc64.Decrypt(qs, _key))and don't bother with the Replace(" ", "+")
Elmo Gallen
Elmo Gallen
A: 

Why are you trying to encrypt your query string? If the data is sensitive, you should be using SSL. If you are worried about someone looking over the user's shoulder, use form POST instead of GET.

I think it is pretty likely that there is a better solution for your fundamental problem than encrypting the query string.

Joseph Bui
We are using SSL as well, but someone decided to just pass this data on the querystring a long time ago, so that's the way it will be for now.
Elmo Gallen
If you are already using SSL, you only care about shoulder surfing, so how about using Convert.ToBase64String(data) and Convert.FromBase64String(base64) on the parameter values.
Joseph Bui
A: 

Here's a sort of fancy version of the decrypt function from Brian's example above that you could use if you were only going to use this for the QueryString as it returns a NameValueCollection instead of a string. It also contains a slight correction as Brian's example will break without

stringToDecrypt = stringToDecrypt.Replace(" ", "+")

if there are any 'space' characters in the string to decrypt:

Public Shared Function DecryptQueryString(ByVal stringToDecrypt As String, ByVal encryptionKey As String) As Collections.Specialized.NameValueCollection
    Dim inputByteArray(stringToDecrypt.Length) As Byte
    Try
        Dim key() As Byte = System.Text.Encoding.UTF8.GetBytes(encryptionKey.Substring(0, encryptionKey.Length))
        Dim IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}
        Dim des As New DESCryptoServiceProvider()
        stringToDecrypt = stringToDecrypt.Replace(" ", "+")
        inputByteArray = Convert.FromBase64String(stringToDecrypt)
        Dim ms As New MemoryStream()
        Dim cs As New CryptoStream(ms, des.CreateDecryptor(key, IV), CryptoStreamMode.Write)
        cs.Write(inputByteArray, 0, inputByteArray.Length)
        cs.FlushFinalBlock()
        Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8
        Dim decryptedString As String = encoding.GetString(ms.ToArray())
        Dim nameVals() As String = decryptedString.Split(CChar("&"))
        Dim queryString As New Collections.Specialized.NameValueCollection(nameVals.Length)
        For Each nameValPair As String In nameVals
            Dim pair() As String = nameValPair.Split(CChar("="))
            queryString.Add(pair(0), pair(1))
        Next
        Return queryString

    Catch e As Exception
        Throw New Exception(e.Message)
    End Try
End Function

I hope you find this useful!

Brendan Kendrick
A: 

I was originally going to agree with Joseph Bui on the grounds that it would be more processor efficient to use the POST method instead, web standards dictate that if the request is not changing data on the server, the GET method should be used.

It will be much more code to encrypt the data than to just use POST.

smbarbour
A: 

I tried Brian Schmitt's code. Some caveats-- the query strings sometimes can get very long for short query strings. I did some research. You need to use Base64 encoding. Also don't forget when you are concatenating to your URL you need to do Server.UrlEncode but when you take stuff out of Request.QueryString[] it already is UrlDecoded.

Performance stats on three random strings- old 68/1844/164 characters, base 64, 44/832/84

public byte[] StrToByteArray(string str)
{
    if (str.Length == 0)
        throw new Exception("Invalid string value in StrToByteArray");
    return Convert.FromBase64String(str);
}

public string ByteArrToString(byte[] byteArr)
{
    return Convert.ToBase64String(byteArr);
}
MatthewMartin
A: 

Look into TSHAK. Many large sites out there use this 3rd party component.

http://www.dotnetjunkies.com/howto/99201486-acfd-4607-a0cc-99e75836dc72.dcik http://blog.taragana.com/index.php/archive/tutorial-to-encrypt-a-query-in-two-minutes/

Hope this helps.

Coda