Lyo.KeyStore
1.0.9
dotnet add package Lyo.KeyStore --version 1.0.9
NuGet\Install-Package Lyo.KeyStore -Version 1.0.9
<PackageReference Include="Lyo.KeyStore" Version="1.0.9" />
<PackageVersion Include="Lyo.KeyStore" Version="1.0.9" />
<PackageReference Include="Lyo.KeyStore" />
paket add Lyo.KeyStore --version 1.0.9
#r "nuget: Lyo.KeyStore, 1.0.9"
#:package Lyo.KeyStore@1.0.9
#addin nuget:?package=Lyo.KeyStore&version=1.0.9
#tool nuget:?package=Lyo.KeyStore&version=1.0.9
Lyo.KeyStore
Key encryption key (KEK) storage and rotation contracts for Lyo.Encryption. Encryption services call 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 is stored.
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 methods
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. AddKey pins an exact (keyId, version) pair. Use that 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 look like 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 are configurable. |
HkdfKeyDerivationService |
HKDF-Extract + HKDF-Expand (SHA-256 by default). Derives 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 keyIds and versions. Not every store implements 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 and returns false when the version doesn't exist or matches GetCurrentVersion. Call 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 wrap per-operation DEKs. KEK rotation can use ReEncryptDek on ITwoKeyEncryptionService without re-encrypting bulk payload. See the 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 the newest encrypt version. - Backups. Database and 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 in this package: AddLocalKeyStore() registers a shared LocalKeyStore as IKeyStore. AddLocalKeyStore(Action<LocalKeyStore>) configures keys before the container finishes building. Keyed encryption registration lives in EncryptionServiceExtensions, for example AddEncryptionServiceKeyed. See also Lyo.Encryption/README.md.
Encryption guide
Algorithm choice, stream formats, threat modeling, and long-form examples remain in ../README.md, the 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.9)
- Lyo.Exceptions (>= 1.0.9)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
-
net10.0
- Konscious.Security.Cryptography.Argon2 (>= 1.3.1)
- Lyo.Common (>= 1.0.9)
- Lyo.Exceptions (>= 1.0.9)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
NuGet packages (5)
Showing the top 5 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.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.KeyStore.Aws
AWS Secrets Manager implementation of the Lyo KeyStore interface for production key management. |
|
|
Lyo.KeyStore.Web.Components
Blazor workbench for in-process IKeyStore: list ids/versions, add from string, rotate, set current. Does not expose key bytes over HTTP. |
|
|
Lyo.Api.FileStorage
HTTP API surface for Lyo file storage: file routes, stream upload, archive, and FileMetadata QueryProject. |
GitHub repositories
This package is not used by any popular GitHub repositories.