SPMS_API/SPMS.Infrastructure/Security/E2EEService.cs
SEAN 27f33f809b feat: E2EE 암호화 유틸리티 구현 (#28)
- AesEncryption: AES-256-CBC 암호화/복호화
- RsaEncryption: RSA-2048 키 쌍 생성/암복호화
- E2EEService: 하이브리드 암복호화 (요청 복호화, 응답 암호화)
- TimestampValidator: 타임스탬프 검증 (±30초)
- SecureTransportAttribute: Action Filter (보안등급 3 엔드포인트용)
- DI 등록: IE2EEService → E2EEService (Singleton)

Closes #28
2026-02-09 16:33:38 +09:00

65 lines
2.1 KiB
C#

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;
}
}