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); } } }