namespace Application.Abstractions.Crypto;
///
/// Config 문자열 컬럼에 키 버전을 함께 담아 암호화 저장하는 헬퍼.
/// 별도 KeyVersion 컬럼이 없는 Config 특성상 "enc:v{version}:{Base64}" 자체 포맷을 사용한다.
/// 접두사가 없는 값은 레거시 평문으로 간주해 그대로 반환한다 (하위호환).
///
public static class EncryptedConfigValue
{
private const string Prefix = "enc:v";
/// 평문을 현재 키 버전으로 암호화해 버전 접두사 포맷으로 반환
public static string Protect(IFieldEncryptor encryptor, string plaintext)
{
ArgumentNullException.ThrowIfNull(encryptor);
return $"{Prefix}{encryptor.CurrentKeyVersion}:{encryptor.Encrypt(plaintext)}";
}
/// 버전 접두사 포맷 여부
public static bool IsProtected(string? value)
{
return value is not null && value.StartsWith(Prefix, StringComparison.Ordinal);
}
/// 버전 접두사 포맷이면 복호화, 아니면(레거시 평문) 그대로 반환
public static string Unprotect(IFieldEncryptor encryptor, string value)
{
ArgumentNullException.ThrowIfNull(encryptor);
ArgumentNullException.ThrowIfNull(value);
if (!IsProtected(value))
{
return value;
}
var rest = value.AsSpan(Prefix.Length);
var separator = rest.IndexOf(':');
if (separator <= 0 || !int.TryParse(rest[..separator], out var version))
{
throw new InvalidOperationException("암호화된 설정 값의 키 버전 형식이 올바르지 않습니다.");
}
return encryptor.Decrypt(rest[(separator + 1)..].ToString(), version);
}
}