- 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>
70 lines
2.2 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|