- AesEncryption: AES-256-CBC 암호화/복호화 - RsaEncryption: RSA-2048 키 쌍 생성/암복호화 - E2EEService: 하이브리드 암복호화 (요청 복호화, 응답 암호화) - TimestampValidator: 타임스탬프 검증 (±30초) - SecureTransportAttribute: Action Filter (보안등급 3 엔드포인트용) - DI 등록: IE2EEService → E2EEService (Singleton) Closes #28
65 lines
2.1 KiB
C#
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;
|
|
}
|
|
}
|