Feedemy.KeyManagement
3.0.1
dotnet add package Feedemy.KeyManagement --version 3.0.1
NuGet\Install-Package Feedemy.KeyManagement -Version 3.0.1
<PackageReference Include="Feedemy.KeyManagement" Version="3.0.1" />
<PackageVersion Include="Feedemy.KeyManagement" Version="3.0.1" />
<PackageReference Include="Feedemy.KeyManagement" />
paket add Feedemy.KeyManagement --version 3.0.1
#r "nuget: Feedemy.KeyManagement, 3.0.1"
#:package Feedemy.KeyManagement@3.0.1
#addin nuget:?package=Feedemy.KeyManagement&version=3.0.1
#tool nuget:?package=Feedemy.KeyManagement&version=3.0.1
Feedemy.KeyManagement
Enterprise-grade key management library for .NET applications.
Features
- Automatic Key Rotation - Background service with configurable intervals
- Versioned Encryption - Auto-decryption with version detection
- Asymmetric Keys - RSA (2048/3072/4096) and ECDSA (P-256/P-384/P-521)
- Multi-Platform Storage - Windows DPAPI, Linux Keyring, Azure Key Vault
- Distributed Caching - Redis with pub/sub invalidation
- Database Persistence - SQL Server, PostgreSQL, and SQLite
- Health Monitoring - ASP.NET Core health checks
- Fallback Storage - Multi-provider redundancy
- Audit Trail - Complete compliance logging
- Roslyn Analyzers - 48 compile-time security rules
Installation
dotnet add package Feedemy.KeyManagement
# Persistence (choose one)
dotnet add package Feedemy.KeyManagement.Providers.EntityFramework # SQL Server
dotnet add package Feedemy.KeyManagement.Providers.Npgsql # PostgreSQL
dotnet add package Feedemy.KeyManagement.Providers.Sqlite # SQLite (dev/testing)
# Optional
dotnet add package Feedemy.KeyManagement.Analyzers
Quick Start
Development Setup
using Feedemy.KeyManagement.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyManagement(options =>
{
options.EnableAutoRotation = true;
options.RotationCheckInterval = TimeSpan.FromHours(6);
options.DefaultRotationDays = 90;
});
var app = builder.Build();
app.Run();
Production Setup
builder.Services.AddKeyManagement(options =>
{
options.EnableAutoRotation = true;
options.RotationCheckInterval = TimeSpan.FromHours(6);
// Auto-initialization
options.Initialization.EnableAutoInitialization = true;
options.Initialization.ExternalKeysJsonPath = "keys.json";
})
.WithAzureKeyStorage("https://your-vault.vault.azure.net/")
.WithRedisCache("localhost:6379")
.WithSqlServerMetadata("Server=localhost;Database=KeyManagement;...");
builder.Services.AddHealthChecks()
.AddKeyManagementHealthCheck();
Basic Usage
public class MyService
{
private readonly IKeyManagementService _keyService;
private readonly IKeyManagementAdminService _adminService;
// Create a key
public async Task CreateKeyAsync()
{
await _adminService.CreateKeyAsync(new CreateKeyRequest
{
KeyName = "MyEncryptionKey",
AutoGenerate = true,
KeySize = 32,
RotationIntervalDays = 90,
CreatedBy = "Admin"
});
}
// Retrieve a key (cached - sub-millisecond)
public async Task<byte[]> GetKeyAsync()
{
return await _keyService.RetrieveKeyAsync("MyEncryptionKey");
}
// Check health
public async Task<KeyHealthStatus> GetHealthAsync()
{
var health = await _keyService.GetKeyHealthAsync("MyEncryptionKey");
return health.Status;
}
}
Key Initialization
Define keys in keys.json for auto-generation on first run:
{
"Keys": [
{
"KeyName": "EncryptionKey",
"KeyType": "Symmetric",
"RotationIntervalDays": 90,
"Category": "MasterKey"
},
{
"KeyName": "JwtSigningKey",
"KeyType": "RSA",
"KeySize": 2048,
"RotationIntervalDays": 180,
"Category": "Signing"
}
]
}
Asymmetric Keys
// Sign data
var signature = await _asymmetricOps.SignAsync(
"JwtSigningKey",
data,
HashAlgorithmName.SHA256);
// Verify signature
var isValid = await _asymmetricOps.VerifyAsync(
"JwtSigningKey",
data,
signature,
HashAlgorithmName.SHA256);
// Get public key for external use
var publicKeyPem = await _asymmetricOps.GetPublicKeyPemAsync("JwtSigningKey");
Performance
| Operation | Mean | Notes |
|---|---|---|
| RetrieveKey (cached) | < 1 μs | L1 cache hit |
| RetrieveKey (cache miss) | ~12 ms | Database + storage |
| Sign (RSA-2048) | ~1.2 ms | |
| Verify (RSA-2048) | ~0.15 ms | |
| Sign (ECDSA P-256) | ~0.35 ms | |
| Verify (ECDSA P-256) | ~0.12 ms |
Packages
| Package | Description |
|---|---|
Feedemy.KeyManagement |
Core library |
Feedemy.KeyManagement.Providers.EntityFramework |
SQL Server persistence |
Feedemy.KeyManagement.Providers.Npgsql |
PostgreSQL persistence |
Feedemy.KeyManagement.Providers.Sqlite |
SQLite persistence (dev/testing) |
Feedemy.KeyManagement.Analyzers |
Roslyn analyzers |
Documentation
Detailed documentation available in docs/partial/:
README_CORE.md- API referenceREADME_CONFIG.md- Configuration optionsREADME_STORAGE.md- Storage providersREADME_PERSISTENCE.md- Database setupREADME_CACHE.md- Caching architectureREADME_INIT.md- Initialization guideREADME_BACKGROUND.md- Background servicesREADME_EXTENSIONS.md- DI setup
License
This project is dual-licensed:
- MIT License - Free for all use cases including commercial
- Commercial License - For enterprise support, SLA, and priority features
| Use Case | License | Cost |
|---|---|---|
| Personal projects | MIT | Free |
| Open source projects | MIT | Free |
| Commercial products | MIT | Free |
| Enterprise support & SLA | Commercial | Paid |
Commercial inquiries: licensing@feedemy.com
Support
Copyright (c) 2025 Feedemy
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Azure.Identity (>= 1.18.0)
- Azure.Security.KeyVault.Secrets (>= 4.9.0)
- Microsoft.Data.SqlClient (>= 6.1.4)
- Microsoft.Data.Sqlite (>= 10.0.3)
- Microsoft.EntityFrameworkCore.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Caching.Memory (>= 10.0.3)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.3)
- Microsoft.Extensions.Hosting (>= 10.0.3)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Options (>= 10.0.3)
- OpenTelemetry.Api (>= 1.15.0)
- Polly (>= 8.6.5)
- StackExchange.Redis (>= 2.11.8)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Feedemy.KeyManagement:
| Package | Downloads |
|---|---|
|
Feedemy.KeyManagement.Providers.Npgsql
PostgreSQL (Npgsql) persistence provider for Feedemy.KeyManagement. Provides PostgreSQL storage for key metadata, versions, and audit logs with migrations support. Platform-independent alternative to SQL Server. |
|
|
Feedemy.KeyManagement.Providers.EntityFramework
Entity Framework Core persistence provider for Feedemy.KeyManagement. Provides SQL Server storage for key metadata, versions, and audit logs with migrations support. Fully tested with 56/56 integration tests passing. |
|
|
Feedemy.KeyManagement.Providers.Sqlite
SQLite persistence provider for Feedemy.KeyManagement. Provides lightweight, file-based storage for key metadata, versions, and audit logs. Ideal for development, testing, and single-server deployments. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v3.0.0 - Major Security, Performance & Stability Release
SECURITY (CRITICAL):
- Fixed SQL injection in PostgreSQL DatabaseMigrator (parameterized queries via NpgsqlParameter)
- Fixed plaintext Azure credential storage on Linux (AES-256-GCM encryption with machine-derived key)
- AES-GCM AAD bypass mitigation (AllowLegacyNoAadDecryption option, default false)
- DPAPI application-specific entropy ("Feedemy.KeyManagement.v1") with legacy auto-migration
- Linux per-installation random salt with .salt.bak backup/recovery chain
- Linux key re-encryption safety: write-read-verify with FixedTimeEquals, .migrating transactional backup
- Linux RetrieveKeyAsync TOCTOU fix (File.Exists moved inside lock)
- Credential JSON secure deletion after import (random-overwrite + File.Delete)
- CryptographicOperations.ZeroMemory throughout all sensitive byte array paths (12+ locations)
- IDisposable for WindowsDpapiStorageProvider, FallbackStorageProvider, MasterKeyProvider
PERFORMANCE:
- MasterKeyProvider in-memory cache with 5-min TTL (eliminates 2 IO round-trips per decryption)
- MasterKeyProvider.InvalidateCache() called after master key rotation for cache coherence
- Source-generated logging ([LoggerMessage]) for retrieval hot path
- TagList zero-allocation telemetry, Span-based IsEncryptedFormat detection
- Prefix-based cache pattern removal fast path (bypasses regex for simple patterns)
- Health check response caching (30s TTL with SemaphoreSlim double-check)
- RandomNumberGenerator.Fill / SHA256.HashData static APIs (no instance allocation)
- RegexOptions.None instead of Compiled (prevents assembly leak)
- Volatile.Read for FallbackStorageProvider._consecutiveFailures (prevents torn reads)
- Atomic RetrievalLockEntry.Dispose via Interlocked.CompareExchange
- Static eviction callback in KeyCacheService (eliminates closure allocation)
FIXED:
- Startup crash risks shifted behind DI build (ConfigurationValidationHostedService)
- Background services opt-in by default (EnableAutoRotation, EnableCacheInvalidationListener, EnableFallbackSync)
- CacheInvalidationListener resiliency with bounded retry and exponential backoff
- Double pub/sub removed from InvalidateAllVersionsAsync
- Startup ordering fixed for ServicesStartConcurrently=true
- UseAzureDefaults production safety: metadata provider validation enforced
- Rollback log level: successful rollback now logs Warning instead of Critical
- ConfigurationEnumMappings default cases now throw ArgumentOutOfRangeException
- Fire-and-forget defensive copy in FallbackStorageProvider.SyncToFallbackAsync
BREAKING CHANGES:
- OperationResult<T> now immutable (init-only properties), Warnings is IReadOnlyList<string>
- IKeyMetadataRepository has new required members (ExistsIncludingInactiveAsync, GetByKeyNameAsync)
- IMasterKeyProvider has new InvalidateCache() method (custom implementations must add it)
- MasterKeyProvider now implements IDisposable
- Background services opt-in by default
- UseAzureDefaults() requires persistent metadata provider
- GetByNameAsync/ExistsAsync targets active records by default
- See CHANGELOG.md and docs/MIGRATION_GUIDE.md for full migration guide