AES In C# using Microsoft Cryptography Library
Sample class library implementing AES using Microsoft’s Cryptography Library
Introduction
The Advanced Encryption Standard (AES), also known by its original name Rijndael is a specification for the encryption of electronic data. AES is a subset of the Rijndael block cipher developed by two Belgian cryptographers, Vincent Rijmen and Joan Daemen.
AES is a symmetric key algorithm, meaning the same key is used for both encryption and decryption of data.
AES In .NET Core
Aes represents the abstract base class from which all implementations of AES mush inherit. .NET also provides following implementations of AES at the time of writing.
- AesCng
- AesCryptoServiceProvider
- AesManaged
Aes abstract base class also provides static methods to create an instance of an implementation
- Create() - creates an instance AesCryptoServiceProvider by default
Implementation
Lets start using AES in our code. We would need to include System.Security.Cryptography
namespace.
using System.Security.Cryptography;
Encryption
Encrypt method accepts a string and key, encrypts string with key and random IV and returns a base64 encoded string packing IV and encrypted string. We will start by creating an instance of Aes and setting key, following will create the default implementation.
var aes = Aes.Create();
aes.Key = key;
Create Encryptor, using provided key and random IV (initialisation vector) this would create different cipher text using the same key
var cryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV);
Call internal method to encrypt string and create cipher text.
var cipherText = Encrypt(plainText, cryptoTransform);
We then pack the data in a byte array along with IV and convert to base64 string. IV would be required to decrypt data along with key if not packed with encrypted data.
Complete code for the method is below
public string Encrypt(string plainText, byte[] key)
{
using (var aes = Aes.Create())
{
aes.Key = key;
var cryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV);
var cipherText = Encrypt(plainText, cryptoTransform);
var data = new byte[cipherText.Length + aes.IV.Length + 1];
data[0] = (byte) aes.IV.Length;
Array.Copy(aes.IV, 0, data, 1, aes.IV.Length);
Array.Copy(cipherText, 0, data, aes.IV.Length + 1, cipherText.Length);
return Convert.ToBase64String(data);
}
}
Private method accepts data and encryptor, creates a memory stream
var memoryStream = new MemoryStream();
Initialises a crypto stream with memory stream, encryptor and write mode
var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write);
Creates a writer using crypto stream and call Write method to perform the encryption
var writer = new StreamWriter(cryptoStream);
writer.Write(data);
Complete code for the method is below
private byte[] Encrypt(string data, ICryptoTransform cryptoTransform)
{
if (data == null || data.Length <= 0)
throw new ArgumentException(nameof(data));
using (MemoryStream memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
using (var writer = new StreamWriter(cryptoStream))
{
writer.Write(data);
}
}
return memoryStream.ToArray();
}
}
Decryption
Decrypt method works in conjunction with Encrypt method above, it accepts base64 encoded string and key. It unpacks base64 encoded string to get iv and encrypted data and performs decryption and returns plain text. We will start by unpacking cipher text to get IV used to encrypt data and encrypted data and follow that by creating an instance of Aes and setting key and IV
var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
Create Decryptor,
var cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV);
Call internal method to decrypt data and return decrypted string
return Decrypt(encrypted, cryptoTransform);
Complete code for the method is below
public string Decrypt(string cipherText, byte[] key)
{
var data = Convert.FromBase64String(cipherText);
byte ivSize = data[0];
var iv = new byte[ivSize];
Array.Copy(data, 1, iv, 0, ivSize);
var encrypted = new byte[data.Length - ivSize - 1];
Array.Copy(data, ivSize + 1, encrypted, 0, encrypted.Length);
using (var aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
var cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV);
return Decrypt(encrypted, cryptoTransform);
}
}
Private method accepts data and decryptor, creates a memory stream using encrypted data
var memoryStream = new MemoryStream(data)
Initialises a crypto stream with memory stream, decryptor and read mode
var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read)
Creates a reader using crypto stream and call Read method to perform the decryption
var reader = new StreamReader(cryptoStream)
var decrypted = reader.ReadToEnd();
Complete code for the method is below
private string Decrypt(byte[] data, ICryptoTransform cryptoTransform)
{
if (data == null || data.Length <= 0)
throw new ArgumentException(nameof(data));
using (var memoryStream = new MemoryStream(data))
{
using (var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
{
using (var reader = new StreamReader(cryptoStream))
{
return reader.ReadToEnd();
}
}
}
}
Complete code for the wrapper class that implements encryption and decryption using Aes can be found at AesCrypto.cs. Unit tests for the wrapper class can be found at AesCryptoTests.cs. Complete project as class library along with tests is at CryptoSandbox.
References
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=netcore-2.2
Leave a Comment
Your email address will not be published. Required fields are marked *