isn/src/isnd/Helpers/ApiKeyProtector.cs
2026-07-05 21:44:49 +01:00

82 lines
2.2 KiB
C#

using System;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.DataProtection;
namespace isnd.Helpers
{
public static class ApiKeyProtector
{
private const byte LegacyDelta = 145;
public static string TryUnprotectKey(IDataProtector protector, string protectedValue)
{
if (string.IsNullOrWhiteSpace(protectedValue))
{
return protectedValue;
}
if (TryUnprotect(protector, protectedValue, out var unprotected))
{
return unprotected;
}
if (TryUnprotectLegacy(protectedValue, out unprotected))
{
return unprotected;
}
return protectedValue;
}
private static bool TryUnprotect(IDataProtector protector, string protectedValue, out string unprotected)
{
try
{
unprotected = protector.Unprotect(protectedValue);
return true;
}
catch (CryptographicException)
{
unprotected = null;
return false;
}
catch (FormatException)
{
unprotected = null;
return false;
}
}
private static bool TryUnprotectLegacy(string protectedValue, out string unprotected)
{
try
{
unprotected = UnprotectLegacy(protectedValue);
return true;
}
catch (FormatException)
{
unprotected = null;
return false;
}
}
public static string UnprotectLegacy(string protectedValue)
{
if (string.IsNullOrWhiteSpace(protectedValue))
{
return protectedValue;
}
var bytes = Convert.FromBase64String(protectedValue);
var unprotectedBytes = new byte[bytes.Length];
for (var index = 0; index < bytes.Length; index++)
{
unprotectedBytes[index] = (byte)(bytes[index] ^ LegacyDelta);
}
return Encoding.UTF8.GetString(unprotectedBytes);
}
}
}