I’ve had several people ask me lately about encrypting data in .NET. I’m not sure why the question has come up a lot recently, but it’s definitely something good to know if you have any sensitive data that needs to be stored. .NET provides two main encryption roads that you can travel down including symmetric encryption and asymmetric encryption. Symmetric encryption relies upon a private key to encrypt and decrypt while asymmetric encryption relies upon a public key to encrypt and a private key to decrypt. Symmetric encryption provides the best performance while asymmetric encryption provides the best security in situations where keys need to be exchanged between different parties. If you need to encrypt and decrypt data directly within an application symmetric encryption works fine as long as other prying eyes can’t get their hands on the private key (or your source code).
I have a fairly straightforward encryption/decryption class named Encryptor that I use when I need to perform symmetric encryption in my web applications. The class relies upon a symmetric algorithm called Rijndael that can be used to encrypt and decrypt data.
While I’m not going to provide a detailed discussion of what the class does I’m happy to post it here for anyone who needs that type of functionality. Keep in mind that you’ll need to update the password and salt values to whatever you need to use in your applications and should consider dynamically grabbing the password from a secured data store as opposed to hard-coding it in the source code (especially if you’ll be shipping the assembly…people can disassemble it using tools like Reflector). The salt acts as a type of junk data that is used in constructing the password and can also be used to pad encrypted data with bogus bytes so that hackers don’t know which part of the data is valid and which part is junk.
using System;
using System.IO;
using System.Security.Cryptography;
namespace YourApp.Model.Helpers {
internal class Encryptor
{
internal static string Decrypt(string cipherText)
{
byte[] cipherBytes = Convert.FromBase64String(cipherText);
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_Pwd, _Salt);
byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));
return System.Text.Encoding.Unicode.GetString(decryptedData);
}
private static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV) {
MemoryStream ms = new MemoryStream();
CryptoStream cs = null;
try {
Rijndael alg = Rijndael.Create();
alg.Key = Key;
alg.IV = IV;
cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherData, 0, cipherData.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
catch {
return null;
}
finally {
cs.Close();
}
}
public static string Encrypt(string clearText)
{
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_Pwd, _Salt);
byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
return Convert.ToBase64String(encryptedData);
}
private static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
{
MemoryStream ms = new MemoryStream();
CryptoStream cs = null;
try
{
Rijndael alg = Rijndael.Create();
alg.Key = Key;
alg.IV = IV;
cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(clearData, 0, clearData.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
catch
{
return null;
}
finally
{
cs.Close();
}
}
static string _Pwd = "Your_Password_Goes_Here"; //Be careful storing this in code unless it’s secured and not distributed
static byte[] _Salt = new byte[] {0x45, 0xF1, 0x61, 0x6e, 0x20, 0x00, 0x65, 0x64, 0x76, 0x65, 0x64, 0x03, 0x76};
}
}
To use the class to encrypt data (and get back a Base64 encoded string) the following code can be written:
string creditCardNumber = Encryptor.Encrypt(cust.CreditCardNumber);