Securing Query Strings with SecureQueryString 2.0
By Tim Shakarian ASP.NET MVP
Published: 11/17/2004
Reader Level: Beginner Intermediate
Rated: 5.00 by 2 member(s).
Tell a Friend
Rate this Article
Printable Version
Discuss in the Forums

Securing Query Strings with SecureQueryString 2.0

Almost a year ago I wrote an article about securing query strings. With that article I released the free component: SecureQueryString 1.0. If you haven’t already, I highly recommend that you take the time to read this article to get an overview as well as important guidance on usage. Today I have officially released SecureQueryString 2.0. In this article I will focus on the new things that you can do in 2.0.

Sample code can be downloaded here.

What’s new?

Version 1.0 included basic encryption functionality as well as query string expiration. Here’s what’s new in version 2.0:

  • Signs data to prevent tampering
  • Implements any SymmetricAlgorithm and HashAlgorithm to be used for cryptographic functions. Default is AES (RijndaelManaged) and MD5 (MD5CryptoServiceProvider) respectively.
  • Supports pluggable cryptographic interfaces for use with 3rd party cryptographic libraries (see ISymmetricCryptoProvider and IHashProvider for implementation details).
  • Rewritten from the ground up using TDD (Unit tests are included in the source download).
  • Complete reference documentation in CHM

While the API is not backwards compatible with version 1.0, it’s very similar. Here’s an example of a simple implementation:

SecureQueryString qs = new SecureQueryString(Key);
qs["SomeParameterName"] = SomeParameterValue;
Response.Redirect("Sample.aspx?x=" + HttpUtility.UrlEncode(qs.ToString()));

The only difference here is that the constructor requires that you pass a key in for the cryptographic functions. Retrieving the query string is similar:

SecureQueryString qs = new SecureQueryString(Key, Request["x"]);
SomeParameterValue = qs["SomeParameterName"];

Of course there are optional steps that exploit new features, but the basic functionality is virtually identical.

Signing

In version 1.0, tampering was theoretically because someone could modify the encrypted information. While this is highly unlikely unless the attacker cracked your key, there are methods that would allow the attacker to at least corrupt the query string. Signing via a hash algorithm (i.e. MD5) makes it virtually impossible for an attacker to manipulate the data within a query string. The downside to signing is that it makes an already bloated query string even larger. Fortunately this version supports any hash algorithm for signing (more on this later), so you can choose to use a weaker algorithm to reduce the payload.

Flexible cryptography

By default the AES algorithm is used for encrypting the query string, and MD5 is used for signing. With minimal effort you can use any .NET or 3rd party algorithm that inherits from System.Security.Cryptography.SymmetricAlgorithm for encrypting the query string. The same goes for any algorithm that inherits from System.Security.Cryptography.HashAlgorithm for signing the query string. The following example illustrates this by used the Triple DES and SHA1 algorithms:

/* First we must create a SymmetricAlgorithmProvider. .NET has a provider which creates the Triple DES object for us, so we’ll use that as well as the key we wish to use. */
SymmetricAlgorithmProvider 3DESProvider = new SymmetricAlgorithmProvider(
    TripleDESCryptoServiceProvider.Create(),
    Key
    );


/* Second, we’ll need a HashAlgorithmProvider. This is very similar to creating the SymmetricAlgorithmProvider for Triple DES. */
HashAlgorithmProvider sha1Provider = new HashAlgorithmProvider(
   SHA1CryptoServiceProvider.Create()
   );

/* Finally, we will create the SecureQueryString and instruct it to use our providers as opposed to the defaults. */
SecureQueryString qs = new SecureQueryString(Key);
qs.SymmetricCryptoProvider = 3DESProvider;
qs.HashProvider = sha1provider;

But what about 3rd party components that are not managed, such as a COM component? SecureQueryString 2.0 supports “pluggable” cryptography components via the ISymmetricCryptoProvider and IHashProvider interfaces. This means that you can create a managed wrapper that implements the appropriate interface for your unmanaged 3rd party components. Even if the component is managed, it may not inherit the respective .NET cryptography base classes. Some of you will notice that this loosely follows the Provider Design Pattern. This allows for extensibility without the need for “white box” code changes, or changes to the SecureQueryString source.

Let’s take a look at how simple this type of extensibility is. For the purposes of this example, we’ll use a mock hashing component called SuperSecureHash. This component is written in managed code, but it does not inherit from HashAlgorithm. SuperSecureHash has a method called GenerateHash(string), which takes a string and returns the hashed value as a byte[]. First we need to create a SuperSecureHashProvider  class, and implement IHashProvider. Then, we’ll need to fill out the required Hash(byte[]) method. Since IHashProvider.Hash takes a byte[], we’ll need to convert the input to a string so that we can pass it to SuperSecureHash.GenerateHash. To do this, we will use System.Encoding.Unicode.GetString.

public class SuperSecureHashProvider : IHashProvider {

   public byte[] Hash(byte[] buffer) {
        SuperSecureHash hasher = new SuperSecureHash();
        string hashString = System.Encoding.Unicode.GetString(buffer);
        return hasher.GenerateHash(hashString);
    }

}

Our provider for SuperSecureHash is complete. Now all we have to do is tell SecureQueryString to use our provider for hashing as opposed to the default:

SuperSecureHashProvider myHashProvider = new SuperSecureHashProvider();
SecureQueryString qs = new SecureQueryString(Key);
qs.HashProvider = myHashProvider;

That’s it! In just a few easy steps we’ve been able to plug-in our own hashing algorithm without touching any of the existing source code. If a new version of SecureQueryString comes out, we won’t have to worry about merging our custom code.

Conclusion

Version 2.0 of SecureQueryString gives us a lot more control over how we want to protect query strings. It’s also a nice example of TDD in practice. SecureQueryString is public domain and comes with the entire source including all unit tests. If you have any questions please post to this article’s forum so that everyone can benefit from the discussion. I will also post updates to this component to the forums, as well as my blog.



Marketplace
(Sponsored Links)
What are the green links?
   



 
Copyright © 2007 CMP Tech LLC |
Privacy Policy (4/10/06) | Your California Privacy Rights (4/10/06) | Terms of Service | Advertising Info | About Us | Help