Files
webhook-server/src/WebhookServer.Core/Storage/DpapiSecret.cs
T
justin 8ecfe84540 Initial WebhookServer implementation
Add the .NET 8 solution scaffolded against PLAN.md. Three projects share
WebhookServer.Core (models, auth, execution, storage, IPC, callbacks)
and WebhookServer.Service hosts an embedded Kestrel listener plus the
named-pipe admin server. WebhookServer.Gui is a thin MVVM client over
the pipe. Includes 25 unit tests covering HMAC verification, bearer
auth, IP allowlist parsing, arg-template rendering, DPAPI round-trip,
and the encrypt-on-save config store.

Install/uninstall PowerShell scripts default to LocalSystem and accept
a domain user or gMSA via -ServiceAccount.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:04:52 -04:00

31 lines
1.1 KiB
C#

using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
namespace WebhookServer.Core.Storage;
/// <summary>
/// DPAPI helpers using <see cref="DataProtectionScope.LocalMachine"/> so the same machine
/// (regardless of which Windows account the service runs under) can decrypt config secrets.
/// Wire format is plain base64 of the protected blob — caller wraps in JSON.
/// </summary>
[SupportedOSPlatform("windows")]
public static class DpapiSecret
{
public static string Protect(string plaintext)
{
if (string.IsNullOrEmpty(plaintext)) return "";
var bytes = Encoding.UTF8.GetBytes(plaintext);
var blob = ProtectedData.Protect(bytes, optionalEntropy: null, DataProtectionScope.LocalMachine);
return Convert.ToBase64String(blob);
}
public static string Unprotect(string base64)
{
if (string.IsNullOrEmpty(base64)) return "";
var blob = Convert.FromBase64String(base64);
var bytes = ProtectedData.Unprotect(blob, optionalEntropy: null, DataProtectionScope.LocalMachine);
return Encoding.UTF8.GetString(bytes);
}
}