Powered by Blogger.

Thursday, July 15, 2010

ASP.NET data encryption / decryption made easy

Creating a wrapper for the built-in encryption capabilities in the .NET framework.
DataEncryption

Introduction

This articles shows how to create a basic wrapper for encrypting and decrypting strings using existing built-in methods in the .NET framework that are by default not accessible.

Background

I had to reverse engineer script resource URLs (like ScriptResource.axd?d=WIkfIHx2pe1WhCNefMjMESVyFb1-lrFL...) for a script combining project, so I could actually put resource paths like System.Web.Forms.js instead of those long unfriendly URLs in the config files... One thing I noticed is that resource names are getting encrypted using the MachingKeySection class, and since all of those really useful methods are either declared as private or internal, I have decided to create a wrapper that would enable me to easily access all those functionalities.

Using the code

The code is pretty straightforward if you know what to look for in the .NET framework. First of all, we get the type of the class we are looking for. In this case, it's the MachineKeySection class which contains the EncryptOrDecryptData method we are looking for.
// This class is made public but the methods
// we requiere are made private or internal.
Type machineKeySection = typeof(System.Web.Configuration.MachineKeySection);
Now that we know the type, we can use Reflection to get a reference to the EncryptOrDecryptData method. This method is used for almost everything internally by the .NET framework. So now, we have the power to decrypt almost everything. Since the computer's machine key is used as the encryption key, we can only decrypt data what was encrypted on the same server.
// Get encryption / decryption method
// You can look up all the methods using Reflector
// or a simillar tool.
MethodInfo _EncDecMethod = machineKeySection.GetMethod("EncryptOrDecryptData",
BindingFlags.NonPublic | BindingFlags.Static, Type.DefaultBinder,
new[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) },
null);
Now that we have a reference to the encryption-decryption method, we can invoke it.
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, 
byte[] modifier, int start, int length)
  • bool fEncrypt - set to true if you want the data to be encrypted, or to false if you want the data to be decrypted.
  • byte[] buf - data that you want to encrypt or decrypt.
  • int length - Length of the data, usually just buf.length if you want to encrypt or decrypt the entire byte array.

Extending

If you require string encryption and decryption, then you could extend the functionalities of your class by adding two other methods. One for decrypting and one for encrypting data. Instead of passing in a byte array and converting it to a string and vice versa, you would only pass in a string and also get a string as the result.
Encryption example:
// Data we want to encrypt
string data = "Encrypt me";

// Convert strig to byte array
byte[] bytes = Encoding.UTF8.GetBytes(data);

// Invoke the encryption method.
byte[] encData = (byte[])_EncDecMethod.Invoke(null, 
new object[] { true, bytes, null, 0, bytes.Length });

// Ecnrypted string
string encData Convert.ToBase64String(encData);
The resulting string can now be copied to wherever you want and then copied back and decrypted. The decryption method is pretty much the same, just in reverse order. Both method implementations are included in the demo project.

Conclusion

This code is really useful if you are creating custom configuration files or if you have XML documents that contain sensitive data. By calling EncryptOrDecryptData directly, you can encrypt almost everything.

By Dejan Bozic

No comments:

Post a Comment

  ©Template by Dicas Blogger.

TOPO