API key protection

This commit is contained in:
Paul Schneider 2026-07-05 21:18:37 +01:00
commit 38bb7e40ef
7 changed files with 143 additions and 19 deletions

View file

@ -12,7 +12,7 @@ namespace Isn
public static void LoadConfig()
{
FileInfo cfgSettingIf = new FileInfo(_configFileName);
FileInfo cfgSettingIf = new FileInfo(ConfigFileName);
if (cfgSettingIf.Exists)
{
var json = File.ReadAllText(cfgSettingIf.FullName);
@ -29,12 +29,13 @@ namespace Isn
{ "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
};
private static readonly string _configFileName =
Path.Combine(
Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile), ".isn"),
"config.json")
;
private static string ConfigDirectory =>
Environment.GetEnvironmentVariable("ISN_CONFIG_DIR")
?? Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
".isn");
private static string ConfigFileName => Path.Combine(ConfigDirectory, "config.json");
public const string push = "push";
static readonly OptionSet options = new OptionSet {

View file

@ -61,7 +61,7 @@ namespace Isn
}
public static void SaveConfig()
{
FileInfo cfgSettingIf = new FileInfo(_configFileName);
FileInfo cfgSettingIf = new FileInfo(ConfigFileName);
if (!cfgSettingIf.Directory.Exists) cfgSettingIf.Directory.Create();
File.WriteAllText(
cfgSettingIf.FullName,

View file

@ -31,12 +31,12 @@ namespace isnd.Controllers
try
{
var clientVersionId = Request.Headers["X-NuGet-Client-Version"];
string apiKey = Request.Headers["X-NuGet-ApiKey"][0];
string apiKey = Request.Headers["X-NuGet-ApiKey"].FirstOrDefault() ?? string.Empty;
ViewData["versionId"] = typeof(PackagesController).Assembly.FullName;
var files = new List<string>();
ViewData["files"] = files;
var clearkey = protector.Unprotect(apiKey);
var clearkey = ApiKeyProtector.UnprotectWithFallback(protector, apiKey);
var apikey = dbContext.ApiKeys.SingleOrDefault(k => k.Id == clearkey);
if (apikey == null)
{

View file

@ -0,0 +1,50 @@
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 UnprotectWithFallback(IDataProtector protector, string protectedValue)
{
if (string.IsNullOrWhiteSpace(protectedValue))
{
return protectedValue;
}
try
{
return protector.Unprotect(protectedValue);
}
catch (CryptographicException)
{
return UnprotectLegacy(protectedValue);
}
catch (FormatException)
{
return UnprotectLegacy(protectedValue);
}
}
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);
}
}
}