Lyo.KeyStore
1.0.0
dotnet add package Lyo.KeyStore --version 1.0.0
NuGet\Install-Package Lyo.KeyStore -Version 1.0.0
<PackageReference Include="Lyo.KeyStore" Version="1.0.0" />
<PackageVersion Include="Lyo.KeyStore" Version="1.0.0" />
<PackageReference Include="Lyo.KeyStore" />
paket add Lyo.KeyStore --version 1.0.0
#r "nuget: Lyo.KeyStore, 1.0.0"
#:package Lyo.KeyStore@1.0.0
#addin nuget:?package=Lyo.KeyStore&version=1.0.0
#tool nuget:?package=Lyo.KeyStore&version=1.0.0
Lyo.KeyStore
Key Encryption Key (KEK) storage and rotation contracts for Lyo.Encryption. Encryption services call into IKeyStore by keyId (and optional version string) so ciphertext can outlive a single key material rotation.
Vocabulary: the KEK lives in the store. Data Encryption Keys (DEKs) used by envelope / two-key flows are generated per operation by the encryption layer and are not persisted in the keystore—only the KEK that wraps them.
Examples
Register with DI
using Lyo.KeyStore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
// Unkeyed
services.AddLocalKeyStore(ks =>
{
ks.UpdateKeyFromString("app", configuration["Encryption:CurrentKek"]!);
});
// Keyed (pair with AddEncryptionServiceKeyed / addon *ServiceKeyed)
const string storeKey = "primary";
services.AddKeyedLocalKeyStore(storeKey, ks =>
{
ks.AddKeyFromString("app", "v1", configuration["Encryption:Kek:v1"]!);
ks.SetCurrentVersion("app", "v1");
});
Register with DI (2)
{
"Encryption": {
"CurrentKek": "replace-in-user-secrets",
"Kek": {
"v1": "versioned-secret"
}
}
}
IKeyStore at a glance
Versions are strings (for example "1", "2025-01", or opaque ids from an HSM). GetCurrentVersion returns the version used when callers omit an explicit version
on encrypt.
| Concern | Members |
|---|---|
| Read material | GetKey, GetKeyAsync, GetCurrentKey, GetCurrentKeyAsync |
| Read version pointer | GetCurrentVersion, GetCurrentVersionAsync |
| Write / rotate | AddKey, AddKeyAsync, AddKeyFromString, AddKeyFromStringAsync, SetCurrentVersion, SetCurrentVersionAsync, UpdateKey, UpdateKeyAsync, UpdateKeyFromString, UpdateKeyFromStringAsync |
| Existence | HasKey, HasKeyAsync |
| Metadata | GetKeyMetadata, SetKeyMetadata, async variants; GetSaltForVersion when derivation salts are tracked per version |
UpdateKey* allocates a new version (monotonic in LocalKeyStore) and sets it current—use this for rotation workflows. AddKey pins an exact **(keyId, version)
** pair—use when importing known version labels from another system.
Exceptions
Failures surface as KeyNotFoundException, InvalidKeyException, KeyVersionNotFoundException, all rooted at EncryptionKeyException. Log with keyId ( never log raw key bytes); pair with metrics so silent misconfiguration does not masquerade as “bad client data.”
Key derivation (KeyDerivation/)
HKDF (RFC 5869), PBKDF2-SHA256 helpers, and Argon2 adapters live in this assembly so onboarding UIs can derive stable bytes from passphrases consistently with **AddKeyFromString
**. Prefer SecureKeyGenerator when generating random material instead of ad-hoc RNG.
Implementations of IKeyDerivationService:
| Service | Notes |
|---|---|
Pbkdf2KeyDerivationService |
PBKDF2 (SHA-256 by default); iteration count and output length configurable. |
HkdfKeyDerivationService |
HKDF-Extract + HKDF-Expand (SHA-256 by default); ideal for deriving sub-keys from existing key material. |
Argon2KeyDerivationService |
Argon2id with configurable memory / parallelism / time-cost via constructor parameters (BouncyCastle on netstandard2.0). |
Key validation (KeyValidator)
ValidateKeyOrThrow(byte[] keyMaterial, ISymmetricKeyMaterialSize spec)— rejects null/empty buffers and key lengths that aren't in the algorithm's accepted set.IsValid(...)/TryValidate(...)— non-throwing variants for UIs that report validation failures inline.- Optional entropy/heuristic checks (e.g. all-zero buffers, repeating patterns) so that obviously bad imports fail early.
Inventory (IKeyInventoryStore)
Optional capability for admin UIs and audits: enumerate logical **keyId**s and versions. Not every production store implements full listing—probe for IKeyInventoryStore (or your cloud-specific API) before assuming discovery works.
Dependency injection
| Extension | Registers |
|---|---|
AddLocalKeyStore() |
LocalKeyStore + unkeyed IKeyStore |
AddLocalKeyStore(Action<LocalKeyStore> configure) |
Configured LocalKeyStore + unkeyed IKeyStore |
AddKeyedLocalKeyStore(string key, Action<LocalKeyStore> configure) |
Per-key LocalKeyStore + IKeyStore |
Configuration uses the configure => lambda (there is no AddLocalKeyStoreFromConfiguration). Read IConfiguration inside configure — the same pattern as other Lyo
libraries:
Example appsettings.json (values consumed manually in configure):
Local development (LocalKeyStore)
In-memory store for tests and local apps:
services.AddLocalKeyStore(ks =>
{
ks.AddKeyFromString("app", "v1", "local-dev-secret");
ks.SetCurrentVersion("app", "v1");
});
AddKeyedLocalKeyStore registers distinct LocalKeyStore instances per DI key—useful when a single process hosts multiple logical tenants if you are careful about
keyed resolution and never cross-wire IKeyStore instances.
LocalKeyStore.RemoveKey(string keyId, string version) retires a non-current version (returns false when the version doesn't exist or matches GetCurrentVersion). Combine
with SetCurrentVersion before pruning the previous current.
Production: LocalKeyStore is not durable and not audited—swap for Lyo.KeyStore.Aws, Azure Key Vault, PKCS#11, or another IKeyStore that meets your retention
and access policies.
Cloud bridge
See Lyo.KeyStore.Aws for AwsKeyStore and helpers that align with AWS Secrets Manager style payloads.
How encryption uses the store
Symmetric and envelope services resolve keyId on encrypt; ciphertext and stream headers carry keyId and version so decrypt can call GetKey(keyId, version) even after rotation. Two-key flows additionally wrap per-operation DEKs—rotation of the KEK can use ReEncryptDek patterns documented on ITwoKeyEncryptionService without re-encrypting bulk payload (see encryption README).
Operational checklist
- Thread safety — custom stores must tolerate concurrent
Get*while adminsAdd*/SetCurrentVersion. - Rotation — keep old versions until all ciphertext referencing them is re-encrypted or retired; track
GetCurrentVersionseparately from “newest encrypt version.” - Backups — database + blob snapshots do not replace key governance; export and access control live in infra policy.
- Configuration — prefer environment-specific
keyIdnamespaces (tenant:prod:comic-files) to avoid accidental cross-environment decrypt.
Dependency injection
Microsoft.Extensions.DependencyInjection.Extensions (this package): - AddLocalKeyStore() — registers a shared LocalKeyStore as IKeyStore. - AddLocalKeyStore(Action<LocalKeyStore>) — configure keys before the container finishes building. Keyed encryption registration patterns live in EncryptionServiceExtensions (for example * *AddEncryptionServiceKeyed**); see also Lyo.Encryption/README.md.
Umbrella documentation
Algorithm choice, stream formats, threat modeling, and long-form examples remain in ../README.md (folder-level encryption guide).
Dependencies
Generated from ProjectReference / PackageReference (same model as docs/Lyo.ProjectGraph.html).
Lyo.Common— (direct, lyo)Lyo.Exceptions— (direct, lyo)Konscious.Security.Cryptography.Argon21.3.1— (direct, third-party)Microsoft.Extensions.DependencyInjection.Abstractions10.0.5— (direct, microsoft, net10.0, netstandard2.0)Microsoft.Extensions.Logging.Abstractions10.0.5— (transitive, microsoft)System.Memory4.6.3— (transitive, microsoft, netstandard2.0)System.Text.Json10.0.5— (transitive, microsoft, netstandard2.0)
| 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 was computed. 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 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. |
| .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
- Konscious.Security.Cryptography.Argon2 (>= 1.3.1)
- Lyo.Common (>= 1.0.0)
- Lyo.Exceptions (>= 1.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
-
net10.0
- Konscious.Security.Cryptography.Argon2 (>= 1.3.1)
- Lyo.Common (>= 1.0.0)
- Lyo.Exceptions (>= 1.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Lyo.KeyStore:
| Package | Downloads |
|---|---|
|
Lyo.Encryption
A production-ready .NET encryption library providing secure, authenticated encryption with support for multiple algorithms (AES-GCM, ChaCha20Poly1305, RSA), key management, and envelope encryption patterns. |
|
|
Lyo.KeyStore.Aws
AWS Secrets Manager implementation of the Lyo KeyStore interface for production key management. |
|
|
Lyo.Authentication
Server-side authentication services for Lyo: Ed25519-signed JWT issuance/validation (`ILyoJwtIssuer`, `Ed25519LyoJwtIssuer`, `JwkSetBuilder`), opaque Format-B token issuance/validation/store (`IApiTokenIssuer`, `IApiTokenStore`, `ApiTokenCodec` minting/hashing), refresh-token exchange, user/external-identity stores, scope registry runtime, and audit recorder plumbing. Pure data shapes (records, claim names, format helpers, audit-event taxonomy, `Scope`) live in `Lyo.Authentication.Models` and are consumer-safe. This package brings in `Lyo.KeyStore`, `Lyo.Hashing`, and BouncyCastle — do not reference it from a Blazor WebAssembly client. |
|
|
Lyo.FileStorage.Web.Components
Reusable Blazor components for file storage workbenches: upload/save, DEK/KEK migration and rotation, metadata grid, keystore tools. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 212 | 8/16/2026 |