AES In C# using BouncyCastle.Net
Sample class library implementing AES using Bouncy Castle (1.8.5)
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.
Bouncy Castle
Bouncy Castle Crypto APIs are lightweight crypto APIs for Java and C#. In this article we will look at using C# implementation of AES.
Implementation
Lets start using AES in our code. We would need to include following namespaces.
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security
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. Our wrapper is using following 2 variations of the transforms.
- AES/GCM/NoPadding (default)
- AES/CBC/PKCS7 - compatible with System.Security.AES
We will start by generating random IV using SecureRandom
provided by BouncyCastle.
var random = new SecureRandom();
var iv = random.GenerateSeed(AesIvSize);
We will then call CreateKeyParameters
helper method to create ICipherParameters
. CreateKeyParameters
would create appropriate key parameters to pass to initialise method of the cipher depending on current cipher mode.
var keyParameters = CreateKeyParameters(key, iv, GcmTagSize * 8);
We will now create cipher using CipherUtilities
helper of BouncyCastle
and initialise it with encryptMode and keyParameters
var cipher = CipherUtilities.GetCipher(_algorithm);
cipher.Init(true, keyParameters);
Convert plain text string to bytes and call DoFinal
method on cipher
object to encrypt data.
var plainTextData = Encoding.UTF8.GetBytes(plainText);
var cipherText = cipher.DoFinal(plainTextData);
We finally pack the data in a byte array along with IV, GCM tag size (depending on CipherMode) and convert to base64 string. IV/gcm tag size 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)
{
var random = new SecureRandom();
var iv = random.GenerateSeed(AesIvSize);
var keyParameters = CreateKeyParameters(key, iv, GcmTagSize * 8);
var cipher = CipherUtilities.GetCipher(_algorithm);
cipher.Init(true, keyParameters);
var plainTextData = Encoding.UTF8.GetBytes(plainText);
var cipherText = cipher.DoFinal(plainTextData);
return PackCipherData(cipherText, iv);
}
Decryption
Decrypt method works in conjunction with Encrypt method above, it accepts base64 encoded cipher text string and key. It unpacks base64 encoded string to get iv, gcm tag size if CipherMode is GCM and encrypted data bytes and performs decryption and returns plain text.
We will start by unpacking cipher text to get IV used to encrypt data, gcm tag size and encrypted data bytes and follow that by creating key parameters using helper method CreateKeyParameters
.
var (encryptedBytes, iv, tagSize) = UnpackCipherData(cipherText);
var keyParameters = CreateKeyParameters(key, iv, tagSize * 8);
We will follow that by creating cipher using CipherUtilities
helper of BouncyCastle
and initialise it with decryption mode and key parameters.
var cipher = CipherUtilities.GetCipher(_algorithm);
cipher.Init(false, keyParameters);
Call DoFinal
method on cipher
object to decrypt data.
var decryptedData = cipher.DoFinal(encryptedBytes);
And finally we convert decrypted bytes to UTF8 string and return to caller.
return Encoding.UTF8.GetString(decryptedData);
Complete code for the method is below
public string Decrypt(string cipherText, byte[] key)
{
var (encryptedBytes, iv, tagSize) = UnpackCipherData(cipherText);
var keyParameters = CreateKeyParameters(key, iv, tagSize * 8);
var cipher = CipherUtilities.GetCipher(_algorithm);
cipher.Init(false, keyParameters);
var decryptedData = cipher.DoFinal(encryptedBytes);
return Encoding.UTF8.GetString(decryptedData);
}
Complete code for the wrapper class that implements encryption and decryption using BouncyCastle Aes can be found at AesBcCrypto.cs. Unit tests for the wrapper class can be found at AesBcCryptoTests.cs. Complete project as class library along with tests is at CryptoSandbox.
References
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard http://www.bouncycastle.org/csharp/
Leave a Comment
Your email address will not be published. Required fields are marked *