As part of our implementation for the Union Bank Refund Process, we needed to build a secure channel for transferring sensitive transaction details from the Business to the Customer. To ensure confidentiality, integrity, and authenticity, we implemented AES encryption using the GCM (Galois/Counter Mode) — a modern and secure choice for authenticated encryption.
In this blog, I’ll walk you through how we’ve achieved this in C# with .NET Core, using the BouncyCastle cryptographic library.
Why AES-GCM?
- AES (Advanced Encryption Standard) is a widely adopted symmetric encryption algorithm.
- GCM (Galois/Counter Mode) adds integrity through authentication tags, preventing tampering.
- It's fast, secure, and ideal for real-time and financial applications like refunds.
Tech Stack
- Language: C# (.NET Core)
- Encryption Mode: AES-GCM
- Library: BouncyCastle
- Scenario: Encrypting/decrypting sensitive refund payloads between systems
Code. AES Encryption & Decryption Helper
using System;
using System.Text;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Digests;
public class AesEncryptionHelper
{
private const int KeyLengthBits = 256;
private const int SaltLengthBytes = 16;
private const int IvLengthBytes = 16;
private const int TagLengthBits = 128;
private const int Pbkdf2Iterations = 65536;
public string PasswordBasedEncAES(string plainText, string password)
{
byte[] salt = GetRandomBytes(SaltLengthBytes);
byte[] iv = GetRandomBytes(IvLengthBytes);
byte[] key = DeriveKey(password, salt, Pbkdf2Iterations, KeyLengthBits);
GcmBlockCipher cipher = new GcmBlockCipher(new Org.BouncyCastle.Crypto.Engines.AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(key), TagLengthBits, iv, null);
cipher.Init(true, parameters);
byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);
byte[] cipherText = new byte[cipher.GetOutputSize(inputBytes.Length)];
int len = cipher.ProcessBytes(inputBytes, 0, inputBytes.Length, cipherText, 0);
cipher.DoFinal(cipherText, len);
// Combine IV + CipherText + Salt
byte[] result = new byte[iv.Length + cipherText.Length + salt.Length];
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
Buffer.BlockCopy(cipherText, 0, result, iv.Length, cipherText.Length);
Buffer.BlockCopy(salt, 0, result, iv.Length + cipherText.Length, salt.Length);
return Convert.ToBase64String(result);
}
public string PasswordBasedDecryptAES(string cipherTextBase64, string password)
{
byte[] input = Convert.FromBase64String(cipherTextBase64);
byte[] iv = new byte[IvLengthBytes];
byte[] cipherText = new byte[input.Length - IvLengthBytes - SaltLengthBytes];
byte[] salt = new byte[SaltLengthBytes];
Buffer.BlockCopy(input, 0, iv, 0, iv.Length);
Buffer.BlockCopy(input, iv.Length, cipherText, 0, cipherText.Length);
Buffer.BlockCopy(input, iv.Length + cipherText.Length, salt, 0, salt.Length);
byte[] key = DeriveKey(password, salt, Pbkdf2Iterations, KeyLengthBits);
GcmBlockCipher cipher = new GcmBlockCipher(new Org.BouncyCastle.Crypto.Engines.AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(key), TagLengthBits, iv, null);
cipher.Init(false, parameters);
byte[] plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
int len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
cipher.DoFinal(plainText, len);
return Encoding.UTF8.GetString(plainText).TrimEnd('\0');
}
private byte[] DeriveKey(string password, byte[] salt,int Pbkdf2Iterations, int keyLengthBits)
{
var gen = new Pkcs5S2ParametersGenerator(new Sha256Digest());
gen.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt, Pbkdf2Iterations);
KeyParameter keyParam = (KeyParameter)gen.GenerateDerivedMacParameters(keyLengthBits);
return keyParam.GetKey();
}
private byte[] GetRandomBytes(int length)
{
byte[] bytes = new byte[length];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(bytes);
}
return bytes;
}
}

Join the conversation! Your thoughts help the community grow.