SPMS_API/SPMS.Infrastructure/Security/CredentialEncryptionService.cs
seonkyu.kim 94e0b92780 feat: APNs/FCM 키 등록 및 조회 API 구현 (#48)
- APNs 키 등록 API (POST /v1/in/service/{serviceCode}/apns)
- FCM 키 등록 API (POST /v1/in/service/{serviceCode}/fcm)
- 키 정보 조회 API (POST /v1/in/service/{serviceCode}/credentials)
- AES-256 암호화로 민감 정보 저장
- 조회 시 메타 정보만 반환 (Private Key 미노출)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 00:28:47 +09:00

70 lines
2.2 KiB
C#

using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Configuration;
using SPMS.Application.Interfaces;
using SPMS.Domain.Common;
using SPMS.Domain.Exceptions;
namespace SPMS.Infrastructure.Security;
public class CredentialEncryptionService : ICredentialEncryptionService
{
private readonly byte[] _key;
public CredentialEncryptionService(IConfiguration configuration)
{
var keyBase64 = configuration["CredentialEncryption:Key"];
if (string.IsNullOrEmpty(keyBase64))
{
throw new InvalidOperationException("CredentialEncryption:Key is not configured.");
}
_key = Convert.FromBase64String(keyBase64);
if (_key.Length != 32)
{
throw new InvalidOperationException("CredentialEncryption:Key must be 32 bytes (256 bits).");
}
}
public string Encrypt(string plainText)
{
if (string.IsNullOrEmpty(plainText))
return string.Empty;
var iv = AesEncryption.GenerateIv();
var plainBytes = Encoding.UTF8.GetBytes(plainText);
var encryptedBytes = AesEncryption.Encrypt(plainBytes, _key, iv);
var result = new byte[iv.Length + encryptedBytes.Length];
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
Buffer.BlockCopy(encryptedBytes, 0, result, iv.Length, encryptedBytes.Length);
return Convert.ToBase64String(result);
}
public string Decrypt(string encryptedText)
{
if (string.IsNullOrEmpty(encryptedText))
return string.Empty;
try
{
var encryptedData = Convert.FromBase64String(encryptedText);
if (encryptedData.Length < 16)
{
throw new SpmsException(ErrorCodes.DecryptionFailed, "Invalid encrypted data.", 500);
}
var iv = encryptedData[..16];
var ciphertext = encryptedData[16..];
var decryptedBytes = AesEncryption.Decrypt(ciphertext, _key, iv);
return Encoding.UTF8.GetString(decryptedBytes);
}
catch (CryptographicException)
{
throw new SpmsException(ErrorCodes.DecryptionFailed, "Failed to decrypt credentials.", 500);
}
}
}