Files
2025-12-12 15:40:34 -03:00

78 lines
2.4 KiB
C#

using System.Security.Cryptography;
using System.Text;
using GestorFacturas.API.Services.Interfaces;
namespace GestorFacturas.API.Services;
public class EncryptionService : IEncryptionService
{
private readonly string _key;
public EncryptionService(IConfiguration config)
{
// La clave debe venir del .env / appsettings
_key = config["EncryptionKey"] ?? throw new ArgumentNullException("EncryptionKey no configurada");
// Ajustar si la clave no tiene el tamaño correcto (AES-256 requiere 32 bytes)
// Aquí hacemos un hash SHA256 de la clave para asegurar que siempre tenga 32 bytes válidos
using var sha256 = SHA256.Create();
var keyBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(_key));
_key = Convert.ToBase64String(keyBytes);
}
public string Encrypt(string plainText)
{
if (string.IsNullOrEmpty(plainText)) return plainText;
var key = Convert.FromBase64String(_key);
using var aes = Aes.Create();
aes.Key = key;
aes.GenerateIV(); // Generar vector de inicialización aleatorio
using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using var ms = new MemoryStream();
// Escribir el IV al principio del stream (necesario para desencriptar)
ms.Write(aes.IV, 0, aes.IV.Length);
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
return Convert.ToBase64String(ms.ToArray());
}
public string Decrypt(string cipherText)
{
if (string.IsNullOrEmpty(cipherText)) return cipherText;
try
{
var fullCipher = Convert.FromBase64String(cipherText);
var key = Convert.FromBase64String(_key);
using var aes = Aes.Create();
aes.Key = key;
// Extraer el IV (los primeros 16 bytes)
var iv = new byte[16];
Array.Copy(fullCipher, 0, iv, 0, iv.Length);
aes.IV = iv;
using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using var ms = new MemoryStream(fullCipher, 16, fullCipher.Length - 16);
using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
using var sr = new StreamReader(cs);
return sr.ReadToEnd();
}
catch
{
// Si falla al desencriptar (ej. porque el dato viejo no estaba encriptado),
// devolvemos el texto original para no romper la app en la migración.
return cipherText;
}
}
}