Encryption is something that has fascinated me for years.  Some time ago, not knowing better, I designed my own cypher, which involving transferring bits and otherwise obfuscating clear text in a reversible fashion.  It was simply an intellectual exercise; the math of strong encryption is something I’ve not delved into deeply.

Symmetric encryption is where one uses the same key to encrypt and decrypt clear text or binaries.  The problem with symmetric encryption is one must determine how to pass a password securely between the sender and the receiver, something asymmetric encryption is able to solve.  I’m not delving into asymmetric encryption today.

.NET 4.x makes implementing symmetric encryption relatively painless, and also provides a way of making key generation from passwords more robust.

Below is a set of simple encryption object using static methods to implement symmetric encryption using Rijndael.  One thing I wanted to do was make it a bit more friendly to use and implement, so I created a settings object for the encryptor to take as an argument in its constructor.  This settings object would contain settings for the salt and initialization vector.  In addition, these settings could be set as strings.  The salt is converted to an array of bytes.  The IV is also converted to an array of bytes, but the encryptor uses the keymaking ability of the Rfc2898DeriveBytes objects within .NET to create a truly randomized IV.  The encryptor also uses this same functionality when generating a key out of the password when encrypting or decrypting.

So first let me introduce the settings object.


One thing I wanted to note was that the KeySize property is read only.  Also, even though it is available, the encryptor object doesn’t actually use it.  If you decide to, you can implement it your own way.  I kept things simple because a long key is best and I didn’t want to go off into the weeds dealing with validating key sizes.

You’ll notice there are default values for the seeds, key sizes, iterations, etc.  This allows you to instantiate the settings object and only make the changes you feel are necessary.  You should change your default values from what I have here for your own use.

Iterations is the number of operations used to generate a key.  Microsoft suggests a value of at least a thousand; I’ve used lower numbers here in this simple demonstration. This functionality allows one to generate a strong key based on a string, such as a password.  The encryptor object also generates an Initialization Vector using this functionality and has a separate setting, IViterations, which the settings object passes into the encryptor.

The settings object has some minor validation for the various properties.

Next is the actual encryptor, which has a constructor which has a single argument which allows the setting object to be passed as a parameter.


Notice that this object has existing default values for everything that the settings object would contain.  If you wanted to, you could create a default constructor (with no arguments) and the encryptor would still work.  However, the encryptor does not expose those properties which would allow you to properly configure it.

The two main methods of the encryptor are the ToBase64Encoded and FromBase64Encoded methods.  Encryption returns an array of bytes, which may be difficult to store in many cases.  Therefore I have chosen to convert binary results into text ones.  You may create your own methods to simply return an array of bytes for encrypted text or data.

It is in these two methods where the password is passed, along with the text to be encrypted or decrypted.  The password, as was mentioned earlier, is ran through the Rfc2898DeriveBytes object to create a secure key.

The BytesFromString method is used to generate an array of bytes for the salt.  The encryptor object makes this method available as a public service in case there was a need to convert any other text to an array of bytes.  This method takes two arguments, a string and an integer. The purpose of the integer is to set the size of the array of bytes to be returned.  If you set this value to 0 or less, you’ll receive the entire array of bytes.  If you set a value, you’ll receive an array of that size.  If the string is too small to supply a byte array requested, the array will be padded with 0x00’s.

Finally, it would be nice to put this encryptor into action.  If you create for yourself a console application, you can paste the above code into your console project and then replace your class Program object with the Main subroutine with the following:


You’ll notice I set up a password first.  This isn’t necessary. In fact, the password is the only thing that can change for an encryptor object once it is instantiated.

Then the settings object is created and a text seed for the IV and salt is set.  You may have noticed the @ sign.  This tells C# to ignore control characters (such as \n) and treate the values as literals.

The routine then creates an encryptor and encrypts text and displays it on the console.  It then reverses the process and compares it to the initial clear text.



Like this post? Share it!