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);
}
}
}