using System.Buffers.Binary;
using System.Security.Cryptography;
public static class Program
public static void Main()
string password = "Vooo@EN77&&12345";
using var aesObj = new AesGcmService(password);
string plain = "This is a test message.";
Console.WriteLine($"Plain: \"{plain}\"");
string enc = aesObj.Encrypt(plain);
Console.WriteLine($"Encrypted: \"{enc}\"");
string dec = aesObj.Decrypt("DAAAAJct7mmLbNim9LjuDRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAA=");
Console.WriteLine($"Decrypted: \"{dec}\"");
public class AesGcmService : IDisposable
private readonly AesGcm _aes;
private readonly byte[] _key;
public AesGcmService(string password)
byte[] key = new Rfc2898DeriveBytes(password, new byte[8], 1000).GetBytes(16);
_key = new Rfc2898DeriveBytes(password, new byte[8], 1000).GetBytes(16);
public string Encrypt(string plain)
byte[] plainBytes = Encoding.UTF8.GetBytes(plain);
int nonceSize = AesGcm.NonceByteSizes.MaxSize;
int tagSize = AesGcm.TagByteSizes.MaxSize;
int cipherSize = plainBytes.Length;
int encryptedDataLength = 4 + nonceSize + 4 + tagSize + cipherSize;
Span<byte> encryptedData = encryptedDataLength < 1024 ? stackalloc byte[encryptedDataLength] : new byte[encryptedDataLength].AsSpan();
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(0, 4), nonceSize);
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4), tagSize);
var nonce = encryptedData.Slice(4, nonceSize);
var tag = encryptedData.Slice(4 + nonceSize + 4, tagSize);
var cipherBytes = encryptedData.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
RandomNumberGenerator.Fill(nonce);
Console.WriteLine("Key: " + BitConverter.ToString(_key));
Console.WriteLine("PlainBytes: " + BitConverter.ToString(plainBytes));
Console.WriteLine("cipherSize: "+ cipherSize);
Console.WriteLine("encryptedDataLength: "+ encryptedDataLength);
string encryptedDataHex = BitConverter.ToString(encryptedData.ToArray());
Console.WriteLine($"Encrypted Data: {encryptedDataHex}");
Console.WriteLine("Nonce: " + BitConverter.ToString(nonce.ToArray()));
Console.WriteLine("Tag: " + BitConverter.ToString(tag.ToArray()));
Console.WriteLine("CipherBytes: " + BitConverter.ToString(cipherBytes.ToArray()));
_aes.Encrypt(nonce, plainBytes.AsSpan(), cipherBytes, tag);
Console.WriteLine($"Final Encrypted Data: {encryptedDataHex}");
return Convert.ToBase64String(encryptedData);
public string Decrypt(string cipher)
Span<byte> encryptedData = Convert.FromBase64String(cipher).AsSpan();
int nonceSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(0, 4));
int tagSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4));
int cipherSize = encryptedData.Length - 4 - nonceSize - 4 - tagSize;
var nonce = encryptedData.Slice(4, nonceSize);
var tag = encryptedData.Slice(4 + nonceSize + 4, tagSize);
var cipherBytes = encryptedData.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
Span<byte> plainBytes = cipherSize < 1024 ? stackalloc byte[cipherSize] : new byte[cipherSize];
_aes.Decrypt(nonce, cipherBytes, tag, plainBytes);
return Encoding.UTF8.GetString(plainBytes);