Simple AES byte encryption and decryption routines in C#

I was looking for some simple examples of using AES symmetric encryption to encrypt and decrypt data in C#. Though there are some very helpful resources out there, what I needed were basic routines that:
– Take clear text and key as byte arrays and return encrypted text as a byte array.
– Take encrypted text and key as byte arrays and return clear text as a byte array.

The most informative resources I found were:
.NET Security blog: Generating a key from a password.
This covers, and explains, the key generation code very well. I.e. how to convert a pass phrase into a secure key for symmetric encryption.
.NET documentation for the AESManaged class.
Describes available methods and has a complete AES example which disposes of object correctly.

Since neither reference had exactly what I needed, I combined elements from both to create the following example routines which encrypt and decrypt byte arrays, using an AES key size of 256:

using System.Security.Cryptography;
using System.IO;

private byte[] AESEncryptBytes(byte[] clearBytes, byte[] passBytes, byte[] saltBytes)
{
   byte[] encryptedBytes = null;

   // create a key from the password and salt, use 32K iterations – see note
   var key = new Rfc2898DeriveBytes(passBytes, saltBytes, 32768);

   // create an AES object
   using (Aes aes = new AesManaged())
   {
      // set the key size to 256
      aes.KeySize = 256;
      aes.Key = key.GetBytes(aes.KeySize / 8);
      aes.IV = key.GetBytes(aes.BlockSize / 8);
      using (MemoryStream ms = new MemoryStream())
      {
          using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(),
CryptoStreamMode.Write))
{
             cs.Write(clearBytes, 0, clearBytes.Length);
             cs.Close();
          }
encryptedBytes = ms.ToArray();
       }
}
return encryptedBytes;
}

private byte[] AESDecryptBytes(byte[] cryptBytes, byte[] passBytes, byte[] saltBytes)
{
byte[] clearBytes = null;

    // create a key from the password and salt, use 32K iterations
    var key = new Rfc2898DeriveBytes(passBytes, saltBytes, 32768);

    using (Aes aes = new AesManaged())
{
// set the key size to 256
aes.KeySize = 256;
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);

        using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cryptBytes, 0, cryptBytes.Length);
cs.Close();
}
clearBytes = ms.ToArray();
}
}
return clearBytes;
}

Note the routines take a salt argument in addition to a password. Enforcing the use of a salt makes for a more secure password hash. The salt argument can be any data of at least 8 bytes. For testing you could hardcode it; how you generate it depends on your application requirements.

The key in the example above is created using Rfc2898DeriveBytes which implements Password-Based Key Derivation Function 2 (PBKDF2) – an RSA standard for secure key derivation. I’ve not seen any definitive guidelines on the number of iterations to use, but keep in mind the following:

– The initial standard, written in 2000, recommended 1000 iterations.
– More iterations make a key more secure, up to a point (i.e. millions).
– As CPU speeds get faster, the number of iterations need to increase to maintain the same level of security.
– Key generation takes noticeably longer as you increase the number of iterations.

In my example I somewhat arbitrarily chose 32768 iterations as the highest number that doesn’t cause much noticeable lag during key generation when the program is run.

Suppose you want to use these routines to encrypt/decrypt strings instead of byte arrays? You could change the routines directly, or write wrappers to convert the strings before calling them like this:

private string AESEncryptString(string clearText, string passText, string saltText)
{
byte[] clearBytes = Encoding.UTF8.GetBytes(clearText);
byte[] passBytes = Encoding.UTF8.GetBytes(passText);
byte[] saltBytes = Encoding.UTF8.GetBytes(saltText);

    return Convert.ToBase64String(AESEncryptBytes(clearBytes, passBytes, saltBytes));
}

private string AesDecryptString(string cryptText, string passText, string saltText)
{
byte[] cryptBytes = Convert.FromBase64String(cryptText);
byte[] passBytes = Encoding.UTF8.GetBytes(passText);
byte[] saltBytes = Encoding.UTF8.GetBytes(saltText);

    return Encoding.UTF8.GetString(AESDecryptBytes(cryptBytes, passBytes, saltBytes));
}

As an example, here’s a program I wrote that uses these routines, a password vault for Windows desktop called Keyache: https://github.com/gbowerman/KeyCache.


Advertisements
This entry was posted in Cryptography. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s