using System.Security.Cryptography; using System.Text; using Aegis.Application.Abstractions; namespace Aegis.Repository.Crypto; public class AesGcmLabelCrypto : ILabelCrypto { private readonly ILabelKeyProvider _keys; private const int TagSize = 16; public AesGcmLabelCrypto(ILabelKeyProvider keys) => _keys = keys; public string DecryptDatastoreName( byte[] nameEnc, byte[] nameNonce, string lkKid, int lkVersion, string aad) { var key = _keys.GetLabelKey(lkKid, lkVersion); try { return DecryptUtf8AesGcm(key, nameEnc, nameNonce, Encoding.UTF8.GetBytes(aad)); } finally { CryptographicOperations.ZeroMemory(key); } } private static string DecryptUtf8AesGcm(byte[] key, byte[] cipherWithTag, byte[] nonce, byte[] aad) { if (cipherWithTag.Length < TagSize) throw new CryptographicException("Ciphertext inválido."); var cipherLen = cipherWithTag.Length - TagSize; var ciphertext = new byte[cipherLen]; var tag = new byte[TagSize]; Buffer.BlockCopy(cipherWithTag, 0, ciphertext, 0, cipherLen); Buffer.BlockCopy(cipherWithTag, cipherLen, tag, 0, TagSize); var plaintext = new byte[cipherLen]; using var aead = new AesGcm(key); aead.Decrypt(nonce, ciphertext, tag, plaintext, aad); var text = Encoding.UTF8.GetString(plaintext); CryptographicOperations.ZeroMemory(plaintext); CryptographicOperations.ZeroMemory(ciphertext); CryptographicOperations.ZeroMemory(tag); return text; } }