Simple Cryptography Block

I was looking around for a piece of code which would take a string and encrypt it into a Base64 encoded string such that I could later decrypt the string and obtain the message.  This was to be used in a confirmation email.  The message being urlencoded onto a confirmation url that the user could click and verify his email address was correct, or to redirect to a password setup page.  I found some examples in MSDN, but none did quite what I wanted.  I also wanted to use the key from the machineKey section of web.config.

I came up with this and thought others might find some use for it.

using System;
using System.Text;
using System.Security.Cryptography;
using System.Web.Configuration;
using System.IO;
using System.Configuration;

namespace SodaBlue.Utility
{
  public static class Cryptography
  {
    public static string EncryptAESToBase64(string dataToEncrypt)
    {
      //Get the decryption key from the machine key section of the web.config
      MachineKeySection machineKey = (MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey");
      string key = machineKey.DecryptionKey;
      byte[] keyBytes = UTF8Encoding.UTF8.GetBytes(key);
      Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, keyBytes, 1000);

      // Use the AES managed encryption provider
      AesManaged encryptor = new AesManaged();
      encryptor.Key = rfc.GetBytes(16);
      encryptor.IV = rfc.GetBytes(16);

      using (MemoryStream ms = new MemoryStream())
      {
        using (CryptoStream encrypt = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
        {
          byte[] dataBytes = new UTF8Encoding(false).GetBytes(dataToEncrypt);
          encrypt.Write(dataBytes, 0, dataBytes.Length);
          encrypt.FlushFinalBlock();
          encrypt.Close();
          return Convert.ToBase64String(ms.ToArray());
        }
      }
    }

    public static string DecryptAESFromBase64(string dataToDeCrypt)
    {
      //Get the decryption key from the machine key section of the web.config
      MachineKeySection machineKey = (MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey");
      string key = machineKey.DecryptionKey;
      byte[] keyBytes = new UTF8Encoding(false).GetBytes(key);
      Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(key, keyBytes, 1000);

      AesManaged decryptor = new AesManaged();
      decryptor.Key = rfc.GetBytes(16);
      decryptor.IV = rfc.GetBytes(16);

      using (MemoryStream ms = new MemoryStream())
      {
        using (CryptoStream decrypt = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
        {
          byte[] dataBytes = Convert.FromBase64String(dataToDeCrypt);
          decrypt.Write(dataBytes, 0, dataBytes.Length);
          decrypt.FlushFinalBlock();
          decrypt.Close();

          return new UTF8Encoding(false).GetString(ms.ToArray());
        }
      }
    }

  }
}

And a simple unit test to validate we can encrypt and decrypt

using System;
using NUnit.Framework;
using sbCommunity.Core.Infrastructure;

namespace sbCommunity.UnitTests
{
  [TestFixture]
  public class CryptographyTest
  {
    [Test]
    public void TestEncrypt()
    {
      const string cTest = "Now is the time for all good men to come to the aid of our countries";
      string encrypted = Cryptography.EncryptAESToBase64(cTest);
      string decrypted = Cryptography.DecryptAESFromBase64(encrypted);
      Assert.AreEqual(cTest, decrypted);
    }
  }
}
Published Saturday, October 25, 2008 2:23 PM by sodablue
Filed under: , ,

Comments

# re: Simple Cryptography Block

Sunday, October 26, 2008 11:33 PM by Kishan

There are some uncomplete lines. Kindly put some linebreak so as to see them. BTW your article is very nice and helpful.

# re: Simple Cryptography Block

Friday, January 23, 2009 10:31 AM by Mike

I have some data that has been encrypted using the encryption/decription key specified in the decryptionKey attribute of the machineKey config section.

The encryption was done via the Membership provider. I'd like to be able to decrypt the data (encrypted using this key) using just the cryptography assemblies (and with no refernce to the membership provider).

I won't explain why I don't want to use the Membership provider (I know I can get that to work).

# re: Simple Cryptography Block

Tuesday, May 12, 2009 6:41 PM by Steven

Very useful, Excelent!!!

Thanks.

# re: Simple Cryptography Block

Friday, January 08, 2010 5:17 PM by mamu

Great post, explains it all. As i came here after extensive search on MSDN. I would to share one thing that i found could be improved is. Rfc2898DeriveBytes could be replaced with PasswordDeriveBytes Class as it's intended for password.

Leave a Comment

(required) 
(required) 
(optional)
(required)