using Microsoft.Extensions.Configuration; using SPMS.Application.Interfaces; using SPMS.Domain.Common; using SPMS.Domain.Exceptions; namespace SPMS.Infrastructure.Security; public class E2EEService : IE2EEService { private const int RsaEncryptedKeySize = 256; private const int AesIvSize = 16; private const int MinPayloadSize = RsaEncryptedKeySize + AesIvSize; private readonly string _privateKeyPem; public E2EEService(IConfiguration configuration) { var keyPath = configuration["E2EE:PrivateKeyPath"]; if (!string.IsNullOrEmpty(keyPath) && File.Exists(keyPath)) { _privateKeyPem = File.ReadAllText(keyPath); } else { _privateKeyPem = configuration["E2EE:PrivateKeyPem"] ?? string.Empty; } } public E2EEDecryptResult DecryptRequest(byte[] encryptedPayload) { if (string.IsNullOrEmpty(_privateKeyPem)) throw SpmsException.BadRequest("E2EE 키가 설정되지 않았습니다."); if (encryptedPayload.Length < MinPayloadSize) throw SpmsException.BadRequest("잘못된 암호화 페이로드입니다."); var encryptedKey = encryptedPayload[..RsaEncryptedKeySize]; var iv = encryptedPayload[RsaEncryptedKeySize..(RsaEncryptedKeySize + AesIvSize)]; var encryptedBody = encryptedPayload[(RsaEncryptedKeySize + AesIvSize)..]; var aesKey = RsaEncryption.Decrypt(encryptedKey, _privateKeyPem); var decryptedBody = encryptedBody.Length > 0 ? AesEncryption.Decrypt(encryptedBody, aesKey, iv) : []; return new E2EEDecryptResult { DecryptedBody = decryptedBody, AesKey = aesKey }; } public byte[] EncryptResponse(byte[] plainResponse, byte[] aesKey) { var iv = AesEncryption.GenerateIv(); var encrypted = AesEncryption.Encrypt(plainResponse, aesKey, iv); var result = new byte[iv.Length + encrypted.Length]; Buffer.BlockCopy(iv, 0, result, 0, iv.Length); Buffer.BlockCopy(encrypted, 0, result, iv.Length, encrypted.Length); return result; } }