Creating a wrapper for the built-in encryption capabilities in the .NET framework.
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 theMachingKeySection
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 theMachineKeySection
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 totrue
if you want the data to be encrypted, or tofalse
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 justbuf.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 callingEncryptOrDecryptData
directly, you can encrypt almost everything.By Dejan Bozic
No comments:
Post a Comment