2026-07-05 21:18:37 +01:00
|
|
|
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;
|
|
|
|
|
|
2026-07-05 21:44:49 +01:00
|
|
|
public static string TryUnprotectKey(IDataProtector protector, string protectedValue)
|
2026-07-05 21:18:37 +01:00
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(protectedValue))
|
|
|
|
|
{
|
|
|
|
|
return protectedValue;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-05 21:44:49 +01:00
|
|
|
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)
|
|
|
|
|
{
|
2026-07-05 21:18:37 +01:00
|
|
|
try
|
|
|
|
|
{
|
2026-07-05 21:44:49 +01:00
|
|
|
unprotected = protector.Unprotect(protectedValue);
|
|
|
|
|
return true;
|
2026-07-05 21:18:37 +01:00
|
|
|
}
|
|
|
|
|
catch (CryptographicException)
|
|
|
|
|
{
|
2026-07-05 21:44:49 +01:00
|
|
|
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;
|
2026-07-05 21:18:37 +01:00
|
|
|
}
|
|
|
|
|
catch (FormatException)
|
|
|
|
|
{
|
2026-07-05 21:44:49 +01:00
|
|
|
unprotected = null;
|
|
|
|
|
return false;
|
2026-07-05 21:18:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|