AdysTech.CredentialManager
3.1.0
dotnet add package AdysTech.CredentialManager --version 3.1.0
NuGet\Install-Package AdysTech.CredentialManager -Version 3.1.0
<PackageReference Include="AdysTech.CredentialManager" Version="3.1.0" />
<PackageVersion Include="AdysTech.CredentialManager" Version="3.1.0" />
<PackageReference Include="AdysTech.CredentialManager" />
paket add AdysTech.CredentialManager --version 3.1.0
#r "nuget: AdysTech.CredentialManager, 3.1.0"
#:package AdysTech.CredentialManager@3.1.0
#addin nuget:?package=AdysTech.CredentialManager&version=3.1.0
#tool nuget:?package=AdysTech.CredentialManager&version=3.1.0
CredentialManager
A .NET library for storing and retrieving credentials from the Windows Credential Store.
Wraps the native CredWrite, CredRead, CredEnumerate, and CredDelete APIs via P/Invoke,
providing a safe managed interface for credential management in desktop applications, CLI tools,
and background services.
Features
- Save, retrieve, enumerate, and remove credentials from Windows Credential Store
- Prompt users for credentials via Windows UI dialog or console
- Store comments and custom attributes (JSON-serialized, up to 64 per credential)
- Configurable persistence (Session, LocalMachine, Enterprise)
- JIT-safe memory zeroing of credential buffers via
RtlZeroMemoryP/Invoke - Full nullable reference type annotations
- Source Link enabled for debugger integration
Target Frameworks
| Framework | Purpose |
|---|---|
| .NET 8.0 | Primary target, full analyzer coverage |
| .NET Standard 2.0 | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+, Mono, Unity) |
Installation
NuGet (recommended)
dotnet add package AdysTech.CredentialManager
Or in your .csproj:
<PackageReference Include="AdysTech.CredentialManager" Version="3.1.0" />
Project Reference
For local development or when building from source:
<ProjectReference Include="path/to/src/AdysTech.CredentialManager/AdysTech.CredentialManager.csproj" />
Quick Start
using System.Net;
using AdysTech.CredentialManager;
// Save
var cred = new NetworkCredential("user", "password", "domain");
CredentialManager.SaveCredentials("MyApp:api-token", cred);
// Retrieve
var stored = CredentialManager.GetCredentials("MyApp:api-token");
if (stored != null)
Console.WriteLine($"User: {stored.UserName}, Domain: {stored.Domain}");
// Remove
CredentialManager.RemoveCredentials("MyApp:api-token");
Integration Guide
Adding to Your Project
Install the NuGet package (see Installation above).
Add the using directive:
using AdysTech.CredentialManager;Use
CredentialManageras a static class — no instantiation needed.
Target Naming Convention
Use a consistent prefix for your target names to avoid collisions with other applications:
const string TargetPrefix = "MyApp:";
CredentialManager.SaveCredentials($"{TargetPrefix}api-key", cred);
CredentialManager.SaveCredentials($"{TargetPrefix}oauth-token", cred);
Typical Integration Pattern
public static class SecureStore
{
private const string Prefix = "MyApp:";
public static void StoreToken(string key, string token, string user = "token")
{
var cred = new NetworkCredential(user, token);
CredentialManager.SaveCredentials($"{Prefix}{key}", cred,
persistence: Persistence.LocalMachine);
}
public static string? GetToken(string key)
{
return CredentialManager.GetCredentials($"{Prefix}{key}")?.Password;
}
public static void RemoveToken(string key)
{
try { CredentialManager.RemoveCredentials($"{Prefix}{key}"); }
catch (CredentialAPIException) { /* not found — already removed */ }
}
}
Error Handling
All public methods throw ArgumentNullException for null parameters and CredentialAPIException
for Windows API failures. GetCredentials and GetICredential return null when the target
is not found (not an error).
try
{
CredentialManager.SaveCredentials("target", cred);
}
catch (CredentialAPIException ex)
{
// ex.Message — human-readable description
// ex.ApiName — Win32 function that failed (e.g. "CredWrite")
// ex.ErrorCode — Win32 error code
Console.Error.WriteLine($"{ex.ApiName} failed: {ex.Message} (error {ex.ErrorCode})");
}
Platform Considerations
This library is Windows-only (P/Invoke to advapi32.dll and credui.dll). For cross-platform
credential storage, use it behind an abstraction:
public interface ICredentialStore
{
void Save(string key, string user, string password);
NetworkCredential? Get(string key);
void Remove(string key);
}
Implement with CredentialManager on Windows and an alternative (e.g., libsecret/keyring)
on Linux/macOS.
API Reference
Static Methods on CredentialManager
| Method | Description |
|---|---|
SaveCredentials(target, credential, ...) |
Save a NetworkCredential to the store. Returns ICredential on success. |
GetCredentials(target, type) |
Retrieve as NetworkCredential. Returns null if not found. |
GetICredential(target, type) |
Retrieve as ICredential (includes comment, attributes, persistence). |
EnumerateCredentials(target?) |
List all credentials, optionally filtered by target prefix. |
EnumerateICredentials(target?) |
Same as above, returning ICredential objects. |
RemoveCredentials(target, type) |
Delete a credential from the store. |
PromptForCredentials(target, ...) |
Show the Windows credential dialog. |
PromptForCredentialsConsole(target) |
Console-based credential prompt. |
GetBasicAuthString(credential) |
Extension method: Base64-encode user:password for HTTP Basic Auth. |
ICredential Interface
ICredential exposes properties beyond NetworkCredential:
| Property | Type | Description |
|---|---|---|
TargetName |
string |
The target identifier |
UserName |
string? |
Username |
CredentialBlob |
string? |
Password or token |
Comment |
string? |
Comment (visible via API only, not in Windows UI) |
Persistence |
Persistence |
Storage scope |
Type |
CredentialType |
Generic or Windows (domain) |
Attributes |
IDictionary<string, Object>? |
JSON-serialized key-value pairs (max 64, 256 bytes each) |
LastWritten |
DateTime |
Last modification timestamp |
Persistence
| Value | Behavior |
|---|---|
Session |
Exists only for the current logon session, cleared on reboot |
LocalMachine |
(Default) Persisted locally, not synced to domain controllers |
Enterprise |
Persisted and synced to Active Directory domain controllers |
Attributes
Store structured metadata alongside credentials using JSON-serialized attributes:
var cred = (new NetworkCredential("user", "token")).ToICredential()!;
cred.TargetName = "MyApp:service";
cred.Attributes = new Dictionary<string, Object>(StringComparer.Ordinal)
{
{ "role", "admin" },
{ "expiresAt", DateTime.UtcNow.AddHours(1).ToString("o") },
{ "retryCount", 3 }
};
cred.SaveCredential();
// Reading back — attributes are returned as JsonElement
var stored = CredentialManager.GetICredential("MyApp:service");
var role = ((JsonElement)stored!.Attributes!["role"]).GetString();
var count = ((JsonElement)stored.Attributes["retryCount"]).GetInt32();
Constraints: each attribute value must serialize to 256 bytes or less, maximum 64 attributes per credential, attribute keys maximum 256 characters.
Upgrading from v2.x
BinaryFormatter Attributes
Legacy BinaryFormatter-encoded attributes can no longer be read. The BinaryFormatter compatibility layer has been removed entirely. Legacy attributes are silently skipped with a debug message. Re-save credentials to convert them to JSON format.
Attribute Type Changes
Attribute values are now JsonElement objects instead of the original .NET types:
// v2.x
var role = (string)cred.Attributes["role"];
// v3.x
var role = ((JsonElement)cred.Attributes["role"]).GetString();
// Complex types:
var info = ((JsonElement)cred.Attributes["info"]).Deserialize<MyType>();
Spelling Corrections
The misspelled Persistance enum, properties, and parameters have been corrected to
Persistence. Update all references accordingly.
Default Persistence
The default persistence changed from Enterprise to LocalMachine. If your application
relies on domain-replicated credentials, explicitly pass Persistence.Enterprise.
Security
- No BinaryFormatter — attribute serialization uses
System.Text.Jsonexclusively. BinaryFormatter was removed due to its critical deserialization vulnerability (CWE-502). - JIT-safe memory zeroing — native credential buffers are zeroed using
RtlZeroMemoryvia P/Invoke before being freed. The JIT cannot optimize away an external function call, unlikeMarshal.Copywith zero bytes. - Configurable persistence — credentials default to
LocalMachine(notEnterprise), preventing unintended replication across domain controllers. - Correct buffer sizes — credential UI prompts use the Windows-defined constants
CREDUI_MAX_USERNAME_LENGTH(513) andCREDUI_MAX_PASSWORD_LENGTH(256). - Static analysis — the library builds with zero warnings across 6 Roslyn analyzer suites: Microsoft.CodeAnalysis.NetAnalyzers, StyleCop, SecurityCodeScan, Roslynator, SonarAnalyzer, and Meziantou.Analyzer (~2,000+ combined rules).
Note:
CredentialBlobis a managedstring, which the GC may copy or retain in memory. For maximum security, keep credential objects short-lived and avoid caching password values.
Building
dotnet build -c Release
dotnet test -c Release
The project requires Windows for testing (credential store access via interactive logon session).
License
MIT — Copyright (c) 2016-2026 Adys Tech
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 8.0.5)
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (3)
Showing the top 3 popular GitHub repositories that depend on AdysTech.CredentialManager:
| Repository | Stars |
|---|---|
|
gitextensions/gitextensions
Git Extensions is a standalone UI tool for managing git repositories. It also integrates with Windows Explorer and Microsoft Visual Studio (2015/2017/2019).
|
|
|
goatcorp/FFXIVQuickLauncher
Custom launcher for FFXIV
|
|
|
ErikEJ/EFCorePowerTools
Entity Framework Core Power Tools - reverse engineering, migrations and model visualization in Visual Studio & CLI
|
| Version | Downloads | Last Updated |
|---|---|---|
| 3.1.0 | 2,643 | 2/27/2026 |
| 2.6.0 | 420,357 | 1/19/2022 |
| 2.5.0 | 66,265 | 11/10/2021 |
| 2.4.0 | 18,380 | 9/1/2021 |
| 2.3.0 | 278,884 | 12/20/2020 |
| 1.7.0 | 22,770 | 9/26/2018 |
| 1.6.0 | 1,760 | 9/25/2018 |
| 1.5.0 | 1,796 | 9/10/2018 |
| 1.4.5 | 1,885 | 8/22/2018 |
| 1.4.0 | 2,367 | 7/5/2018 |
| 1.3.0 | 2,388 | 6/25/2018 |
| 1.2.1 | 2,532 | 4/19/2018 |
v3.1.0: Spelling fix (Persistance→Persistence), BinaryFormatter fallback removed, 6 Roslyn analyzer suites (0 warnings), Source Link, demo app. See CHANGELOG.md.