using System.Buffers.Binary;
using System.Security.Cryptography;
public static class Program
public static void Main()
string password = "very secure password";
using var aesObj = new AesGcmService(password);
string plain = "This is a test message.";
Console.WriteLine($"Plain: \"{plain}\"");
string enc = "jT4z6TBGQrlhnbOaI65MWiKVYhgGKRlQsZoJUgR6vTueuAvZQq8IiZPnVxOb+w==";
string dec = aesObj.Decrypt(enc);
Console.WriteLine($"Decrypted: \"{dec}\"");
public class AesGcmService : IDisposable
private readonly AesGcm _aes;
public AesGcmService(string password)
byte[] key = Encoding.UTF8.GetBytes("tokopedia1234567");
Console.WriteLine($"key: \"{key}\"");
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;
Console.WriteLine($"nonceSize: \"{nonceSize}\"");
Console.WriteLine($"tagSize: \"{tagSize}\"");
Console.WriteLine($"cipherSize: \"{cipherSize}\"");
int encryptedDataLength = nonceSize + tagSize + cipherSize;
Span<byte> encryptedData = encryptedDataLength < 1024 ? stackalloc byte[encryptedDataLength] : new byte[encryptedDataLength].AsSpan();
Console.WriteLine($"encryptedDataLength: \"{encryptedDataLength}\"");
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(0, 1), nonceSize);
return Convert.ToBase64String(encryptedData);
public string Decrypt(string cipher)
Console.WriteLine("Decrypt");
Span<byte> encryptedData = Convert.FromBase64String(cipher).AsSpan();
Console.WriteLine($"encryptedData: \"{encryptedData.Length}\"");
int nonceSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(0, 16));
Console.WriteLine($"nonceSize: \"{nonceSize}\"");
int tagSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(nonceSize, 2));
Console.WriteLine($"tagSize: \"{tagSize}\"");
int cipherSize = encryptedData.Length - 4 - nonceSize - 4 - tagSize;
Console.WriteLine($"cipherSize: \"{cipherSize}\"");
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);